代码随想录算法训练营第四天 | 题目 LeetCode24. 两两交换链表中的节点 题目 LeetCode19.删除链表的倒数第N个节点 题目 LeetCode 142.环形链表II

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

注意:交换的时候不是交换两个节点中的值,而是交换物理地址的顺序。

在进行循环时:若节点个数为偶数,需要判断cur->next是否为空;若节点个数为奇数,需要判断cur->next->next是否为空;

循环条件顺序不能写乱:若先进行cur->next->next !=  NULL判断,那么如果cur->next为空,那么该语句就会报错(空指针异常错误),无法进行下去。

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        //定义虚拟头结点
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head;
        ListNode* cur = dummyHead;
        //循环条件注意:若节点个数为偶数,需要判断cur->next是否为空;
        //若节点个数是奇数,需要判断cur->next->next是否为空;
        //循环顺序不能写乱,必须先判断cur->next再判断cur->next->next,否则容易发生空指针异常;
        while(cur->next != NULL && cur->next->next != NULL){
            ListNode* temp = cur->next;
            ListNode* temp1 = cur->next->next->next;
            //开始进行交换
            cur->next = cur->next->next;
            cur->next->next = temp;
            cur->next->next->next = temp1;
            //更新cur,为下一轮交换做准备
            cur = cur->next->next;
        }
        return dummyHead->next;


    }
};

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

分析:这题的重点是正序找到要删除的节点的前一个节点。倒数第n个节点,和dummhead节点相差的距离,与正着数第n个节点 ,和尾部NULL距离相同。

如图所示,定义两个指针fast和slow,让fast先走n+1步。

 fast此时到D节点的位置。然后slow与fast同步走,直到fast = NULL。此时slow指向要删除节点的前一个节点。此时进行删除操作。

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head;
        ListNode* fast = dummyHead;
        ListNode* slow = dummyHead;
        //先让fast走n+1步
        while(n-- && fast != NULL){
            fast = fast->next;
        }
        fast = fast->next;
        //开始让fast和slow一起走
        while(fast != NULL){
            fast = fast->next;
            slow = slow->next;
        }
        ListNode* temp = slow->next;
        slow->next = slow->next->next;
        delete temp;
        temp = NULL;
        return dummyHead->next;
    }
};

LeetCode 160.链表相交 

注:链表相交:指的是相同位置的指针指向的值相等;相当于是对两个链表相同位置进行比较。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* curA = headA;
        ListNode* curB = headB;
        int lenA = 0;
        int lenB = 0;
        //分别获得链表的长度
        while(curA != NULL){
            curA = curA->next;
            lenA++;
        }
        while(curB != NULL){
            curB = curB->next;
            lenB++;
        }
        //重新令curA和curB分别指向A链表和B链表的头节点
        curA = headA;
        curB = headB;
        //令lenA表示长链表
        if(lenB > lenA){
            swap(lenB,lenA);
            swap(curB,curA);
        }
        //计算两个链表之间的长度差
        int gap = lenA-lenB;
        //两个链表尾部对其,将指针curA和curB调整到同一个位置
        while(gap--){
            curA = curA->next; 
        }
        //进行交点的判断
        while(curB != NULL){
            if(curA == curB) return curA;
             
            curA = curA->next;
            curB = curB->next;
        }
        return NULL;
        
        
    }
};

 LeetCode 142.环形链表II

(采用快慢指针方法)

分析:本题有两个重点,(1)找到相遇的点,即判断是否有环;(2)找到环入口;

(1)分别设置两个指针fast和slow,fast指针每次走两步,slow指针每次走一步,当存在环的时候,当两个指针都进入环内,fast指针和slow指针会相遇。

(2)x:表示head节点到入环节点之间的节点个数;

         y:表示入环节点到相遇节点之间的节点个数;

         z:表示相遇节点到入环节点之间的个数;

slow指针走的节点总数:x+y(fast指针在slow指针入环的第一圈就能和slow指针相遇);

fast指针走的节点总数:x+y+n(y+z),其中n表示fast指针在环内走的圈数;

由于slow指针和fast指针是同时出发,而fast指针的速度是slow指针的两倍,那么当他们相遇时, 2(x+y)=x+y+n(y+z)   =>   x=(n-1)(y+z)+z;

当n=1时,也就是在fast走过一圈后与slow相遇,上述公示为 x=z。

也就是说,定义一个指针index1从相遇点出发,定义一个指针index2从head点出发,当两个指针同时以同样的速度前进,他们会在入环节点相遇。

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        //fast指针先走,每次走两步
        while(fast != NULL && fast->next != NULL)
        {
            fast = fast->next->next;
            //slow指针走,每次走一步
            slow = slow->next;     
            //判断两个指针有没有相遇,如果相遇,表示有环;否则,表示无环
            if(fast == slow){
                //相遇后,要找到入环点
                ListNode* index1 = fast;
                ListNode* index2 = head;
                //两个指针在入环点相遇
                while(index1!= index2){
                    index1 = index1->next;
                    index2 = index2->next;
                }
                return index1;
            }          
        }
        return NULL;
    }
};

图源:代码随想录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值