算法记录 | Day④

LeetCode 24-两两交换链表中的节点
题目链接:
https://leetcode.cn/problems/swap-nodes-in-pairs/submissions/
解题思路:

用虚拟节点cur两两交换,返回虚拟头节点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mh1hhpy0-1665908914836)(https://code-thinking.cdn.bcebos.com/pics/24.%E4%B8%A4%E4%B8%A4%E4%BA%A4%E6%8D%A2%E9%93%BE%E8%A1%A8%E4%B8%AD%E7%9A%84%E8%8A%82%E7%82%B91.png)]

代码实现
class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode dum = new ListNode();
        dum.next = head;
        ListNode cur = dum;
        while (cur.next != null && cur.next.next != null) {
            ListNode temp1 = cur.next;
            ListNode temp2 = cur.next.next.next;
            cur.next = cur.next.next;
            cur.next.next = temp1;
            cur.next.next.next = temp2;

            cur = cur.next.next;

        }
        return dum.next;
    }
}
难点:
  • 操作的指针一定指向要反转的两个节点中的前一个结点

  • cur = dum?:cur指向dum才能操作头结点和第二个结点 因为要返回head指针所以要保留dum

  • while里的条件为什么不能是(cur.next.next != null && cur.next != null)?:

    一定要先判断cur.next不为空,再判断cur.next.next不为空,因为万一cur.next为空,则cur.next.next中的cur.next就是对空指针取值再找他的next域,会报空指针异常

  • 结点偶数:cur.next == null(链表为空时)

  • 结点奇数:cur.next.next == null

  • while条件相当于cur后必须有两节点,少于2个无法交换,循环就结束了,无论节点是奇数还是偶数

  • cur要移到需要操作的两个节点的前一个结点

  • 移节点时为什么是cur = cur.next.next?:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pXKlZgks-1665908914837)(C:\Users\Cl\AppData\Roaming\Typora\typora-user-images\image-20221015205528424.png)]


LeetCode 19-删除链表的倒数第N个结点
题目链接:
https://leetcode.cn/problems/remove-nth-node-from-end-of-list/
解题思路:

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

代码实现
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dum = new ListNode();
        dum.next = head;
        ListNode fast = dum;
        ListNode slow = dum;

        n++;
        while (n != 0 && fast != null) {
            fast = fast.next;
            n--;
        }
        while (fast != null) {
            fast = fast.next;
            slow = slow.next;
        }
        slow.next = slow.next.next;
        return dum.next;
    }
}
难点:
  • 为什么fast走n+1步而不是走n步?:如果fast走n步,slow指向要删除的结点,但是slow应该指向要删除的结点的前驱,因为需要利用 要删除的节点的前驱 来删除倒数第n个结点。

  • 为什么不这样写?:

    while(n != 0 && fast != null) {
        fast = fast.next;
        n--;
    }
    fast = fast.next;//如果n>链表的长度,则fast指向null,则fast.next是对空指针操作  会报错
    

LeetCode 面试题02.07.链表相交
题目链接:
https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/
解题思路:

定义两个cur指针分别指向链表头。让curA移到curB末尾对齐的位置,再比较如果相同返回curA 都不相同返回null

代码实现
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dum = new ListNode();
        dum.next = head;
        ListNode fast = dum;
        ListNode slow = dum;

        n++;
        while (n != 0 && fast != null) {
            fast = fast.next;
            n--;
        }
        while (fast != null) {
            fast = fast.next;
            slow = slow.next;
        }
        slow.next = slow.next.next;public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode curA = headA;
        ListNode curB = headB;
        int lenA = 0;
        int lenB = 0;

        while (curA != null) {
            lenA++;
            curA = curA.next;
        }

        while (curB != null) {
            lenB++;
            curB = curB.next;
        }

        curA = headA;
        curB = headB;

        if (lenB > lenA) {
            int tempL = lenA;
            lenA = lenB;
            lenB = tempL;

            ListNode tempN = curA;
            curA = curB;
            curB = tempN;
        }

        int gap = lenA - lenB;

        while (gap != 0) {
            curA = curA.next;
            gap--;
        }

        while (curA != null) {
            if (curA == curB) {
                return curA;
            }
            curA = curA.next;
            curB = curB.next;
        }
        return null;
    }
}
难点:
  • 如果链表B比链表A长要交换头指针的原因:如果A链表一定是长的那条,则只要写一种方法,而不用讨论链表B比链表A长的情况
  • 让cur移动到和curB末尾对齐的位置的原因:如果有一个节点相交,则这个节点之后的所有节点都是相交的 只要判断第一个相交的节点
  • 遍历curA和curB 要先保证curA或者curB不是空指针,所以最后一个while循环里的条件是判断curA不为空

LeetCode 142.环形链表II
题目链接:
https://leetcode.cn/problems/linked-list-cycle-ii/
解题思路:
判断链表是否有环

用快慢指针 fast每次2步 slow每次1步 如果fast和slow在途中相遇则链表有环

找到环的入口

两个指针,从头结点和相遇结点,各走一步,直到相遇,相遇点即为环入口

代码实现
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;

        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;

            if (slow == fast) {
                ListNode index1 = fast;
                ListNode index2 = head;
                while (index1 != index2) {
                    index1 = index1.next;
                    index2 = index2.next;
                }
                return index2;
            }
        }
        return null;
    }
}
难点:
  • 革命尚未成功同志还需努力T-T难点太多了omg
  • https://programmercarl.com/0142.%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8II.html#_142-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8ii
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值