代码随想录训练营第四天任务--链表part02

 

任务列表

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

 交换整个链表中前后两个节点,不能只交换数据,而是将节点前后指向交换。本题思路就是首先交换前后两个节点数据,这里用1,2,3,4表示交换的两个节点2,3和两个节点之前的一个节点1,和之后的一个节点4,让1节点next指向3,然后让3指向2,最后让2指向4即可,这个过程中Cur表示第一个节点,需要保存2和4的地址。操作完成后将Cur向后移两位,遍历链表,条件是两个节点都不指向NULL。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummyHead=new ListNode(0);
        dummyHead->next=head;
        ListNode* Cur=dummyHead;
        while(Cur->next!=NULL&&Cur->next->next!=NULL)
        {
            ListNode* Temp=Cur->next;
            ListNode* Temp1=Temp->next->next;
            Cur->next=Cur->next->next;
            Cur->next->next=Temp;
            Cur->next->next->next=Temp1;
            Cur=Cur->next->next;
        }
        return dummyHead->next;
    }
};

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

本题思路就是快速找到倒数第N个节点,如果只用一个指针遍历节点需要回溯才能找到倒数第N个节点,我们可以通过双指针的方法,让快节点先指向第N个节点,慢节点指向第一个节点,后遍历节点直至快节点指向NULL,此时,慢节点就是倒数第N个节点,注意的是,删除倒数第N个节点,是在第N+1个节点操作,只需快节点在遍历前多走一步即可在遍历结束时使慢节点指向倒数第N+1个节点,然后将倒数第N+1节点指向倒数第N-1节点即可删除链表倒数第N个节点。

 

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummyhead=new ListNode(0);
        dummyhead->next=head;
        ListNode* FaIndex=dummyhead,*SlIndex=dummyhead;
        while(n--&&FaIndex!=NULL)
        {
            FaIndex=FaIndex->next;
        }
        FaIndex=FaIndex->next;
        while(FaIndex!=NULL)
        {
            SlIndex=SlIndex->next;
            FaIndex=FaIndex->next;
        }
        if(SlIndex->next!=NULL)
        SlIndex->next=SlIndex->next->next;
        return dummyhead->next;
    }
};

 面试题 02.07. 链表相交

思路一 

求两个链表相交的起始点,如果不相交返回NULL。本题思路就是两个链表中,如果相交部分,相交的部分是一样的且在链表后面部分,所以我们不能从起始位置开始比较(可能会错过),我们先把链表尾部对齐,具体实现就是先求两链表长度,然后大的链表从两个链表长度差值开始遍历,小的链表从起始位置同时开始遍历,遇到节点相同时返回即可,直至最后指向null返回null即可。

代码随想录训练营第四天任务--链表part02_第1张图片 

思路二

本题我也想了第二种思路,本题的关键就是需要尾部对齐,从尾部开始比较,但是链表只能从头部开始遍历,所以我们可以采用两个栈分别存放链表节点位置,由于其先进后出的特性,两个栈的顶部是其对应链表最后一个节点指针,所以从栈的顶部开始比较,如果第一个不同就是无相交,返回null即可,如果相同继续出栈比较,用一个变量保存相同时的地址即可,直至出栈时两地址不同,说明此时不相交了,返回上一次相同的地址即可。 

/**
 * 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* NodeA=headA;
        ListNode* NodeB=headB;
        int lenA=0,lenB=0;
        while(NodeA!=NULL)
        {
            lenA++;
            NodeA=NodeA->next;
        }
        while(NodeB!=NULL)
        {
            lenB++;
            NodeB=NodeB->next;
        }
        NodeA=headA;
        NodeB=headB;
        if(lenB>lenA)
        {
            swap(lenA,lenB);
            swap(NodeA,NodeB);
        }
        int sub=lenA-lenB;
        while(sub--)
        {
            NodeA=NodeA->next;
        }
        while(NodeA!=NULL)
        {
            if(NodeA==NodeB)
            return NodeA;
            NodeA=NodeA->next;
            NodeB=NodeB->next;
        }
        return NULL;

    }
};

 142.环形链表II  

这道题目真的很有意思,要求找到环形链表的入口。本题编程方面其实不难,值得思考的是其背后的思路。这道题采用的是双指针的思想,但是本人双指针的用法还太烂了,虽然想到用双指针但是完全想不出来怎么实现。本题采用快慢指针,快指针每次移动两次,慢指针每次移动一次,如果有环,则快指针率先进入环内,慢指针在快指针在环内运动n圈后进入环中,此时两指针一定会在慢指针进入环内第一圈相遇,此时快指针走过的节点数是慢指针的节点数的两倍,经过公式换算有x=(n-1)(y+z)+z。我们现在知道的信息是相遇的点,现在慢指针从原点出发,快指针从相遇点出发(这个是关键),每次两个指针都只移动一次,因为x=(n-1)(y+z)+z,两指针以相同速度出发,一定会在环形入口点相遇。

代码随想录训练营第四天任务--链表part02_第2张图片

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* FaIndex=head;
        ListNode* SlIndex=head;
        while(FaIndex!=NULL&&FaIndex->next!=NULL)
        {
            FaIndex=FaIndex->next->next;
            SlIndex=SlIndex->next;
            if(FaIndex==SlIndex)
            {
                SlIndex=head;
                while(FaIndex!=SlIndex)
                {
                SlIndex=SlIndex->next;
                FaIndex=FaIndex->next;
                }
                return FaIndex;
            }
        }
        return NULL;
    }
};

你可能感兴趣的:(算法,leetcode,职场和发展)