Leetcode刷题第四天:24. 两两交换链表中的节点,19.删除链表的倒数第N个节点,面试题 02.07. 链表相交,142.环形链表II

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

自己看随想录的时候感觉很简单,但是实敲的时候有好多小地方翻不清楚,所以还是看了视频。接下来是我第一次打困惑的地方,也是值得注意的地方:1、首先是便利条件,这样做是为了确保cur节点后面有两个非空节点,这样才有进行下次循环的必要;2、第二点是,cur要指向本次需要翻转的两个节点的前一个节点。并且设置两个tmp指针:

当cur指向2时就丢掉的1的地址,所以要用tmp指向1;当2指向1时就丢掉了3的地址,所以要用tmp2指向3;

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        //设置虚拟头结点
        ListNode* dummyhead = new ListNode(0, head);
        ListNode* cur = dummyhead;
        while(cur->next!=NULL&&cur->next->next!=NULL)
        {   
            ListNode* tmp = cur->next;
            ListNode* tmp1 = cur->next->next->next;
            cur->next = tmp->next;
            cur->next->next=tmp;
            tmp->next=tmp1;
            cur = cur->next->next;
        }
        ListNode* result = dummyhead->next;
        delete dummyhead;
        return result;
    }
};

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

这次依然是直接看文章,该题采用双指针的解法,快指针先移动,和慢指针之间差n个节点,然后快慢同时移动最后,这样快指针移动到空节点的时候,慢指针就指向倒数第n个节点的前一个节点,方便删除。

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        //设置虚拟头节点
        ListNode* dummyhead = new ListNode(0, head);
        ListNode* fast = dummyhead;
        ListNode* slow = dummyhead;
        while(n-- && fast != NULL) {
            fast = fast->next;
        }
        fast = fast->next; 
        while(fast!=nullptr)
        {
            fast = fast->next;
            slow = slow->next;
        }
        ListNode* tmp = slow->next;
        slow->next=slow->next->next;
        delete tmp;
        tmp = NULL;
        return dummyhead->next;
    }
};

面试题 02.07. 链表相交

这个题是找两个链表开始相交的地方。关键点是找到哪个链表更长,然后移动长链表的头节点,使其移动到和短链表头节点对其的地方,如图所示:

然后同时移动,直到找到curA和curB相同的时候。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* curA = headA;
        ListNode* curB = headB;
        int lenA=0,lenB=0;
        while(curA!=NULL)
        {
            lenA++;
            curA=curA->next;
        }
        while(curB!=NULL)
        {
            lenB++;
            curB=curB->next;
        }
        curA=headA;
        curB=headB;
        if(lenB>lenA)
        {
            swap(lenA, lenB);
            swap(curA, curB);
        }
        int cha = lenA-lenB;
        while(cha--)
        {
            curA=curA->next;
        }
        while(curA!=NULL)
        {
            if(curA==curB) return curA;
            curA=curA->next;
            curB=curB->next;
        }
        return NULL;
    }
};

142.环形链表II

这里卡哥讲了一个非常便于理解快慢指针相遇的逻辑:快指针每次移动两个节点,慢指针每次移动一个节点,快指针相当于以一个节点的速度去追慢指针!所以一定会相遇。

这个题要找环的入口,主要有两个计算,第一是计算快指针和慢指针会不会相遇;第二是计算唤醒入口的节点在哪里。前面已经讲了如何判断是否有环,接下来解决第二个问题:

如果有环,两个节点在图中相遇,此时:

fast走过的路程是:x+y+n(z+y)  n大于等于1;

slow走过的路程是:x+y

这里卡哥解释了为什么slow在环内不到一圈就能被追上。

由于fast走过的路程一定是slow的2倍,所以:x+y+n(z+y)=2(x+y)

因此:x=nz+(n-1)y=z+(n-1)(z+y)  n大于等于1

这个式子的意思是一个指针从相遇点出发,一个指针从头节点出发,一定会在入口处相遇。

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast!=NULL&&fast->next!=NULL)
        {
            fast=fast->next->next;
            slow=slow->next;
            if(fast==slow)
            {
                ListNode* index1 = head;
                ListNode* index2 = fast;
                while(index1!=index2)
                {
                    index1 = index1->next;
                    index2 = index2->next;
                }
                return index1;
            }
        }
        return NULL;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值