24.两两交换链表中的节点
- 题目描述
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
- 考虑:涉及节点个数,终止条件
- 代码随想录视频讲解链接:https://www.bilibili.com/video/BV1YT411g7br/?spm_id_from=333.788&vd_source=110bab21cbd93149da7eacba5f850b6b
/**
* 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();
dummyHead.next = head;
ListNode cur = dummyHead;
//考虑偶数个节点和奇数个节点
//两两交换共涉及4个节点,包括交换节点和交换节点前后节点
while(cur.next != null && cur.next.next != null){
ListNode tmp2 = cur.next;
cur.next = cur.next.next;
ListNode tmp4 = cur.next.next;
cur.next.next = tmp2;
tmp2.next = tmp4;
//cur后移2位
cur = tmp2;
}
return dummyHead.next;
}
}
19.删除链表的倒数第N个节点面试题
- 题目描述
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
- 考虑:没有给出链表长度size
- 代码随想录视频讲解链接:https://www.bilibili.com/video/BV1vW4y1U7Gf/?vd_source=110bab21cbd93149da7eacba5f850b6b
/**
* 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) {
//没有给链表长度size,所以没办法通过正向遍历到第n-i+1个节点
//双指针法
ListNode dummyHead = new ListNode();
dummyHead.next = head;
ListNode fast = dummyHead;
ListNode slow = dummyHead;
n += 1;
//n的终止条件需要想清楚,fast
while(n > 0 && fast != null){
fast = fast.next;
n--;
}
while(fast != null){
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return dummyHead.next;
}
}
02.07. 链表相交
- 题目描述
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
- 思路:长短链表末端位置对齐,因为相交节点开始后面都是一样的,从末端开始比较。
- 代码随想录文字讲解链接:https://programmercarl.com/%E9%9D%A2%E8%AF%95%E9%A2%9802.07.%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC
/**
* 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 curA = headA;
ListNode curB = headB;
int lenA = 0;
int lenB = 0;
while(curA != null){//求链表A的长度
lenA++;
curA = curA.next;
}
while(curB != null){//求链表B的长度
lenB++;
curB = curB.next;
}
curA = headA;
curB = headB;
//确保curA指向的是长链,lenA是长链的长度
if(lenB > lenA){
//换指针
ListNode tmpNode = curA;
curA = curB;
curB = tmpNode;
//换长度
int tmp = lenA;
lenA = lenB;
lenB = tmp;
}
//使curA和curB在同一起点上,末端位置对齐
int gap = lenA - lenB;
while(gap > 0){
curA = curA.next;
gap--;
}
while(curA != null){
if(curA == curB){
return curA;
}
curA = curA.next;
curB = curB.next;
}
return null;
}
}
142.环形链表II
- 题目描述
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
说明:不允许修改给定的链表。
- 思路:解决问题除了逻辑角度考虑,还有数学角度,环形链表双指针
- 代码随想录视频讲解链接:https://www.bilibili.com/video/BV1if4y1d7ob/?vd_source=110bab21cbd93149da7eacba5f850b6b
/**
* 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;
//循环条件中要考虑fast走两步,next为空异常
while(fast != null && fast.next != null){
//快指针走两步,慢指针走一步,
fast = fast.next.next;
slow = slow.next;
//如果是环形链表,快慢指针会相遇,否则快指针走到链表尾,return null
if(fast == slow){
ListNode meet = fast;//记录相遇点
//环形链表分为三段:1、进入环前x;2、环中相遇前y;3、相遇后到环入口z
//fast走的:x+y+n(y+z),n>=1
//slow走的:x+y(slow没走完一圈就能被追上,因为slow的一圈对应fast的两圈)
//公式:x+y+n(y+z) = 2(x+y) -> x+y = n(y+z) ->x = n(y+z)-y ->x = (n-1)(y+z) + z
ListNode index = head;
while(index != meet){
index = index.next;
meet = meet.next;
}
return meet;
}
}
return null;
}
}