• 链表Oj练习题 纯C语言


    目录

    链表分割

    链表的回文结构

    相交链表

    环形链表

    环形链表 II


    链表分割

    链表分割

     思路:

    1. 遍历原链表
    2. 把>=×的插入到一个链表
    3. 链表1和链表2链接起来

    假设链表为3 5 1 6 3 4

    则分为: 3 1 3       5 6 4

    之后相连即可

    魔鬼细节:如图所示,如果6是大链的最后一个数,那么greaterTail->next仍然指向3,会成环

    所以需要greaterTail->next=NULL;  防止死循环

    1. /*
    2. struct ListNode {
    3. int val;
    4. struct ListNode *next;
    5. ListNode(int x) : val(x), next(NULL) {}
    6. };*/
    7. class Partition {
    8. public:
    9. ListNode* partition(ListNode* pHead, int x) {
    10. struct ListNode*lessHead,*lessTail,*greaterHead,*greaterTail;
    11. lessHead=lessTail=(struct ListNode*)malloc(sizeof(struct ListNode));
    12. greaterHead=greaterTail=(struct ListNode*)malloc(sizeof(struct ListNode));
    13. lessTail->next=greaterTail->next=NULL;
    14. struct ListNode* cur=pHead;
    15. while(cur){
    16. if(cur->val
    17. {
    18. lessTail->next=cur;
    19. lessTail=lessTail->next;
    20. }
    21. else
    22. {
    23. greaterTail->next=cur;
    24. greaterTail=greaterTail->next;
    25. }
    26. cur=cur->next;
    27. }
    28. lessTail->next=greaterHead->next;
    29. greaterTail->next=NULL; //致命细节
    30. struct ListNode* list=lessHead->next;
    31. return list;
    32. }
    33. };

    链表的回文结构

    链表的回文结构

     思路:用快慢指针找到中间节点,再用链表反转反转中间节点后的链表,将链表和反转的链表一一对比即可

    1. /*
    2. struct ListNode {
    3. int val;
    4. struct ListNode *next;
    5. ListNode(int x) : val(x), next(NULL) {}
    6. };*/
    7. class PalindromeList {
    8. public:
    9. struct ListNode* middleNode(struct ListNode*head)
    10. {
    11. struct ListNode*slow,*fast;
    12. slow=fast=head;
    13. while(fast&&fast->next)
    14. {
    15. slow=slow->next;
    16. fast=fast->next;
    17. }
    18. return slow;
    19. }
    20. struct ListNode*reverse(struct ListNode*head)
    21. {
    22. struct ListNode*newHead=NULL;
    23. struct ListNode*cur=head;
    24. while(cur)
    25. {
    26. struct ListNode*next=cur->next;
    27. cur->next=newHead;
    28. newHead=cur;
    29. cur=next;
    30. }
    31. return newHead;
    32. }
    33. bool chkPalindrome(ListNode* A)
    34. {
    35. struct ListNode* mid=middleNode(A); //快慢指针
    36. struct ListNode* rHead=reverse(mid); //链表反转
    37. while(A&&rHead)
    38. {
    39. if(A->val==rHead->val) //一一对比
    40. {
    41. A=A->next;
    42. rHead=rHead->next;
    43. }
    44. else
    45. {
    46. return false;
    47. }
    48. }
    49. return true;
    50. }
    51. };

    相交链表

    相交链表

    思路:(让两链表长度相等)算出链A与链B的长度并相减得到相差长度,用长链表减去相差长度;将链表指针一一对比即可

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * struct ListNode *next;
    6. * };
    7. */
    8. struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    9. struct ListNode* tailA=headA,*tailB=headB;
    10. int lenA=1,lenB=1;
    11. while(tailA->next)
    12. {
    13. tailA=tailA->next;
    14. lenA++;
    15. }
    16. while(tailB->next)
    17. {
    18. tailB=tailB->next;
    19. lenB++;
    20. }
    21. if(tailA!=tailB)
    22. {
    23. return NULL; //若尾链都不相等,则不相交
    24. }
    25. struct ListNode*shortList=headA,*longList=headB;
    26. if(lenA>lenB)
    27. {
    28. longList=headA;
    29. shortList=headB;
    30. }
    31. int x=abs(lenB-lenA);
    32. while(x--)
    33. {
    34. longList=longList->next;
    35. }
    36. while(shortList&&longList)
    37. {
    38. if(shortList==longList)
    39. return shortList;
    40. shortList=shortList->next;
    41. longList=longList->next;
    42. }
    43. return NULL;
    44. }

    环形链表

    环形链表 II

     思路:用快慢指针,为了保证一定能追到并相遇,快指针与漫指针的差为1

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * struct ListNode *next;
    6. * };
    7. */
    8. bool hasCycle(struct ListNode *head) {
    9. struct ListNode*slow=head,*fast=head;
    10. while(fast&&fast->next)
    11. {
    12. slow=slow->next;
    13. fast=fast->next->next;
    14. if(slow==fast)
    15. return true;
    16. }
    17. return false;
    18. }

    环形链表 II

    环形链表 II

    思路:数学证明

    • L很小,C很大,slow进环前,fast可能在环里面,一圈都没走完
    • L很大,C很小,slow进环前,fast在环里面走了很多圈了
    • 但是slow进环以后,在一圈之内,fast一定追上slow因为slow进环以后,他们之间距离最多是C-1
       

    设从头节点到环的入口点的步数为L,环的长度为C。

    假设环入口点走X步快慢指针相遇了。

    可得出:

    慢指针走的路程为:L+X。

    快指针走的路程为:L+X+C*N(其中N代表圈数,N>=1)。

    快指针路程是慢指针路程的两倍

    所以:L+X+C*N=2*(L+X)。

    化简得:L=C*N-X

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

    因此我们只需要让一个指针从head走,另一个指针从meet走,当两指针相等时,它们就指向环的入口点

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * struct ListNode *next;
    6. * };
    7. */
    8. struct ListNode *detectCycle(struct ListNode *head) {
    9. struct ListNode*slow=head,*fast=head;
    10. while(fast&&fast->next)
    11. {
    12. slow=slow->next;
    13. fast=fast->next->next;
    14. if(slow==fast)
    15. {
    16. struct ListNode*meet=slow;
    17. while(meet!=head)
    18. {
    19. meet=meet->next;
    20. head=head->next;
    21. }
    22. return meet;
    23. }
    24. }
    25. return NULL;
    26. }

  • 相关阅读:
    allegro中shape的一些基本操作(三)——挖空铜皮(shape)、删除孤岛
    Linux篇---第二篇
    MAVEN学习笔记
    react获取input值
    Python中的@dataclass装饰器
    Clickhouse on S3 部署方案
    element-plus布局排版问题总结(更新ing)
    算法: 求数幂n次方50. Pow(x, n)
    JVM:(八)运行时数据区之方法区
    母线电容及其计算方法
  • 原文地址:https://blog.csdn.net/qq_61386381/article/details/124711796