代码随想录训练营第四天

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

文章

代码随想录0024.两两交换链表中的节点

思路

两个指针指向当前要交换的两个节点,一个指针指向这两个节点前面的节点,一个指针指向这两个节点后面的节点。交换之后拼回去。

代码

class Solution {
    public ListNode swapPairs(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode dummy = new ListNode(0, head);
        ListNode prev = head;
        ListNode post = head.next;
        ListNode root = dummy;
        ListNode temp;
        while (true) {
            temp = post.next;
            root.next = post;
            post.next = prev;
            prev.next = temp;
            root = prev;
            prev = temp;
            if (prev == null || prev.next == null) {
                break;
            }
            post = temp.next;
        }
        return dummy.next;
    }
}

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

文章

代码随想录0019.删除链表倒数第N个节点

思路

快慢指针。快指针比慢指针先行N步,快指针到最后一个节点停止,此时慢指针指向待删除节点的前驱节点,便于执行删除操作。

代码

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(0, head);
        ListNode fast = dummy;
        ListNode slow = dummy;
        while (n > 0) {
            fast = fast.next;
            --n;
        }
        while (fast.next != null) {
            slow = slow.next;
            fast = fast.next;
        }
        slow.next = slow.next.next;
        return dummy.next;
    }
}

160.相交链表

文章

代码随想录面试题02.07.链表相交

思路

先分别遍历两个链表,计算长度差。
再遍历,让长链表的指针先行长度差的步数,然后开始并行,检查是否有相同节点。

代码

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        int diffAB = 0;
        ListNode pA = headA;
        ListNode pB = headB;
        while(pA != null || pB != null) {
            if (pA == pB) {
                return pA;
            }
            if (pA == null) {
                ++diffAB;
                pB = pB.next;
            } else if (pB == null) {
                --diffAB;
                pA = pA.next;
            } else{
                pA = pA.next;
                pB = pB.next;
            }
        }
        pA = headA;
        pB = headB;
        if (diffAB > 0) {
            while (diffAB > 0) {
                pB = pB.next;
                --diffAB;
            }
        }
        if (diffAB < 0) {
            while (diffAB < 0) {
                pA = pA.next;
                ++diffAB;
            }
        }
        while (pA != null) {
            if (pA == pB) {
                return pA;
            }
            pA = pA.next;
            pB = pB.next;
        }
        return null;
    }
}

142.环形链表II

文章

代码随想录0142.环形链表II

思路

不会做,看题解。
快慢指针,快指针一步走2,慢指针一步走1,如果有环则一定相遇。设头结点到环入口距离为 l l l 环入口到相遇位置距离为 x x x,环一圈长度为 r r r ,易知慢指针走过的路程为 l + x + n r l + x + nr l+x+nr,快指针走过的路程为 l + x + ( n + 1 ) r l + x + (n + 1)r l+x+(n+1)r ,而快指针走过的路程一定是慢指针的2倍,从而有 l + x = r l + x = r l+x=r,则有 l = r − x l = r - x l=rx
我就卡在这里了,不知道 r r r ,不知道 x x x,我咋求 l l l
万万没想到,不是算出来的,是数出来的。
l = r − x l = r - x l=rx 这个等式的含义是:从头结点到环入口的距离等于慢指针继续走完当前这一圈剩下的路程。这意味着如果此时有另一个指针从头结点出发,慢指针与其同步推进,二者相遇时位置应该恰好是环入口。

代码

public class Solution {
    public ListNode detectCycle(ListNode head) {
        if (head == null || head.next == null) {
            return null;
        }
        ListNode slow = head;
        ListNode fast = head;
        ListNode ptr = head;
        int s = 0;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            ++s;
            if (fast == null || fast.next == null) {
                return null;
            }
            if (slow == fast) {
                // System.out.println(slow.val);
                break;
            } 
        } 
        while (ptr != slow) {
            slow = slow.next;
            ptr = ptr.next;
        }
        return ptr;
    }
}

总结

其实很巧的是,今天LeetCode推送的每日一题是141.环形链表也是链表的题目,我也做了,但是其中包含的要点完全被142.环形链表II覆盖,相当于无用功。
今天感觉环形链表和链表相交两个题目有一些共性,需要用一个指针先完成差距量,然后再用另一个指针从头出发寻找相遇的节点。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值