刷题日记 DAY4

链表

leetcode 203 移出链表元素

双指针

本题使用两个指针,前面的指针要比后面的指针多n个偏移量,这样当前面的指针指向链表的末尾时,后面的指针就指向了要删除的元素,但是删除元素需要获取该元素前面的值,解决办法就是前面的指针再多偏移一个。
P.S.关于有关链表的插入与删除操作尽量使用一个虚拟头节点,这样可以使链表每个位置的操作统一化

    ListNode* removeElements(ListNode* head, int val) {
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head;
        ListNode* cur = dummyHead;
        while (cur->next != nullptr) {
            if (cur->next->val == val) {
                ListNode* tmp = cur->next;
                cur->next = cur->next->next;
                delete tmp;
            }
            else {
                cur = cur->next;
            }     
        }
        head = dummyHead->next;
        delete dummyHead;
        return head;
    }

leetcode 142 环形链表-ii

双指针

本题的要点在于如何推理出相遇的位置。两个指针同时从头节点出发,慢指针每一移动一个单位,快指针每次移动2个单位,如果该链表成环,定会在环内相遇。现设头节点到环入口的距离为x,环入口到相遇点的距离为y,相遇点再到环入口的距离为z,那么在相遇的时候,慢指针所走的距离为x+y,快指针所走的距离为x+n(y+z)+y,又因为快指针每次移动两个单位,而慢指针每次移动一个单位,故相同时间内快指针移动的单位的数量为慢指针的两倍,可推出2(x+y)=x+n(y+z)+y,因要求得x,化简提取x后可推出x=(n-1)(y+z)+z,其中y+z为圆周,故可设n=0,得到x=z,也就是说一个指针从头节点出发,另一个指针从相遇点出发,两个指针一相同的速度前进,相遇点就是环入口。
关于为什么快指针一定会在一圈内追上慢指针的问题:假设快慢指针一起在进入环入口,快指针的速度时慢指针的两倍,在下一次相遇时就在慢指针的第一圈结束,而真实的情况是快指针一定不慢于慢指针进如环中,故一定会在第一圈追上慢指针。

    ListNode *detectCycle(ListNode *head) {
        ListNode* slow = head;
        ListNode* fast = head;
        while (fast != nullptr && fast->next != nullptr) {
            slow = slow->next;
            fast = fast->next->next;
            if (slow == fast) {
                slow = head;
                while (slow != fast) {
                    slow = slow->next;
                    fast = fast->next;
                }
                return slow;
            }
        }
        return nullptr;
    }
posted on 2022-01-10 00:46  wenchester  阅读(17)  评论(0)    收藏  举报