24. 两两交换链表中的节点
https://leetcode.cn/problems/swap-nodes-in-pairs/
https://programmercarl.com/0024.%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%B9.html#_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%B9
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
思路
模拟
递归
代码
递归
class Solution {
public ListNode swapPairs(ListNode head) {
// 递归
if(head == null || head.next == null){
return head;
}
ListNode next = head.next;
ListNode newNode = swapPairs(next.next);
// 交换
head.next = newNode;
next.next = head;
return next;
}
}
19.删除链表的倒数第 N 个结点
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
进阶:你能尝试使用一趟扫描实现吗?
思路
快慢指针
快指针先移动n+1位。(删除节点需要找到节点的前一位)
然后快慢指针同时移动n位,直到快指针为空
代码
/**
* 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 dumyNode = new ListNode(-1);
dumyNode.next = head;
ListNode quick = dumyNode;
ListNode slow = dumyNode;
for(int i = 0; i <= n; i ++){
quick = quick.next;
}
while(quick != null){
quick = quick.next;
slow = slow.next;
}
slow.next = slow.next.next;
// 这个时候返回的是dummyNode.next,而不是head;
return dumyNode.next;
}
}
面试题 02.07. 链表相交
https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:
思路
注意:这里并不是值相交。而是节点相交。
1:求两个链表的长度
2:比较长度,从长度长的开始遍历
3:把相差的长度去掉,然后开始比较,找到公共节点。
代码
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
// 注意这里不是求值相等,而是求交点相等
ListNode cura = headA;
ListNode curb = headB;
int lena = 0,lenb = 0;
int dislen = 0;//链表长度的差值
// 1先求链表长度
while(cura != null){
lena ++;
cura = cura.next; // 忘了
}
while(curb != null){
lenb ++;
curb = curb.next; // 忘了
}
// 复原指针
cura = headA;
curb = headB;
// 2再将cura移动到较长的链表上
if(lenb > lena){
// 交换cura 和 curb
ListNode temp = cura;
cura = curb;
curb = temp;
// 交换长度
int templen = lena;
lena = lenb;
lenb = templen;
}
// 3求出两个链表的长度差
dislen = lena - lenb;
// 4移动cura到跟curab相同的长度上去
for(int i = 0; i < dislen; i++){
cura = cura.next;
}
// 5开始遍历找到相同的节点
while(cura != null){
if(cura == curb){
return cura;
}
// 这段代码忘了
cura = cura.next;
curb = curb.next;
}
return null;
}
}
142.环形链表II
题意: 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
说明:不允许修改给定的链表。
思路
一、判断是否有环。
思路:快慢指针quick and slow。快指针移动两步,慢指针移动一步,当快慢指针相遇的时候。就可以确定有环了。
二、找到环的起始位置。
思路:经过数学推导得到:快慢指针相遇的位置距离环的起始位置与起到到环的起始位置的距离相等。
利用这个数学公式设立:
index1= 相遇位置
index2 = head。
当这两个指针相遇的时候,就是环的起始位置
代码
/**
* 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 quick = head;
ListNode slow = head;
while(quick != null && quick.next != null){
quick = quick.next.next;
slow = slow.next;
if(quick == slow){
ListNode index1 = head;
ListNode index2 = quick;
while(index1 != index2){
index1 = index1.next;
index2 = index2.next;
}
return index1;
}
}
return null;
}
}