算法训练第四天 | LeetCode 19、142、24、面试题02.07

LeetCode 24

题目简析:两两交换链表元素

如图

1 为cur->next

2为cur->next->next

3为cur->next->next->next

由于经历步骤2后,cur->next已不再是1,我们需要临时结点tmp来记录1

3同理,用临时结点tmp2记录

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummyhead=new ListNode(0);
        dummyhead->next=head;
        ListNode* cur=dummyhead;
        while(cur->next!=nullptr&&cur->next->next!=nullptr){
            cur->next=tmp;
            cur->next->next->next=tmp1;
            cur->next=cur->next->next;
            cur->next->next=tmp;
            cur->next->next->next=tmp1;
            cur=cur->next->next;
        }
        cur=cur->next->next;
        return dummyhead->next;
        }
};

LeetCode 19

题目简析:删除倒数第n个的结点

思路:双指针法

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummyhead = new ListNode(0);
        dummyhead->next=head;
        ListNode*fast=dummyhead;
        ListNode*slow=dummyhead;
        while(n--&&fast!=NULL){
            fast=fast->next;

        }
        fast=fast->next;
        while(fast!=NULL){
            fast=fast->next;
            slow=slow->next;
        }
         slow->next = slow->next->next; 
         return dummyHead->next;
         }
};

fast指针要先向前移动n+1步

先while循环,移动N步后,再补一步

面试题0207链表相交

题目简析:检查链表所相交的起始节点,若没有就返回null

比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
         ListNode*curA=headA;
         ListNode*curB=headB;
         int lenA=0;int lenB=0;
         while(curA!=NULL){
            lenA++;
            curA=curA->next;
         }
         while(curB!=NULL){
            lenB++;
            curB=curB->next;
         }
         curA=headA;
         curB=headB;
         if(lenB>lenA){//使得lenB为上链表
            swap(lenA,lenB);
            swap(curA,curB);
         }
         int gap=lenA-lenB;
         while(gap--){
            curA=curA->next;
         }
         while(curA!=NULL){
            curA=curA->next;
            curB=curB->next;
            if(curA==curB){
                return curA;
            }
         }
         return NULL;
         }
};

LeetCode 142(代码随想录摘抄)

题目简析:给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

主要考察两知识点:

  • 判断链表是否环

  • 如果有环,如何找到这个环的入口

判断链表是否有环

可以使用快慢指针法,分别定义 fast 和 slow 指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。

如果有环,如何找到这个环的入口

此时已经可以判断链表是否有环了,那么接下来要找这个环的入口了。

假设从头结点到环形入口节点 的节点数为x。 环形入口节点到 fast指针与slow指针相遇节点 节点数为y。 从相遇节点 再到环形入口节点节点数为 z。

相遇时: slow指针走过的节点数为: x + y, fast指针走过的节点数:x + y + n (y + z),n为fast指针在环内走了n圈才遇到slow指针, (y+z)为 一圈内节点的个数A。

因为fast指针是一步走两个节点,slow指针一步走一个节点, 所以 fast指针走过的节点数 = slow指针走过的节点数 * 2:

(x + y) * 2 = x + y + n (y + z)

再从n(y+z)中提出一个 (y+z)来,整理公式之后为如下公式:x = (n - 1) (y + z) + z 注意这里n一定是大于等于1的,因为 fast指针至少要多走一圈才能相遇slow指针。

这个公式说明什么呢?

先拿n为1的情况来举例,意味着fast指针在环形里转了一圈之后,就遇到了 slow指针了。

当 n为1的时候,公式就化解为 x = z,

这就意味着,从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点

也就是在相遇节点处,定义一个指针index1,在头结点处定一个指针index2。

让index1和index2同时移动,每次移动一个节点, 那么他们相遇的地方就是 环形入口的节点。

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast != NULL && fast->next != NULL) {
            slow = slow->next;
            fast = fast->next->next;
            // 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇
            if (slow == fast) {
                ListNode* index1 = fast;
                ListNode* index2 = head;
                while (index1 != index2) {
                    index1 = index1->next;
                    index2 = index2->next;
                }
                return index2; // 返回环的入口
            }
        }
        return NULL;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值