代码随想录刷题笔记day4

三个指针+虚拟头结点直接秒了,时间复杂度:O(n) 空间复杂度:O(1)。中间交换指针的时候细心一点,最好画个图。

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(head !=nullptr && head->next == nullptr){
            return head; //一个结点
        }
        ListNode* H = new ListNode();//虚拟头结点
        ListNode* temp = head;
        ListNode* forward =H;//相当于双向列表
        ListNode* latter;
        while(temp != nullptr && temp->next != nullptr){
            latter = temp->next;
            temp->next = latter->next;
            latter->next =temp;
            forward->next = latter;
            forward = temp;
            temp = temp->next;
        }
        head = H->next;
        delete H;
        return head;
    }
};

我先用不带头结点的方式实现了一遍,发现当n=结点个数时需要单独讨论。这道题需要双指针让后一个指针tail先跑n步然后两个指针开始平行移动,当n=结点个数时tail跑完n步直接指向nullptr,在平行移动时在找tail->next将报错。虽然很好讨论但是考虑到手撕代码时可能会忘掉特例,不如使用虚拟头结点安全。

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* H = new ListNode();//虚拟头结点
        H->next = head;
        ListNode* tail = H;
        for(int i=0; i<n; i++){
            tail = tail->next;
        }
        ListNode* temp = H;
        while(tail->next != nullptr){//边界条件是temp的下一个即为要删除的结点
            // temp和tail平行移动
            tail = tail->next;
            temp = temp->next;
        }
        ListNode* a = temp->next;
        temp->next = a->next;
        delete a;
        head = H->next;
        delete H;
        return head;
    }
};

本题没有视频讲解,大家注意 数值相同,不代表指针相同。

题目太长了,题目链接/文章讲解:代码随想录

这个题非常好,首先是要比较的是指针是否相同,而非数值;然后是没有环就不用考虑多个交点的问题,主要是思路是先计算出长度,然后让尾结点对齐,然后再比较。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        int m = 0;//A中结点数目
        int n = 0;//B~
        for(ListNode* i = headA; i != nullptr; i = i->next){m++;}
        for(ListNode* i = headB; i != nullptr; i = i->next){n++;}
        ListNode* tempA = headA;
        ListNode* tempB = headB;
        ListNode* start = headA;//如果相交,记录相交结点,初始化为随便一个的头结点,不然在两个链表从第一个就一样时会报错
        if(m >= n){//A较长,需要先移动A的指针来保证两个链表的尾结点对齐
            for(int i = 0; i < m-n; i++){
                tempA = tempA->next;
                start = tempA;
            }
        }
        else{//B较长,需要先移动B的指针来保证两个链表的尾结点对齐
            for(int i = 0; i < n-m; i++){
                tempB = tempB->next;
                start = tempB;
            }
        }
        while(tempA != tempB && tempA != nullptr){//要比较的是指针而不是数值
            tempA = tempA->next;
            tempB = tempB->next;
            start = tempA;
        }
        if(tempA == nullptr){
            return nullptr;
        }
        else{
            return start;
        }
    }
};

算是链表比较有难度的题目,需要多花点时间理解 确定环和找环入口,建议先看视频。

题目链接/文章讲解/视频讲解:代码随想录

太nb了!!!如果是O(n)空间其实很简单,比如建一个数组储存每个结点的值,把所有遍历过的val赋成0.1,遇到0.1则遇到环,再把val根据数组还原即可。但是O(1)这个快慢指针的方法真是太优雅了,我纯抄的,就不放代码了,和链接完全一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值