• 数据结构链表力扣例题AC(2)——代码以及思路记录


    206. 反转链表

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

    AC方法1

    1. struct ListNode* reverseList(struct ListNode* head) {
    2. if(head == NULL)
    3. return NULL;
    4. struct ListNode* n1, *n2, *n3;
    5. n1 = NULL;
    6. n2 = head;
    7. n3 = head->next;
    8. while(n2)
    9. {
    10. n2->next = n1;
    11. n1 = n2;
    12. n2 = n3;
    13. if(n3)
    14. {
    15. n3 = n3->next;
    16. }
    17. }
    18. return n1;
    19. }

    代码思路

    观察示例,1->2->3->4->5 ==>> 5->4->3->2->1

    要将箭头的方向都旋转,假设从左向右改变,第一步2->1,用两个指针 n1 和 n2 分别指向1和2,使 n2 指向 n1 就可以实现了,但是此时由于 2 之前保存的 3 的地址,现在保存了 1 的地址,3 的地址丢失了,因此在实现变换前,需要先将交换的两个数字后面一位的地址也保存下来,预防这种情况的发生。因为链表的末尾是指向NULL的,因此第一个也需要变为指向NULL,所以第一步将三个指针设置为 n1 = NULL, n2 = head,n3 = head->next。考虑结束条件,如果是 n3 指向空的话,此时 n2 刚指向最后一个元素,最后一个元素依然指向NULL,因此结束条件设置为 n2 指向空更合适。改变链表方向时,将 n2 指向 n1 (n2->next = n1,改变了箭头方向),再将 n1 、n2 和 n3 向前移动(n1 = n2;n2 = n3),但是这里要考虑 n3 向前移动的特殊情况,因为结束条件是 n2 指向空(说明箭头方向都已经完成变换),但是 n2 移动到NULL之前,n3 会先指向NULL,当 n2 指向 NULL的时候,n3也跟着移动就会发生错误(NULL->next是绝对错误的),因此加一个判断,当 n3 已经为空的时候就不移动了。此时原来的最后一个元素是第一个元素,也就是该链表的地址,n1 指向他,返回 n1 地址即可。

    AC方法2

    1. struct ListNode* cur, *newhead;
    2. cur = head;
    3. newhead = NULL;
    4. while(cur)
    5. {
    6. struct ListNode* next = cur->next;
    7. cur->next = newhead;
    8. newhead = cur;
    9. cur = next;
    10. }
    11. return newhead;

    代码思路

    联想一下栈的原理,进栈和出栈是不是就顺序相反,因此可以创建一个新的空链表,从原链表第一个节点开始加入新链表,因此需要将头结点的下一个节点存储(因为头结点会保存新链表的节点地址),创建cur指向头结点,新链表由于是空,指向NULL;接着开始向新链表添加,先创建一个新指针保存cur的下一个节点(next = cur->next),然后将原链表第一个移动到新链表里面进行头插(cur->next = newhead,这一步就是相当于头插),然后更新了新链表的头结点后,对应的指向头结点的指针newhead移动指向新的头结点(newhead = cur;)cur回到原链表,指向next保存的新节点。由于cur是添加到新链表以后再回到原链表,因此当cur指向NULL的时候就可以停止了,因此作为while循环条件,最后返回新链表的头结点地址就是变换了顺序的链表的地址了。

    链表中倒数第k个结点

    输入一个链表,输出该链表中倒数第k个结点。

    AC

    1. struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
    2. // write code here
    3. struct ListNode* fast = pListHead;
    4. struct ListNode* slow = pListHead;
    5. for(int i = 0; i < k; i++)
    6. {
    7. if(fast == NULL)
    8. {
    9. return NULL;
    10. }
    11. fast = fast->next;
    12. }
    13. while(fast)
    14. {
    15. fast = fast->next;
    16. slow = slow->next;
    17. }
    18. return slow;
    19. }

    代码思路

    这道题用快慢指针的方法就非常妙,先简单说说一般思路:先创建一个指针将链表遍历一遍得出链表长度,再用链表长度减去 k 得出正数是第几个,然后输出正数的节点。

    但如果使用快慢指针:fast 指针和 slow 指针最开始都指向头结点,先让 fast 指针走 k 个节点,此时 fast 指针和 slow 指针间就有 k 个节点距离,接着让 fast 和 slow 指针同时向前走,这个过程中两个指针之间始终保持着 k 个距离,因此当 fast 指针走到最后的时候,slow 指针正好处于倒数第 k 个。不过有特殊情况需要考虑,就是如果 k 大于了链表节点数,结果是输出空指针,因此在 fast 移动的时候就去检验他会不会等于空,如果 fast 等于空了直接 return NULL,因为k大于链表节点数,那么 i 还没有大于等于 k ,fast 就已经变为 NULL 了。其次还有 k=0 的情况,这时候进不去 for 循环,但是可以进去 while 循环,也就是快慢指针同时走了,fast=NULL 的时候 slow 也为 NULL 了,最后返回 slow 也就是返回空了。

    这道题只写快慢指针的方法,有兴趣的实现第一种简单思想的,以练算法为主就不暴力了

    CM11 链表分割

    AC

    1. ListNode* partition(ListNode* pHead, int x) {
    2. struct ListNode* head1, *head2, *tail1, *tail2;
    3. head1 = tail1 = (struct ListNode*)malloc(sizeof(struct ListNode));
    4. head2 = tail2 = (struct ListNode*)malloc(sizeof(struct ListNode));
    5. struct ListNode* cur = pHead;
    6. while(cur)
    7. {
    8. if(cur->val < x)
    9. {
    10. tail1->next = cur;
    11. tail1 = tail1->next;
    12. }
    13. else{
    14. tail2->next = cur;
    15. tail2 = tail2->next;
    16. }
    17. cur = cur->next;
    18. }
    19. tail1->next = head2->next;
    20. tail2->next = NULL; //这一步不写的话会形成一个环
    21. pHead = head1->next;
    22. free(head1);
    23. free(head2);
    24. return pHead;
    25. }

    代码思路

    这段代码思路就是新建了两个链表,然后遍历一遍原链表,小于x的加入到第一个新的链表中,大于的加到另一个里边,然后把两个新链表合并起来,也就是让小于x的那个链表的尾节点指向另一个新建链表的头结点,并且大于x的那个链表的尾节点置空,返回新链表的地址。置空的原因是因为,如果不这么操作可能会形成一个环,这种情况会发生在当原链表的尾节点不是大于x的时候,那么尾节点的前一个若大于x,被分到大于x的链表的时候,他的next还未改变,仍然指向尾节点,而尾节点因为比x小而分到了小于x的那个新建链表中,因此形成了一个环。

  • 相关阅读:
    Excel管理Simulink SWC中的标定量与观测量之观测量
    Cocos Creator3.8 项目实战(五)背景无限滚屏效果如何实现
    1、5伪类选择器
    在Winform程序中动态绘制系统名称,代替图片硬编码名称
    面试中常用消息中间件对比
    单链表基本练习-删除
    Linux运维工程师面试题集锦
    时间空间复杂度
    【Java】fastjson
    谷粒商城项目总结(一)-基础篇
  • 原文地址:https://blog.csdn.net/m0_63596031/article/details/136132214