当前位置:   article > 正文

Leetcode刷题——单链表2_fast && fast->next

fast && fast->next

目录

练习题1 链表分割

练习题2 链表的回文结构 

练习题3 链表相交 

练习题4 判断是否为环形链表 

快慢指针延伸问题 

 练习题5 找环形链表的节点

 练习题6 复制带随机指针的链表


练习题1 链表分割

点击跳转

 思路:

将链表一分为2,以x为界限,大于x的尾插到新链表1,小于x的尾插到新链表2

,之后再将新链表1,头插到新链表2,跟归并排序有点像

  1. class Partition {
  2. public:
  3. ListNode* partition(ListNode* pHead, int x) {
  4. ListNode*Guard1=(ListNode*)malloc(sizeof(ListNode));
  5. ListNode*Guard2=(ListNode*)malloc(sizeof(ListNode));
  6. ListNode*tail1=Guard1;
  7. ListNode*tail2=Guard2;
  8. while(pHead)
  9. {
  10. if(pHead->val<x)
  11. {
  12. tail1->next=pHead;
  13. tail1=tail1->next;
  14. }
  15. else
  16. {
  17. tail2->next=pHead;
  18. tail2=tail2->next;
  19. }
  20. pHead=pHead->next;
  21. }
  22. tail1->next=Guard2->next;
  23. tail2->next=NULL;
  24. free(Guard2);
  25. return Guard1->next;
  26. }
  27. };

练习题2 链表的回文结构 

思路:

1.先找到中间节点 

2.从中间节点一直到末尾节点内的节点进行逆置

3. 用俩个节点分别指向头和中间位置,然后挨个进行数字比较,若不想等,直接退出

 注:当奇数时候,第一个2,仍然指向3,因此判断相等

  1. struct ListNode* middleNode(struct ListNode* head){
  2. struct ListNode*fast,*slow;
  3. fast=slow=head;
  4. while(fast&&fast->next)
  5. {
  6. fast=fast->next->next;
  7. slow=slow->next;
  8. }
  9. return slow;
  10. }
  11. struct ListNode* reverseList(struct ListNode* head){
  12. struct ListNode*cur=head;
  13. struct ListNode*prve=NULL;
  14. while(cur)
  15. {
  16. struct ListNode*t=cur->next;
  17. cur->next=prve;
  18. prve=cur;
  19. cur=t;
  20. }
  21. return prve;
  22. }
  23. class PalindromeList {
  24. public:
  25. bool chkPalindrome(ListNode* A) {
  26. ListNode*mid=middleNode(A);
  27. struct ListNode*rmid=reverseList(mid);
  28. while(A&&rmid)
  29. {
  30. if(A->val!=rmid->val)
  31. return false;
  32. else
  33. {
  34. rmid=rmid->next;
  35. A=A->next;
  36. }
  37. }
  38. return true;
  39. }
  40. };

 方法二:临时拷贝一份,然后一个一个比较

练习题3 链表相交 

160. 相交链表 - 力扣(LeetCode)

 相交链表特点:最后一个节点的地址相等

 方法:1.求俩个出链表的长度,即让俩个链表都走到尾节点

            2.求出他们的距离差d

            3.较长的链表先走d步,然后俩个链表开始一起走,每次走一步

  1. struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
  2. struct ListNode *newhead1=headA;
  3. struct ListNode *newhead2=headB;
  4. int k=1;int z=1;int c=0;
  5. while(newhead1->next)
  6. {
  7. newhead1=newhead1->next;
  8. k++;
  9. }
  10. while(newhead2->next)
  11. {
  12. newhead2=newhead2->next;
  13. z++;
  14. }
  15. if(newhead1!=newhead2)
  16. return NULL;
  17. c=abs(k-z);
  18. while(c--)
  19. {
  20. if(k>z)
  21. headA=headA->next;
  22. else
  23. headB=headB->next;
  24. }
  25. while(headA&&headB)
  26. {
  27. if(headA==headB)
  28. return headA;
  29. else
  30. {
  31. headA=headA->next;
  32. headB=headB->next;
  33. }
  34. }
  35. return NULL;
  36. }
  1. struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
  2. struct ListNode *newhead1=headA;
  3. struct ListNode *newhead2=headB;
  4. int k=1;int z=1;
  5. while(newhead1->next)
  6. {
  7. newhead1=newhead1->next;
  8. k++;
  9. }
  10. while(newhead2->next)
  11. {
  12. newhead2=newhead2->next;
  13. z++;
  14. }
  15. if(newhead1!=newhead2)
  16. return NULL;
  17. int gap=abs(k-z);
  18. struct ListNode *Longlist=headA;
  19. struct ListNode *ShoreList=headB;
  20. if(k<z)
  21. {
  22. Longlist=headB;
  23. ShoreList=headA;
  24. }
  25. while(gap--)
  26. {
  27. Longlist=Longlist->next;
  28. }
  29. while(Longlist!=ShoreList)
  30. {
  31. Longlist=Longlist->next;
  32. ShoreList=ShoreList->next;
  33. }
  34. return Longlist;
  35. }

