飞道的博客

代码随想录算法训练营第四天|24. 两两交换链表中的节点 、19.删除链表的倒数第N个节点、160.链表相交、142.环形链表II

324人阅读  评论(0)

24. 两两交换链表中的节点

力扣题目链接(opens new window)

解析:

基础题,主要是要把握边界条件:由题可得,交换的节点两两一组,每交换完成一对,问题规模减2,也就是只剩一个或不剩节点时交换便结束

在这里,我们引入一个虚拟头节点,这样所有的交换操作便得到统一。

每一对节点交换一次,不开辟额外空间,因此时间复杂度O(n),空间复杂度O(1)


   
  1. class Solution {
  2. public:
  3. ListNode* swapPairs(ListNode* head) {
  4. ListNode* dummy_head = new ListNode( -1, head); //虚拟头节点
  5. if(head == nullptr || head->next == nullptr) return head; //边界条件先判断
  6. ListNode* cur2 = head->next;
  7. ListNode* cur1 = head;
  8. ListNode* pre = dummy_head; //两个需要交换的节点,及前节点,共三个节点
  9. while(cur1 && cur2){
  10. cur1->next = cur2->next;
  11. cur2->next = cur1;
  12. pre->next = cur2;
  13. pre = cur1;
  14. if(cur1->next && cur1->next->next){ //若只剩1个或不剩 则退出交换
  15. cur2 = cur1->next->next;
  16. cur1 = cur1->next;
  17. }
  18. else {
  19. break;
  20. }
  21. }
  22. head = dummy_head->next; //头节点还原
  23. delete dummy_head;
  24. return head;
  25. }
  26. };

19.删除链表的倒数第N个节点

力扣题目链接

解析:

本题以普通办法处理的话就是先遍历一遍,确定链表长度,再遍历一遍,实施删除。虽然不会到O(n^2)的复杂度,仍为线性,但是连续遍历两遍不免让人觉得不快。

因此此类问题,同样可以借鉴双指针法,一前一后不回溯的遍历链表,让前后指针距离保持 n 的距离,那么当后指针到达链表尾的时候,我们自然而然可以靠前指针确定删除位置,且该算法只需一遍遍历。


   
  1. /**
  2. * Definition for singly-linked list.
  3. * struct ListNode {
  4. * int val;
  5. * ListNode *next;
  6. * ListNode() : val(0), next(nullptr) {}
  7. * ListNode(int x) : val(x), next(nullptr) {}
  8. * ListNode(int x, ListNode *next) : val(x), next(next) {}
  9. * };
  10. */
  11. class Solution {
  12. public:
  13. ListNode* removeNthFromEnd(ListNode* head, int n) {
  14. ListNode* dummy_head = new ListNode( -1,head);
  15. ListNode* p = dummy_head;
  16. ListNode* q = dummy_head;
  17. int kick_off = 0;
  18. while(kick_off < n && p->next){ //先让p指针先行,确定q指针何时行动
  19. p = p->next;
  20. kick_off++;
  21. }
  22. while(p->next){ //同步行动,直至p指针到最后一个节点,q指针离p n 个位置远
  23. p = p->next;
  24. q = q->next;
  25. }
  26. ListNode *tmp = q->next;
  27. q->next = q->next->next; //实施删除
  28. if(dummy_head->next){ //判断一下是否链表就一个节点,且已被删除
  29. head = dummy_head->next;
  30. }
  31. else{
  32. head = nullptr;
  33. }
  34. delete tmp; // 回收要删除的节点
  35. delete dummy_head; //回收虚拟头
  36. return head;
  37. }
  38. };

160.链表相交

力扣题目链接(opens new window)

解析:

这道题需要巧妙利用到一个思维,也就是链表尾对齐的思维。

如图:若两个链表有相交点,则该交点后的节点均为同一个节点,也就是它们是尾部相等的。所以如果我们能找到长表较之于短表表头的中间位置(等长的位置),然后顺序同步一对一对节点的比较是否相等,便能找到第一个相同的节点,且时间复杂度能控制在O(m+n)。


   
  1. /**
  2. * Definition for singly-linked list.
  3. * struct ListNode {
  4. * int val;
  5. * ListNode *next;
  6. * ListNode(int x) : val(x), next(NULL) {}
  7. * };
  8. */
  9. class Solution {
  10. public:
  11. ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
  12. ListNode* qq = headA;
  13. int lenA = 1;
  14. int lenB = 1;
  15. ListNode* pp = headB;
  16. while(qq->next){ //计算A的长度
  17. qq = qq->next;
  18. lenA++;
  19. }
  20. while(pp->next){ //计算B的长度
  21. pp = pp->next;
  22. lenB++;
  23. }
  24. ListNode* q = headA;
  25. ListNode* p = headB;
  26. if(lenA < lenB){ // 让q指向较长的链表的表头
  27. int tmp = lenA;
  28. ListNode* _tmp = q;
  29. lenA = lenB;
  30. lenB = tmp;
  31. q = p;
  32. p = _tmp;
  33. }
  34. int offset = lenA - lenB;
  35. while(offset > 0 ){ //想象两个不等长的链表,由末尾对齐,将较长的链表的指针遍历到与较短的链表表头节点对齐
  36. q = q->next;
  37. offset--;
  38. }
  39. while(q != p && q){ //开始判等
  40. q = q->next;
  41. p = p->next;
  42. }
  43. return q;
  44. }
  45. };

142.环形链表II

力扣题目链接

解析:

该题涉及到一个数学推理,详情见卡哥:代码随想录


   
  1. /**
  2. * Definition for singly-linked list.
  3. * struct ListNode {
  4. * int val;
  5. * ListNode *next;
  6. * ListNode(int x) : val(x), next(NULL) {}
  7. * };
  8. */
  9. class Solution {
  10. public:
  11. ListNode *detectCycle(ListNode *head) {
  12. ListNode* p = head;
  13. ListNode* q = head;
  14. while( q && q->next){
  15. p = p->next;
  16. q = q->next->next;
  17. if(p == q){
  18. ListNode* pp = head;
  19. ListNode* qq = q;
  20. while(pp != qq){
  21. pp = pp->next;
  22. qq = qq->next;
  23. }
  24. return qq;
  25. }
  26. }
  27. return NULL;
  28. }
  29. };


转载:https://blog.csdn.net/sunnanhunan/article/details/128506857
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场