代码随想录算法训练营第四天 | 24.两两交换链表中的节点,19.删除链表的倒数第N个节点 ,142.环形链表II ,160.链表相交 9.24

代码随想录算法训练营第四天 | 24.两两交换链表中的节点,19.删除链表的倒数第N个节点 ,142.环形链表II ,160.链表相交 9.24

链表解题思路总结

  1. 首先想用什么方法去遍历链表 双指针还是单指针
  2. 然后想指针从哪里开始
  3. 然后想实现功能操作如何实现 指针需要在哪个位置
  4. 然后想循环结束的条件
  5. 然后想返回值 取哪个

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

  1. 想让两个节点交换位置 操作指针需要指在他们两个节点的前一个节点 这点非常重要
  2. 第二 如何判断循环结束条件
    1. 当节点个数为奇数个时,到最后时cur.next.next为空 即最后一个就不用交换位置了
    2. 当节点个数为偶数个时,cur后面没有节点,因此 判断cur.next为空
    3. 因此循环条件为 cur.next!=null && cur.next.next!=null
    4. cur.next必须写前面 这样如果为空就不会执行后面的cur.next.next也就不会报空指针异常错误
  3. 交换操作 需用temp
  4. 然后移动cur指针到后两位 cur.next.next
  5. 最后返回新链表的头节点 dummyhead.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 swapPairs(ListNode head) {
        ListNode dummyhead = new ListNode(-1,head);
        ListNode cur = dummyhead;
        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 dummyhead.next;
    }
}

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

  1. 这题的关键点是如何定位到倒数第n个节点前一个节点
  2. 可以用双指针的方法 先让快指针跑n个节点 然后快慢指针同时跑 直到快指针.next==Null 这样慢指针就到了
  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 removeNthFromEnd(ListNode head, int n) {
        ListNode dummyhead = new ListNode(-1,head);
        ListNode slow = dummyhead;
        ListNode fast = dummyhead;

        while(n!=0){
            fast = fast.next;
            n--;
        }
        while(fast.next!=null){
            fast = fast.next;
            slow = slow.next;
        }

        slow.next = slow.next.next;
        return dummyhead.next;
    }
}

142.环形链表II

如何判断是否有环

  1. 定义快慢两个指针 fast一次走2个节点 slow一次走一个节点 这样快指针相对于慢指针每次走 1个节点
    这样就不会错过慢指针

寻找环的入口

  1. x表示从链表头节点到入口距离 y表示从入口到相遇点距离 z表示从相遇点再到入口距离
  2. 慢指针路程可以表示为x+y 快指针路程可以表示为x+n(y+z)
  3. 因为慢指针一次1格 快指针一次2格 所以有等式 2(x+y)=x+n(y+z) 取n=1 即 x=z
  4. 为什么慢指针路程可以表示为x+y? 因为慢指针在环里面一圈还没有转到就与快指针相遇了 因为快指针速度为慢指针的两倍
    所以必定快指针必定能在一圈之内与慢指针相遇
  5. 由x=z 可以在头节点定义Index1 相遇点定义index2 然后让他们往前走 等到他们相遇 就刚好走到入口点 再返回index1或index2就可以了
  6. 控制快指针慢指针向后跳 的循环终止条件 为 快指针 fast不为空 fast.next也不为空 因为有可能 fast跳完2格自己是空的
    然后fast.next就会空指针报错
/**
 * 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) {

        ListNode fast = head;
        ListNode slow = head;


        while(fast!=null && fast.next!=null){
            fast = fast.next.next;
            slow = slow.next;
            if(fast==slow){
                ListNode index1 = head;
                ListNode index2 = fast;
                while(index1!=index2){
                    index1 = index1.next;
                    index2 = index2.next;
                }
                return index1;
            }
        }
        return null;
        
    }
}

160.链表相交

  1. 注意,交点不是数值相等,而是指针相等
  2. 注意到 要想找两个链表的初始交点 从每个链表前面开始遍历的话是不可行的
  3. 所以可以先分别求出A B链表的长度 然后求出两个链表的长度的差值
  4. 然后就可以让长的链表先遍历差值 与短的链表处于相平齐的位置
  5. 接下来同时遍历移动找相等节点即可
  6. 若一直没找到 则循环结束返回null
  7. 为什么不从后往前遍历 因为链表只知道头指针head 所以只能从前往后遍历
/**
 * 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) {
        ListNode cur;
        cur = headA;
        int lenA = 0;
        while(cur!=null){
            cur = cur.next;
            lenA++;
        }

        int lenB = 0;
        cur = headB;
        while(cur!=null){
            cur = cur.next;
            lenB++;
        }
        
        ListNode cura;
        ListNode curb;


        int minus = Math.abs(lenA-lenB);
        if(lenA>lenB){
            cur = headA;
        }else{
            cur = headB;
        }

        while(minus!=0){
            cur = cur.next;
            minus--;
        }

        if(lenA>lenB){
            cura = cur;
            curb = headB;
        }else{
            curb = cur;
            cura = headA;
        }



        while(cura!=null){
            if(cura!=curb){
                cura = cura.next;
                curb = curb.next;
            }else{
                return cura;
            }

        }
        return null;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值