代码随想录第四天| 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II

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

力扣题目链接

独立写时候,没有考虑到 每第二次交换后,需要调整原来的第二个节点指向,也就没想到需要利用虚拟头指针。

错误代码:

class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode fakeHead = new ListNode(-1,head);
        ListNode cur = head, curnext = head.next;
        ListNode temp = curnext;
        while(curnext != null && cur != null){
            //交换
            curnext.next = cur;
            cur.next = temp.next;

            cur = temp.next;
            curnext = cur.next;
            temp = curnext;
        }
        return fakeHead.next;
    }
}

问题:未想清楚依照什么作为循环判断,

AC代码:

class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode dummyhead= new ListNode(-1,head);
        ListNode cur = dummyhead;
        ListNode first,second;
        ListNode temp;
        while(cur.next != null && cur.next.next != null){
            temp = cur.next.next.next;
            first = cur.next;
            second = cur.next.next;

            cur.next = first.next;
            second.next = first;
            first.next = temp;
            
            cur = first;
        }
        return dummyhead.next;
    }
}

交换需要保存四个位置才能保证位置交换的正确性。

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

力扣题目链接

首次做题想到的思路为:先遍历一遍找到链表的size,然后根据size与n 可以定位到欲删除节点的前一个节点,此时有部分用例不过,发现是因为删除节点为头节点,此时与常规情况不一致,遂想到利用dummyhead;成功AC:

dummyhead解法:

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode cur = head;
        ListNode dummyhead = new ListNode(-1,head);
        int size = 1;
        while (cur.next != null) {
            size++;
            cur = cur.next;
        }
        cur = dummyhead;
        for(int i=0;i<size-n;i++){
            cur = cur.next;
        }
        //此时cur为删除节点前一个;
        cur.next = cur.next.next;
        return dummyhead.next;
    }
}

小结:删除链表元素 首先要想到虚拟头节点用于处理链表头

双指针解法:

双指针的经典应用,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummynode = new ListNode(-1,head);
        ListNode fast = dummynode,slow = dummynode;
        for(int i=0; i<n; i++){
            fast = fast.next;
        }
        while(fast.next != null){
            fast = fast.next;
            slow = slow.next;
        }
        //此时slow为删除节点的前一个
        slow.next = slow.next.next;
        return dummynode.next;
    }
}

这里fast移动n步,因为while的判断 fast会停在链表尾节点,此时slow为尾结点的往前数n个对应节点,即为待删除节点的前一个。 录中移动了n+1,因为fast最终会在尾节点的下一个(null)代码随想录 (programmercarl.com)

面试题 02.07. 链表相交

面试题 02.07. 链表相交 - 力扣(LeetCode)

O(n+m):

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode curA = headA;
        ListNode curB = headB;
        int lenA = 0,lenB = 0;
        while(curA != null){
            lenA++;
            curA = curA.next;
        }
        while(curB != null){
            lenB++;
            curB = curB.next;
        }
        curA = headA;
        curB = headB;
        if(lenA < lenB){
            curA = headB;
            curB = headA;
            int temp = lenA;
            lenA = lenB;
            lenB = temp;
        }
        //此时curA为更长的那个链表头
        for(int i=0;i<lenA-lenB;i++){
            curA = curA.next;
        }
        while(curA != null){
            if(curA == curB){
                System.out.println("Intersected at \'"+curA.val+"\'");
                return curA;
            }
            curA = curA.next;
            curB = curB.next;
        }
        System.out.println("Intersected at \'"+"0"+"\'");
        return null;
    }
}

也可选择不输出,不输出同样ac,且耗时为1ms

O(nm):

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode curA = headA;
        ListNode curB = headB;
        while(curA != null){
            curB = headB;
            while(curB != null){
                if(curA == curB){
                    System.out.println("Intersected at \'"+curA.val+"\'");
                    return curA;
                }
                curB = curB.next;
            }
            curA = curA.next;
        }
        System.out.println("Intersected at \'0\'");
        return null;
    }
}

142.环形链表II

力扣题目链接

依旧是双指针的思路,快慢指针。

对于寻找环的入口,数学推导及证明见代码随想录 (programmercarl.com)

总结就是 快慢指针,若相遇则一定有环;从头节点、相遇节点分别出发 所相遇的节点即为环入口

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast = head,slow = head;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
            if(slow == fast){//相遇 说明一定有环
                ListNode findEntrance = head;
                while(findEntrance != slow){
                    findEntrance = findEntrance.next;
                    slow = slow.next;
                }
                return slow;
            } 
        }
        return null;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值