练习题4 判断是否为环形链表 

141. 环形链表 - 力扣(LeetCode)

 带环链表:1.不能遍历,会陷入死循环

利用快慢指针,快指针一次走俩步,慢指针走一步

 当slow走到中间位置时,fast进入环内

当慢指针进环时,快指针在环内已经走了一小会了,具体走到了哪里,无法知晓 (要根据环的大小决定),但是可以知道fast在环里走的路程,是slow从中间到进环路程的2倍

slow进入环后,看作是fast追赶slow

假设在红色位置fast追上了slow

  1. bool hasCycle(struct ListNode *head) {
  2. struct ListNode *fast=head;
  3. struct ListNode *slow=head;
  4. while(fast&&fast->next)
  5. {
  6. fast=fast->next->next;
  7. slow=slow->next;
  8. if(slow==fast)
  9. return true;
  10. }
  11. return false;
  12. }

快慢指针延伸问题 

 

 证明:slow走一步,fast走俩步,fast能追上slow

假设:slow进环以后,fast和slow之间的差距是N,即追赶距离为N

 slow和fast每移动一次,他们的距离会缩小一格

因此距离由:N,N-1,N-2,N-3……0

所以,能追上

证明:slow走一步,fast走三部,能否追得上

假设:slow进环以后,fast和slow之间的差距是N,即追赶距离为N

一开始fast在3,slow进入圆环

 slow和fast每移动一次,他们的距离会缩小2格,他们的距离N=9

 

此时距离是-1,-1意味着,他们之间的距离变成了C-1(C是环的长度)

最终距离是0还是其他数字,由N决定

如果N是奇数,N=9

9,7,5,3,1,-1

-1意味着,他们之间的距离变成了C-1(C是环的长度)

如果C-1是偶数,即他们的距离是偶数每次-2,一定追得上,如果C-1是奇数,又得去判断下一次C-1是偶数还是奇数

因此,能否追的上如果距离是偶数,则追得上

      如果距离是奇数,得看C-1是否为偶

 练习题5 找环形链表的节点

142. 环形链表 II - 力扣(LeetCode)

 方式1.公式证明

用快慢指针:fast走的距离=2*slow的距离

公式推导

假设进环前的长度L,假设环的长度C,入口点到相遇点距离x

 slow所走距离:L+X,慢指针所走的距离不可能超过一圈,因为N最大是C-1

fast所走距离:L+NC+X,N代表fast走过的圈数,N>=1

2(L+X)=L+X+NC

(L+X)=NC

L=NC-X

L=(N-1)*C+C-X

左边是A所走距离,右边是B所走距离

可证明:一个指针A从头开始走,另一个指针B从相遇点开始走,最终会在入口点相遇

  1. struct ListNode* detectCycle(struct ListNode* head) {
  2. struct ListNode* slow = head;
  3. struct ListNode* fast = head;
  4. struct ListNode* meetnextl =NULL;
  5. while (fast && fast->next)
  6. {
  7. slow = slow->next;
  8. fast = fast->next->next;
  9. if (fast == slow)
  10. {
  11. meetnextl = fast;
  12. while(head!=meetnextl)
  13. {
  14. meetnextl=meetnextl->next;
  15. head=head->next;
  16. }
  17. return head;
  18. }
  19. }
  20. return NULL;
  21. }

