六月集训(第12天)—链表
链表
1. 328. 奇偶链表
思路:
利用两个指针,交替连接得到两个(奇偶)链表,最后将两个链表合并。
注意特判链表为空和只有一个元素的情况
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* oddEvenList(ListNode* head) {
if (head == nullptr) return nullptr; // 特判链表为空
ListNode *head1 = head;
ListNode *head2 = head->next;
if (head2 == nullptr) return head; // 特判只有一个元素
ListNode *rem_head2 = head->next;
int cnt = 1;
while (head1->next != nullptr && head2->next != nullptr) {
if (cnt & 1) {
head1->next = head2->next;
head1 = head1->next;
} else {
head2->next = head1->next;
head2 = head2->next;
}
cnt ^= 1;
}
head2->next = nullptr;
head1->next = rem_head2;
return head;
}
};
2. 725. 分隔链表
思路:
首先可以算出每个子链表需要包含多少个链结unit_len = line_len / k;,开始的几个子链表可能会多一个元素,即开始的rest(rest = line_len % k;)个元素包含unit_len + 1个元素。遍历链表,按照规定的元素个数将对应的子链表放入答案中即可。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
vector<ListNode*> splitListToParts(ListNode* head, int k) {
int line_len = 0;
int rest = 0, unit_len = 0;
vector<ListNode *> ans;
ListNode *temp_head = head;
while (temp_head) {
line_len++;
temp_head = temp_head->next;
}
unit_len = line_len / k; // 每个子链表至少包含unit_len 个元素
rest = line_len % k; // 前rest个子链表包含unit_len + 1个元素
while (head) {
ans.push_back(head);
for (int i = 1; i < unit_len; ++i) head = head->next;
if (rest && unit_len) {
head = head->next;
rest--;
}
ListNode *temp = head;
head = head->next;
temp->next = nullptr; // 尾指针置为空
}
int ans_size = ans.size();
if (ans_size < k) { /* 链表空了,需要加入空指针,让子链表的数量达到k个 */
for (int i = ans_size; i < k; ++i) ans.push_back(nullptr);
}
return ans;
}
};
3. 817. 链表组件
思路:
题意没看懂,卡了半天。先解释一下:链表中的连续子链中的每一个元素都在数组nums中,问这样的连续子链有多少个。
(1) 将nums中的每个元素建立哈希映射。
(2) 遍历链表,如果当前元素在nums中出现了,并且链表中的下一个元素也出现了,则其为连续子链的一部分,当当前元素在nums中,而其在链表中的下一个元素不在链表中,则该元素是当前连续子链的结尾,子链个数+1。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
#define maxn 10010
public:
int numComponents(ListNode* head, vector<int>& nums) {
bool vis[maxn];
int cnt = 0;
memset(vis, false, sizeof(vis));
int nums_size = nums.size();
for (int i = 0; i < nums_size; ++i) vis[ nums[i] ] = true; // (1)
while (head) { // (2)
if (vis[ head->val ] && (head->next == nullptr || !vis[ head->next->val ])) cnt++;
head = head->next;
}
return cnt;
}
};
4. 622. 设计循环队列
思路:
数组模拟循环链表。
class MyCircularQueue {
vector<int> line;
int front = 0, rear = -1;
int line_size = 0, len_limited = 0;
public:
MyCircularQueue(int k) {
for (int i = 0; i < k; ++i) line.push_back(0);
line_size = rear - front + 1;
len_limited = k;
}
bool enQueue(int value) {
if (isFull()) return false;
line_size++;
rear++;
if (rear >= len_limited - 1) rear %= len_limited;
line[rear] = value;
return true;
}
bool deQueue() {
if (isEmpty()) return false;
line_size--;
front++;
if (front >= len_limited - 1) front %= len_limited;
return true;
}
int Front() {
if (isEmpty()) return -1;
return line[front];
}
int Rear() {
if (isEmpty()) return -1;
return line[rear];
}
bool isEmpty() {
return line_size == 0;
}
bool isFull() {
return line_size == len_limited;
}
};
/**
* Your MyCircularQueue object will be instantiated and called as such:
* MyCircularQueue* obj = new MyCircularQueue(k);
* bool param_1 = obj->enQueue(value);
* bool param_2 = obj->deQueue();
* int param_3 = obj->Front();
* int param_4 = obj->Rear();
* bool param_5 = obj->isEmpty();
* bool param_6 = obj->isFull();
*/
东方欲晓,莫道君行早。

浙公网安备 33010602011771号