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了。