代码随想录算法训练营第4天 | 双指针 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点、160.链表相交、142.环形链表II

day4

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

160.链表相交,第一眼自己都没想出解法

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

只要指针设得够多,就能做出来/doge

虚拟结点用的比较习惯了。

发现链表里的题,用指针的话,往往要三个。

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        // if (!head || !head->next) return head;
        ListNode* dummy = new ListNode(0, head);
        ListNode* pre = dummy;
        while (pre->next && pre->next->next) {
            ListNode* tmp = pre->next;
            pre->next = tmp->next;
            ListNode* tmp2 = pre->next->next;
            pre->next->next = tmp;
            tmp->next = tmp2;
            pre = tmp;
        }
        return dummy->next;
    }
};

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

先走n步的双指针一次循环到位,确实没想到,但是这样真的算是一次遍历吗?

两个指针走的次数,和一个指针走两次的次数,理论上是一样的。

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummy = new ListNode(0, head);
        ListNode *fast = dummy, *slow = dummy;
        while (fast && n--) {
            fast = fast->next;
        }
        if (!fast) return dummy->next;
        while (fast->next) {
            fast = fast->next;
            slow = slow->next;
        }
        ListNode *tmp = slow->next;
        slow->next = tmp->next;
        delete tmp;
        return dummy->next;
    }
};

面试题 02.07. 链表相交( 160.链表相交 )

从计算机的角度来看,链表相交的等价条件:指针一样。

题目突破口肯定是相交之后的部分,先把两个指针调整到离终点距离相同的程度,问题就迎刃而解。

class Solution {
public:
    int getLength(ListNode* head) {
        int length = 0;
        ListNode* p = head;
        while (p) {
            length++;
            p = p->next;
        }
        return length;
    }

    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        int lenA = getLength(headA), lenB = getLength(headB);
        int diff = lenA - lenB;
        ListNode* p = diff > 0 ? headA : headB;
        ListNode* q = diff > 0 ? headB : headA;
        diff = diff > 0 ? diff : -diff;
        while (diff) {
            p = p->next;
            diff--;
        }
        while (p) {
            if (p == q) {
                return p;
            }
            p = p->next;
            q = q->next;
        }
        return NULL;
    }
};

142.环形链表II

这题想不出来,我记得是和快慢指针相关,fast步速是slow两倍。

这道题的理论证明看了一遍,要证明可以排除的情况有点复杂。如果面试碰到,我选择放弃证明,直接背代码。

  1. fast走两步,slow走一步,找到相遇的地方;
  2. 两个指针从fast和head处分别开始走,相遇的地方就是入口。
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head, *slow = head;
        while (fast && fast->next) {
            fast = fast->next->next;
            slow = slow->next;
            if (fast == slow) {
                ListNode* p1 = head;
                ListNode* p2 = fast;
                while (p1 != p2) {
                    p1 = p1->next;
                    p2 = p2->next;
                }
                return p1;
            }
        }
        return nullptr;
    }
};

总结

day4的后三个题都用到了快慢指针,或者保持一定差值,或者移动速度不同。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值