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

前言

我感觉链表一直是我的一个大缺陷啊,希望可以赶上:)

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

1.精华笔记

要点是要明确:要修改1点指向,那么必须要知道1前一个点指针

2.图解(来自代码随想录)

感觉画的很清楚了,说明了为什么节点要设计tmp和tmp1的变量来存储节点1和节点3,因为会在步骤一的赋值后丢失。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode dummy = new ListNode();
        dummy.next = head;
        ListNode current = dummy;
        while (current.next != null && current.next.next != null){
            ListNode tmp = current.next;
            ListNode tmp1 = current.next.next.next;
            current.next = current.next.next;
            current.next.next = tmp;
            tmp.next = tmp1;
            current = current.next.next;
        }
        return dummy.next;
    }
}

// 代码中的这一行 `ListNode tmp1 = current.next.next.next;` 确实没有进行空指针异常的提前判断。但是,在这行代码被执行之前,循环的条件 `current.next != null && current.next.next != null` 已经确保了 `current.next` 和 `current.next.next` 都不是空指针。

// 在这个条件下,`current.next.next.next` 可能是一个有效的节点,也可能是空(null)。如果是空,这意味着链表中已经没有更多的节点可以进行交换。在这种情况下,将 `tmp1` 设置为 `null` 是安全的,因为后续的操作是将 `tmp.next` 指向 `tmp1`。如果 `tmp1` 是 `null`,这相当于更新了链表的尾部。

// 因此,虽然没有直接对 `current.next.next.next` 进行空指针检查,但是前面的循环条件已经间接确保了这行代码在执行时不会引发空指针异常。这是因为在到达可能为空的 `current.next.next.next` 之前,代码已经确认了至少存在两个连续的非空节点,这是进行节点交换所必需的。









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

1.代码随想录思路

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

(如果先移动fast到最末尾,数出来size,再让slow移动fast-n,就遍历两遍了,总体效率还是比不上这种思路)

2.Code

看了思路之后很快的做出来了,对链表的理解上升了,开心.

关于ruturn 不可以是head的问题,是因为head有可能已经被删除了,如果删除的是头节点的话。所以必须return dummy.next。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {

        ListNode dummy = new ListNode();
        dummy.next = head;

        ListNode fast = dummy;
        ListNode slow = dummy;

        for (int i=0;i<n;i++){
            if (fast.next != null){
                 fast = fast.next;
            }else{
                return head;
            }
        }
        while (fast.next != null){
            slow = slow.next;
            fast = fast.next;
        }
        slow.next = slow.next.next;
        return dummy.next;

    }
}

 面试题 02.07. 链表相交

1.第一印象:

看不懂题目 呵呵 

2.后续

大约做了半个小时吧,看了一个b站视频:

【面试题02.07链表相交(Python版)】 https://www.bilibili.com/video/BV1VT4y1r7vE/?share_source=copy_web&vd_source=94e7fb54e1e56a78eb4917d7e5240a87

学了一个思路写

这里需要注意的是first.next = headb是错误的,会造成环,应该是first直接为headb了。

我感觉这道题是有一些小巧思的,比如如果heada遍历完了就去链接headb继续遍历,这样下来如果两个表有链接,一定会在链接的位置点相遇。

3.笔记思路

4.Code

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {

        if (headA == null || headB == null) {
            return null;
        }
        ListNode dummy = new ListNode();
        dummy.next = headA;
        ListNode dummyB = new ListNode();
        dummyB.next = headB;
        
        ListNode first = dummy.next;
        ListNode last = dummyB.next;
        boolean flag_A = false;
        boolean flag_B = false;
        while (true){
             if (first == last){
                return first;
            }
            if (first.next == null && flag_A == false){
                // first.next = headB; 错误
                first = headB;
                flag_A = true;
            }else{
                first = first.next;
            }
            if (last.next == null && flag_B == false){
                last = headA;
                flag_B = true;
            }else{
                last = last.next;
            }   
             if (first == last){
                return first;
            }
            if ((first.next == null && flag_A==true) || (last.next == null && flag_B == true)){
                return null;
            }
        }

    }
}

142.环形链表II

大部分都自己写出来啦,最后的判断节点不太会判断了,需要数学逻辑,参考了文章。

1.问题点

(1)代码判断逻辑

这里一开始写错了,但还是不清楚原因?

 if (fast != null && fast.next != null)

(2) 数学逻辑

2.Code 

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {

        if (head == null || head.next == null ){
            return null;
        }

        ListNode fast = head;
        ListNode slow = head;

        while (true){
            if (fast != null && fast.next != null){
                slow = slow.next;
                fast = fast.next.next;
                if (slow == fast){
                   fast = head;
                while (slow != fast) {
                    slow = slow.next;
                    fast = fast.next;
                    }
                    return fast;
                }
            }else{
                return null;
            }
        }
        
    }
}

 总结:

  1. 状态:未完结
  2. 困难:
  3. 待解决问题:
  4. 今日收获:
  5. 来源:代码随想录
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值