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

LeetCode 977 有序数组的平方
题目链接:24. 两两交换链表中的节点 - 力扣(LeetCode)


思路:

这道题其实不难,我们要明白,以头节点为基准,每次交换两个节点并且移动两个节点,如果只剩一个节点就不移动,没节点可移那更好咯,所以我们只用考虑剩下节点为2时的情况。

涉及到交换节点的题目,都要建立一个dummyhead指向head。

#python
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if not head:
            return None
        dummy=ListNode()
        dummy.next=head
        cur=dummy
        while cur.next and cur.next.next:
            A,B=cur.next,cur.next.next
            cur.next=B
            A.next=B.next
            B.next=A
            cur=cur.next.next
        return dummy.next
#java
/**
 * 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) {
        if(head == null){
            return null;
        }
        ListNode dummy = new ListNode(-1, head);
        ListNode cur = dummy;
        while(cur.next != null && cur.next.next != null){
            ListNode A = cur.next, B = cur.next.next;
            A.next = B.next;
            cur.next = B;
            B.next = A;
            cur = cur.next.next;
        }
        return dummy.next;
    }
}

困难与想法:

因为都是以一个点来找后继,所以会有很多cur(比如cur.next.next.next),所以注意设个变量来指代一下,而且最好是画个图,移动指针的时候注意顺序,别把某些指针指空咯,要细心。


LeetCode 19. 删除链表的倒数第 N 个结点
题目链接:19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)


思路:

题目要求删除倒数第N个节点,最单纯的做法就是先遍历一次链表,看看有多长,然后将长度减去N,得到咱们要走多少步数。不过我还是觉得同向双指针更适合这道题,fast指针先走k步,然后slow、fast指针一起走,走到fast.next=None时就把当前slow去掉了。

代码:

#python
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        if not head:
            return None
        dummy=ListNode(0,head)
        slow,fast=dummy,dummy
        for _ in range(n):
            fast=fast.next
        while fast.next:
            slow=slow.next
            fast=fast.next
        slow.next=slow.next.next
        return dummy.next
        
#java
/**
 * 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) {
        if(head == null){
            return null;
        }
        ListNode dummy = new ListNode(-1, head);
        ListNode cur = dummy;
        for(int cnt = 0; cnt < n; cnt++){
            cur = cur.next;
        }
        ListNode pre = dummy;
        while(cur.next != null){
            cur = cur.next;
            pre = pre.next;
        }
        pre.next = pre.next.next;
        return dummy.next;
    }
}

困难与想法:

注意判别一下head==None的时候,然后就是还是之前咱们提到的,只要是要改变节点就从dummy开始。


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


思路:
这道题我第一次看到确实是不会,看了左神和卡哥的视频发现要巧妙的解决它,其实是个数学题,两个同向指针从各自的头节点出发,相同的速度遍历,如果当前链表遍历完了就从对方的头节点遍历,这样很巧妙的是可以确保两个指针走过相同的路,如果在此过程指针指向相同就退出while循环,当然俩指针为空的时候也会退出while循环,所以我们其实return其中一个指针可以满足这两种情况。

代码:

#python
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        if not (headA and headB):
            return None
        cura,curb=headA,headB
        while cura!=curb:
            cura=cura.next if cura else headB
            curb=curb.next if curb else headA
        return cura
/**
 * 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_A = headA, cur_B = headB;
        while(cur_A != null || cur_B != null){
            if(cur_A == cur_B)
                return cur_A;
            else{
                cur_A = cur_A != null ? cur_A.next : headB;
                cur_B = cur_B != null ? cur_B.next : headA;
            }
        }
        return null;
    }
}

困难与想法:

这道题的难点就是要想到遍历完当前链表后要从对方的头节点继续开始遍历,例如cura=cura.next if cura else headB,一开始我想的是cura.next而不是cura,但那样的话走到最后一个节点就不对了会陷入无限循环,因为while cura!=cuab条件一直得不到满足。


LeetCode 142. 环形链表 II
题目链接:142. 环形链表 II - 力扣(LeetCode)


思路:
在操场跑步的时候,如果你跑得慢了,总是会被体育生套圈;同样的,如果这个链表真有个圈,俩指针一快一慢必定也会撞在一起,所以咱们就从头节点开始建立俩快慢指针开始跑呗,如果指为None,就没有环了,指不到空就必定会相遇。
第二个问题,如何返回入环的第一个节点呢?我们不妨想一想,如果真有环,那么快慢节点一定是在第一圈就相遇了(自己推一下对不对),那我们设head到第一个节点距离为a,slow进入环后走了b,fast在b的基础上又走c到环入口,又知道俩者相遇时fast的距离时slow的两倍(每次都走快一步),所以可以得到等式2*(a+b)=a+b+c+b->a=c。此时,slow距离环入口处距离还有c,所以此时我们把fast从head开始,与slow相同的速度,两者就会在入口处相遇了,return就OK。

代码:

#python
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if not head or not head.next:
            return None
        slow,fast=head,head
        while True:
            if not (fast and fast.next):#为啥不要求fast.next.next?
                return None
            slow,fast=slow.next,fast.next.next
            if slow==fast:
                break
        new_fast=head
        while new_fast!=slow:
            new_fast,slow=new_fast.next,slow.next
        return new_fast
#java
/**
 * 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)
            return null;
        ListNode slow = head, fast = head;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow){
                ListNode cur = head;
                while(cur != slow){
                    cur = cur.next;
                    slow = slow.next;
                }
                return cur;
            }
        }
        return null;
    }
}

困难与想法:

 if not (fast and fast.next):#为啥不要求fast.next.next?因为fast每次只走两步,而且为啥不判断slow?因为fast走得比slow快,如果要遇到None也是fast先遇到,所以确实不用判断slow了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

别看了真C不了一点

打赏者皆为义父

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值