目录
1 19. 删除链表的倒数第 N 个节点
2 24. 两两交换链表中的节点
3 25. K 个一组翻转链表
4 138. 随机链表的复制
菜鸟做题第三周,语言是 C++
1 19. 删除链表的倒数第 N 个节点
到底是节点还是结点。。。
解题思路:
- 设置双指针 left 和 right
- 先让 right 右移 n 格
- 再让 left 和 right 一起右移直至 right 指向 nullptr
- left 将恰好处于被删除节点的前一个节点
思路说明图:
这个虚拟节点(dummy node)的设置非常巧妙,完美处理了被删除节点是头节点的情况。
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode * dummy = new ListNode(0, head);
ListNode * left = dummy, * right = head;
for (int i = 0; i < n; ++i) {
right = right->next;
}
while (right) {
left = left->next;
right = right->next;
}
left->next = left->next->next;
return dummy->next;
}
};
虽然不设置虚拟节点(dummy node)也能做,但是写 if 语句的模样真的很狼狈。
2 24. 两两交换链表中的节点
思路很简单,一组一组地交换即可,关键在于保存需要再次使用到的节点指针。
public:
ListNode* swapPairs(ListNode* head) {
ListNode * dummy = new ListNode(0, head);
ListNode * prev = dummy, * post = nullptr;
ListNode * left = head, * right = head ? head->next : nullptr;
while (left && right) {
post = right->next;
right->next = left;
left->next = post;
prev->next = right;
prev = left;
left = post ? post : nullptr;
right = post ? post->next : nullptr;
}
return dummy->next;
}
};
说明:以下是为了防止指针越界而进行的判断
left = post ? post : nullptr;
right = post ? post->next : nullptr;
3 25. K 个一组翻转链表
是上一题的升级版。
解题思路:
- 设置 prev、left、right、temp、next 指针
- prev 用于保存上一组的尾巴
- left 用于保存当前组的头部
- right 和 temp 一起右移,对每一个指针进行反向
是不是看起来很烦,但确实可能要使用到很多指针。
我加了一个函数来判断剩余部分还能不能构成 K 个一组:
bool isEnough(ListNode * p, int k) {
int count = 0;
while (p && count < k) {
p = p->next;
++count;
}
return count == k;
}
其实思路也不难,就是容易转晕:
class Solution {
public:
bool isEnough(ListNode * p, int k) {
int count = 0;
while (p && count < k) {
p = p->next;
++count;
}
return count == k;
}
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode * dummy = new ListNode(0, head);
ListNode * left = head, * right = head->next;
ListNode * prev = dummy;
while (isEnough(left, k)) {
int count = 1;
ListNode * temp = left;
while (count < k) {
++count;
ListNode * next = right->next;
right->next = temp;
temp = right;
right = next;
}
prev->next = temp;
prev = left;
left->next = right;
left = right;
right = left ? left->next : nullptr;
}
return dummy->next;
}
};
4 138. 随机链表的复制
这道题用递归真是太神奇了,可惜我不会。。。
class Solution {
public:
unordered_map<Node *, Node *> cachedNode;
Node* copyRandomList(Node* head) {
if (head == nullptr) return nullptr;
if (!cachedNode.count(head)) {
Node * headNew = new Node(head->val);
cachedNode[head] = headNew;
headNew->next = copyRandomList(head->next);
headNew->random = copyRandomList(head->random);
}
return cachedNode[head];
}
};