代码随想录算法训练营第四天 |链表剩余题目

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

题目链接
状态: 一遍过
思路: 使用虚拟节点放在开头,注意盯住三个节点的变化即可

原始代码

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if (head == nullptr || head->next == nullptr)
            return head;
        ListNode* dummynode = new ListNode(0);
        dummynode->next = head;
        ListNode *cur = head->next, *pre = head, *h = dummynode;
        while (cur != nullptr) {
            pre->next = cur->next;
            cur->next = pre;
            h->next = cur;
            h = pre;
            pre = pre->next;
            if (pre != nullptr)
                cur = pre->next;
            else break;
        }
        h = dummynode->next;
        delete dummynode;
        return h;
    }
};

改进地点:

  1. 在判断while时可以包含空节点或单一节点,统一化判断
  2. 简化每次交换中节点个数
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点
        dummyHead->next = head; // 将虚拟头结点指向head,这样方便后面做删除操作
        ListNode* cur = dummyHead,* tmp,*tmp1;
        while(cur->next != nullptr && cur->next->next != nullptr) {
            tmp = cur->next; // 记录临时节点
            tmp1 = cur->next->next->next; // 记录临时节点

            cur->next = cur->next->next;    // 步骤一
            cur->next->next = tmp;          // 步骤二
            cur->next->next->next = tmp1;   // 步骤三

            cur = cur->next->next; // cur移动两位,准备下一轮交换
        }
        cur = dummyHead->next;
        delete dummyHead;
        return cur;
    }
};

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

题目链接

状态:一遍过
思路:1.虚拟节点指向head。2. 快慢指针相隔n个节点。3. 前一个节点的后继为空,则后一个节点即为倒数第n个节点(应删除节点)的前驱节点,故直接删除即可。4.最后释放删除节点和虚拟节点内存。

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode *dummynode =new ListNode(0);
        dummynode->next=head;
        ListNode*p,*q;
        p=q=dummynode;
        while(n--){
            p=p->next;
        }
        while(p->next!=nullptr){
            p=p->next;
            q=q->next;
        }
        p=q->next;
        q->next=p->next;
        delete p;
        p=nullptr;
        q=dummynode->next;
        delete dummynode;
        return q;
    }
};

面试题 02.07. 链表相交

题目链接
状态:一遍过
思路:先计算短的链表的长度,再计算长的链表与其差值n,目的是使链表右端对齐。接着长的链表先走n个节点,两节点再携手共进,若两个指针所指的节点为同一个,则返回该该节点;否则返回空。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        int m=0,n1=0,n2=0;
        ListNode *p=headA,*q=headB;
        for(;p!=NULL&&q!=NULL;p=p->next,q=q->next,m++);
        while(p!=NULL){
            p=p->next;
            n1++;
        }
        while(q!=NULL){
            q=q->next;
            n2++;
        }
        p=headA;q=headB;
        while(n1--) p=p->next;
        while(n2--) q=q->next;
        while(q!=NULL){
            if(q==p){
                return q;
            }
            q=q->next;
            p=p->next;
        }
        return NULL;
       
    }
};

改进:看了答案的代码大为震撼
A长度为a,B长度为b,将两者末尾再接上对方的链表的头
A — A+B
B — B+A
原理都一样,若A短B长,当B走完自身长度时,A自身已经走完,且多走的距离正是B比A长的距离。这距离本应该在第二次遍历时,让B先走,因此A后接B相当于提前开启第二次遍历,当B走完时接着走A,这时的状态恰好是新一轮的B(A后的B)走了比A多的距离。在此之后携手一同向后走即可找到。
只能说牛犇,我还得练。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *A = headA, *B = headB;
        while (A != B) {
            A = A != nullptr ? A->next : headB;
            B = B != nullptr ? B->next : headA;
        }
        return A;
    }
};

142.环形链表II

题目链接
状态: 一遍过
思路:之前做过有印象,就是追问题,使用快慢指针。设表头到入口距离为x,相遇点距入口距离为a,环剩余距离为b。因为快慢指针速度为1:2,所以在慢指针进入入口后的第一圈内即可相遇,二者的走过的距离比也是1:2 =x+a:x+a+b+a,计算可得x=b,而环的长度为x+a。由此可知在相遇后从表头重新找个新指针,二者以相同的速度走,待下次相遇时所在的节点即为入口。

class Solution {
public:
    ListNode* detectCycle(ListNode* head) {
        ListNode *q = head, *p=head;
        while (p != NULL && p->next != NULL) {
            q = q->next;
            p = p->next->next;
            if (q == p) {
                p = head;
                while (q != p) {
                    q = q->next;
                    p = p->next;
                }
                return p;
            }
        }
        return NULL;
    }
};
代码随想录八股文第四版pdf》是一本关于编程的指南,旨在帮助读者提高编程技能和优化代码。本书内容丰富全面,适合广大程序员和编程爱好者阅读。 首先,本书分为多个章节,每个章节涵盖了不同的编程主题。比如,第一章讲解了基础的编程概念和语法,包括变量、循环和函数等。第二章介绍了面向对象编程(OOP)的概念和原则,如封装、继承和多态等。接下来的章节逐步介绍了数据结构算法,如数组、链表、栈和队列,以及排序和搜索算法等。此外,本书还对常见的编程问题进行了详细分析和解答,帮助读者培养解决问题的思维方式。 其次,本书的特色之一是通过八股文的形式呈现编程知识。作者以简练明了的语言,将复杂的编程概念和技巧概括成几句话,大大提高了读者的理解和记忆效果。例如,对于OOP的解释可以是:“封装数据和行为,继承通用特性,多态表现灵活性。”这种精炼的表述使得读者能够快速抓住核心要点,方便理解和运用。 此外,本书还提供了大量的实例代码和练习题,帮助读者巩固所学知识和提高编码能力。每个章节都附带了相关的代码示例,读者可以通过阅读代码和运行实验,加深对理论知识的理解。此外,练习题既可以作为学习过程中的自测工具,又可以作为深入学习和巩固知识的手段。 综上所述,《代码随想录八股文第四版pdf》是一本内容全面、形式独特的编程指南。通过阅读本书,读者可以系统学习编程知识和技巧,提高编码能力,为日后的编程工作打下坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值