• 链表OJ题+牛客题


    目录

    206.反转链表

    876.链表的中间节点

    链表中倒数第k个节点

    CM11链表分割

    OR36 链表的回文


    206.反转链表

    给你单链表的头节点head,请你反转链表,并返回反转后的链表。

     实现如下结果:

            

     思路:

    取链表中的节点头插:

    代码:

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * struct ListNode *next;
    6. * };
    7. */
    8. struct ListNode* reverseList(struct ListNode* head){
    9. struct ListNode *cur=head;
    10. struct ListNode *plist=NULL;
    11. while(cur)
    12. {
    13. struct ListNode *next=cur->next;
    14. cur->next=plist;//cur->next指向plist的地址
    15. plist=cur; //plist 指向cur的地址,刚上面的一行代码和这一行代码使得链表的空间相连
    16. cur =next;
    17. }
    18. return plist;
    19. }/**
    20. * Definition for singly-linked list.
    21. * struct ListNode {
    22. * int val;
    23. * struct ListNode *next;
    24. * };
    25. */
    26. struct ListNode* reverseList(struct ListNode* head){
    27. struct ListNode *cur=head;
    28. struct ListNode *plist=NULL; //作为新的头节点
    29. while(cur)
    30. {
    31. struct ListNode *next=cur->next; //记住cur的下一个节点
    32. cur->next=plist;// 头插
    33. plist=cur; //换头
    34. cur =next; //将原来cur->next节点的地址赋给cur
    35. }
    36. return plist;
    37. }

    876.链表的中间节点

    给定一个头节点为head的非空单链表,返回链表的中间节点。如果有两个中间节点,则返回第二个中间节点。要求只能遍历一遍

    思路:用快慢指针找到中间节点,定义两个结构体变量指针slow,fast。

    slow每次走一步,fast每次走两步。当fast->next为空的时候,则链表长度为奇数,那么slow就是中间节点;当fast为空时,链表的长度为偶数,那么中间节点有两个,则返回第二个中间节点。

    代码:

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

    链表中倒数第k个节点

    输入一个链表,输出该链表中第k个节点

    思路:定义结构体指针变量slow,fast,让fast先走k部,然后它们都各自每次向后走一步,当fast为空的时候,返回slow,此时slow就为链表中第k个节点。也可以让fast先走k-1步,当fast->next为空的时候,slow就是链表中第k个节点。

    在这里需要注意的就是要注意k的值是否大于链表的长度,如果大于则返回NULL.

     代码:

    1. struct ListNode*FindKthToTail(struct ListNode*pListHead,int k)
    2. {
    3. struct ListNode*fast,slow;
    4. fast=slow=pListHead;
    5. while(k--)//让fast先走k步
    6. {
    7. //链表可能没有k步长
    8. if(fast==NULL)
    9. {
    10. return NULL;
    11. }
    12. fast=fast->next;
    13. }
    14. while(fast)//当fast为空
    15. {
    16. fast=fast->next;
    17. slow=slow->next;
    18. }
    19. return slow;
    20. }

    CM11链表分割

    描述:

    现有一链表头指针为LinstNode* pHead,给一定值x,编写一段代码将所有小于x的节点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表头指针。

    思路:

    这道题用带哨兵位的链表求解,将所有小于x的节点尾插到第一个哨兵位节点后面;其余的尾插到第二个带哨兵位节点后面;最后将两个链表链接,返回第一个哨兵位节点后一个节点。

    这里需要注意的是,在最后尾插结束时记得将第二个链表的尾节点的下一个节点置空(即上图的greaterTail的下一个节点置空),因为尾插结束,greaterTail->next还指向链表中的其他节点,如果不置空,会形成环。

     

    代码: 

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

    OR36 链表的回文

    描述:

    对于一个链表,请设计时间复杂度为O(n),空间复杂度为O(1)的算法,判断其是否为回文结构。

    给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900.

     思路:将链表的后半部分的节点逆置,再将前半部分的值和后半部分的值相比。因为额外的空间复杂度为O(1),所以不能整体逆置,整体逆置要重新开辟一个和原来一样长的链表空间。所以这里将后半部分的节点逆置之后就可以比较了。

    代码:

    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* middle(struct ListNode* phead) //返回中间值
    10. {
    11. struct ListNode*fast,*slow;
    12. fast=slow=phead;
    13. while(fast&&fast->next)
    14. {
    15. slow=slow->next;
    16. fast=fast->next->next;
    17. }
    18. return slow;
    19. }
    20. struct ListNode*reverse(struct ListNode*phead)
    21. {
    22. struct ListNode*cur=phead;
    23. struct ListNode*rehead=NULL;
    24. while(cur)
    25. {
    26. struct ListNode*next=cur->next;
    27. //头插
    28. cur->next=rehead;
    29. rehead=cur;
    30. cur=next;
    31. }
    32. return rehead;
    33. }
    34. bool chkPalindrome(ListNode* A)
    35. {
    36. struct ListNode*mid=middle(A);
    37. struct ListNode*rehead=reverse(mid);
    38. while(A && rehead)
    39. {
    40. if(A->val!=rehead->val)
    41. return false;
    42. A=A->next;
    43. rehead=rehead->next;
    44. }
    45. return true;
    46. // write code here
    47. }
    48. };

  • 相关阅读:
    uniapp 手写 简易 时间轴 组件
    【python】Conda强大的包/环境管理工具
    CH455G驱动数码管
    (项目)ZHUZHU新闻
    2022年全球市场品牌保护和安全标签总体规模、主要生产商、主要地区、产品和应用细分研究报告
    开关量8入4出,高速以太网通讯Socket自由协议远程IO模块 YJ94
    ubuntu20环境搭建+Qt6安装
    React插槽
    矩阵置零00
    【Android】内存泄露 使用 LeakCanary 应当如何应对?最全的解决
  • 原文地址:https://blog.csdn.net/weixin_53269843/article/details/127963267