方法2:转换成相交问题

fast旁白的黑色是相遇点,下面蓝色是相遇点的下一个点,A和B链表的交点,就是入口点 ,

然后让长的先走,接着同时走,跟上面的题一样

  1. struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
  2. struct ListNode *newhead1=headA;
  3. struct ListNode *newhead2=headB;
  4. int k=1;int z=1;
  5. while(newhead1->next)
  6. {
  7. newhead1=newhead1->next;
  8. k++;
  9. }
  10. while(newhead2->next)
  11. {
  12. newhead2=newhead2->next;
  13. z++;
  14. }
  15. if(newhead1!=newhead2)
  16. return NULL;
  17. int gap=abs(k-z);
  18. struct ListNode *Longlist=headA;
  19. struct ListNode *ShoreList=headB;
  20. if(k<z)
  21. {
  22. Longlist=headB;
  23. ShoreList=headA;
  24. }
  25. while(gap--)
  26. {
  27. Longlist=Longlist->next;
  28. }
  29. while(Longlist!=ShoreList)
  30. {
  31. Longlist=Longlist->next;
  32. ShoreList=ShoreList->next;
  33. }
  34. return Longlist;
  35. }
  36. struct ListNode *hasCycle(struct ListNode *head) {
  37. struct ListNode *fast=head;
  38. struct ListNode *slow=head;
  39. while(fast&&fast->next)
  40. {
  41. fast=fast->next->next;
  42. slow=slow->next;
  43. if(slow==fast)
  44. return slow;
  45. }
  46. return fast;
  47. }
  48. struct ListNode* detectCycle(struct ListNode* head) {
  49. struct ListNode* guard1 = hasCycle(head);
  50. if(guard1==NULL)
  51. return NULL;
  52. struct ListNode*fast=head;
  53. struct ListNode*slow=head;
  54. struct ListNode* meetnextl =NULL;
  55. while (fast && fast->next)
  56. {
  57. slow = slow->next;
  58. fast = fast->next->next;
  59. if (fast == slow)
  60. {
  61. meetnextl = fast->next;
  62. fast->next=NULL;
  63. struct ListNode* guard2 = getIntersectionNode(head, meetnextl);
  64. return guard2;
  65. }
  66. }
  67. return NULL;
  68. }

 练习题6 复制带随机指针的链表

138. 复制带随机指针的链表 - 力扣(LeetCode)

 思路:

1.先拷贝各个节点,插到相对应的节点后面,然后将链表连接起来

 2.然后将cur的random所指指针赋值给copy的random

if(cur->random!=NULL)

copy->random=cur->random->next

3.将各节点拷贝下来进行链接,顺便链接原链表

  1. * struct Node {
  2. * int val;
  3. * struct Node *next;
  4. * struct Node *random;
  5. * };
  6. */
  7. struct Node* copyRandomList(struct Node* head) {
  8. struct Node*cur=head;
  9. struct Node* next=NULL;
  10. struct Node*copy=NULL;
  11. while(cur)
  12. {
  13. //1.拷贝一份插入链表内
  14. copy=(struct Node*)malloc(sizeof( struct Node));
  15. next=cur->next;
  16. copy->val=cur->val;
  17. cur->next=copy;
  18. copy->next=next;
  19. cur=next;
  20. }
  21. cur=head;
  22. while(cur)
  23. { //2.链接random
  24. copy=cur->next;
  25. if(cur->random==NULL)
  26. copy->random=NULL;
  27. else
  28. copy->random=cur->random->next;
  29. cur=cur->next->next;
  30. }
  31. cur=head;
  32. struct Node*newhead=NULL;
  33. struct Node*tail=NULL;
  34. while(cur)
  35. {
  36. copy=cur->next;
  37. next=copy->next;
  38. if(newhead==NULL)
  39. newhead=tail=copy;
  40. else
  41. {
  42. tail->next=copy;
  43. tail=tail->next;
  44. }
  45. cur->next=next;
  46. cur=next;
  47. }
  48. return newhead;
  49. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/422126
推荐阅读
相关标签
  

闽ICP备14008679号