代码随想录day04
24. 两两交换链表中的节点
先引入一个虚拟头结点,排除一些特殊情况
class Solution {
public ListNode swapPairs(ListNode head) {
//虚拟头结点
ListNode newHead = new ListNode(-1);
newHead.next=head;
ListNode curNode=newHead;
ListNode tempNode;
ListNode firtNode;
ListNode secondNode;
while(curNode.next != null && curNode.next.next != null){
firtNode = curNode.next;
secondNode = curNode.next.next;
tempNode = curNode.next.next.next;
//交换的三个步骤
curNode.next = secondNode;
secondNode.next = firtNode;
firtNode.next =tempNode;
//移动虚拟头结点的三个位置以实现下一组交换
curNode=firtNode;
}
return newHead.next;
}
}
19.删除链表的倒数第N个节点
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
//虚拟头结点
ListNode newHead=new ListNode(-1);
newHead.next=head;
//快慢指针
ListNode fast=newHead;
ListNode slow=newHead;
//将快指针先移动n个位置
while(n != 0){
fast = fast.next;
n--;
}
//快慢指针同时移动,当快指针移动至链表末尾时,慢指针刚好是我们要删除节点的前一个节点
while(fast.next != null){
fast = fast.next;
slow = slow.next;
}
//删除目标节点
slow.next = slow.next.next;
//防止头结点被删除,故返回cur.next而不是head
return cur.next;
}
}
面试题02.07.链表相交
辅助栈
将两个链表压入栈中,自栈顶逐渐向栈尾比较,找出交叉的子链表
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) {
return null;
}
Stack<ListNode> stackA = new Stack<>();
Stack<ListNode> stackB = new Stack<>();
ListNode dummyA = new ListNode(0, headA);
ListNode dummyB = new ListNode(0, headB);
ListNode curA = dummyA;
ListNode curB = dummyB;
//将链表中内容压入栈中
while (curA != null) {
stackA.push(curA);
curA = curA.next;
}
while (curB != null) {
stackB.push(curB);
curB = curB.next;
}
//将栈顶进行比较
while (!stackA.isEmpty() && !stackB.isEmpty() && stackA.peek() == stackB.peek()) {
stackA.pop();
stackB.pop();
}
if (stackA.isEmpty() && stackB.isEmpty()) {
return null;
}
return stackA.isEmpty() ? stackB.peek().next : stackA.peek().next;
}
}
双指针
A链表遍历完之后遍历B链表至交叉结点所经过的路程为a +(b-c)
B链表遍历完之后遍历B链表至交叉结点所经过的路程为b +(a-c)
二者相等
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) {
return null;
}
ListNode a = headA;
ListNode b = headB;
// 先让a和b遍历各自的链表,当a到达尾部时指向headB的头节点,当b到达尾部时指向headA的头节点
while (a != b) {
a = (a == null) ? headB : a.next;
b = (b == null) ? headA : b.next;
}
// 如果链表相交,a和b会在交点相遇;如果不相交,它们会同时指向null
return a;
}
}
142.环形链表II
图中直线段代表非环部分,圈代表环形部分
fast和slow两个指针都从head出发fast每次移动两个节点,slow每次移动一个节点,当二者相遇时
fast走了2k,slow走了k,fast比slow多走的部分是在绕环走,故k就是环的长度
我们假设相遇点距环起点的距离为m
故:
由head距离环起点的距离为k-m
相遇点绕环走至环起点的距离为k-m
此时两个指针都在相遇点,我们将slow指针移动至head位置,让二者以一个节点的速度出发,则刚好在环起点位置相遇,返回环起点
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode fast,slow;
fast = slow = head;
//快慢指针遍历链表至到二者相遇退出循环
while(fast != null && fast.next!=null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow){
break;
}
}
if(fast == null || fast.next == null){
return null;
}
slow=head;
while(slow != fast){
fast = fast.next;
slow = slow.next;
}
return slow;
}
}