链表专题
/*** 链表的节点* @param <E>*/
public class ListNode<E> {public E element;public ListNode<E> next;public ListNode() {}public ListNode(E element) {this.element = element;}public ListNode(E element, ListNode<E> next) {this.element = element;this.next = next;}@Overridepublic String toString() {return "ListNode{" +"element=" + element +", next=" + next +'}';}
}
链表结构
public class MyLinkedList<E> {private ListNode<E> head;public ListNode<E> getHead() {return head;}public void setHead(ListNode<E> head){this.head = head;}public void add(E data) {ListNode<E> newNode = new ListNode<>(data);if (head == null) {head = newNode;return;}ListNode<E> curr = head;while (curr.next != null) curr = curr.next;curr.next = newNode;}@Overridepublic String toString() {StringBuilder sb = new StringBuilder();ListNode<E> curr = this.head;while (curr != null) {sb.append(curr.element).append("-->");curr = curr.next;}sb.delete(sb.length() - 3, sb.length());return sb.toString();}
}
经典问题
反转链表II
问题
[力扣92] 92. 反转链表 II - 力扣(LeetCode)
问题描述
给你单链表的头指针
head
和两个整数left
和right
,其中left <= right
。请你反转从位置left
到位置right
的链表节点,返回 反转后的链表 。
示例 1:
输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]
示例 2:
输入:head = [5], left = 1, right = 1
输出:[5]
解决方案
定义虚拟头节点dummy, 要操作节点的前一个节点pre(默认为null), 寻找的反转节点的前一个节点first(默认指向dummy节点)
index记录查找到left的步数,tips:left位置从1开始计算,所以我们要寻找的位置应该left-1;
移动first索引查找要操作的元素的前一个节点(节点1)。
记录当前要操作的节点curr,使用curr对要求的节点进行反转操作。
- Node next = curr.next;
- curr.next = pre;
- pre = curr;
- curr = next;
重复执行操作2,3,4节点,出循环后
- first.next.next = curr; //即节点2 连接节点5
- first.next = pre; //即节点1连接要操作的最后一个节点
ListNode<Integer> dummy = new ListNode<>(-1, head);
ListNode<Integer> pre = null;
ListNode<Integer> first = dummy;for (int i = 0; i < left - 1; i++) {first = first.next;
}ListNode<Integer> curr = first.next;for (int i = 0; i <= (right - left); i++) {ListNode<Integer> next = curr.next;curr.next = pre;pre = curr;curr = next;
}first.next.next = curr;
first.next = pre;return dummy.next;
删除链表中中重复元素
问题
[力扣83] 83. 删除排序链表中的重复元素 - 力扣(LeetCode)
问题描述
给定一个已排序的链表的头
head
, 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。
示例 1:
输入:head = [1,1,2]
输出:[1,2]
示例 2:
输入:head = [1,1,2,3,3]
输出:[1,2,3]
解决方案
定义要移动的节点curr: curr = head
如果当前curr的值与curr.next的值相等,则断开此节点连接下一个节点(2),否则移动curr索引
if(curr.val == curr.next.val) curr.next = curr.next.next;
elsecurr = curr.next;
public ListNode deleteDuplicates(ListNode head) {ListNode dummy = new ListNode(-1, head);ListNode curr = dummy.next;while (curr.next != null) {if (curr.val == curr.next.val) {curr.next = curr.next.next;} else {curr = curr.next;}}return dummy.next;}
删除链表中节点
问题
[力扣237] 237. 删除链表中的节点 - 力扣(LeetCode)
问题描述
有一个单链表的
head
,我们想删除它其中的一个节点node
。给你一个需要删除的节点node
。你将 无法访问 第一个节点head
。链表的所有值都是 唯一的,并且保证给定的节点
node
不是链表中的最后一个节点。删除给定的节点。注意,删除节点并不是指从内存中删除它。这里的意思是:
- 给定节点的值不应该存在于链表中。
- 链表中的节点数应该减少 1。
node
前面的所有值顺序相同。node
后面的所有值顺序相同。自定义测试:
- 对于输入,你应该提供整个链表
head
和要给出的节点node
。node
不应该是链表的最后一个节点,而应该是链表中的一个实际节点。- 我们将构建链表,并将节点传递给你的函数。
- 输出将是调用你函数后的整个链表。
示例 1:
![]()
输入:head = [4,5,1,9], node = 5 输出:[4,1,9] 解释:指定链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9
示例 2:
![]()
输入:head = [4,5,1,9], node = 1 输出:[4,5,9] 解释:指定链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9
提示:
- 链表中节点的数目范围是
[2, 1000]
-1000 <= Node.val <= 1000
- 链表中每个节点的值都是 唯一 的
- 需要删除的节点
node
是 链表中的节点 ,且 不是末尾节点
解决方案
![image-20241011172032702](https://i-blog.csdnimg.cn/img_convert/b6d4612c5b11fe7201bcf1624e5b4db3.png)
public void deleteNode(ListNode node) {node.val=node.next.val;node.next=node.next.next;}
移除链表元素
问题
[力扣203] 203. 移除链表元素 - 力扣(LeetCode)
问题描述
给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。
示例 1:
输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]
示例 2:
输入:head = [], val = 1
输出:[]
示例 3:
输入:head = [7,7,7,7], val = 7
输出:[]
解决方案
递归退出条件 :if(curr.next ==null) return null;
curr.next = null;
判断当前节点是否是要删除的节点,如果是则删除(即断开下一个节点的连接)
if(curr.val == val){
return curr.next;
}else{
return curr;
}
递归操作
public ListNode<Integer> removeElementsx(ListNode<Integer> curr, int val) {if (curr == null) return null;curr.next = removeElementsx(curr.next,val);if(curr.val == val ){return curr.next;}else{return curr;}
}
移除链表元素II
问题
[力扣82] 82. 删除排序链表中的重复元素 II - 力扣(LeetCode)
问题描述
给定一个已排序的链表的头
head
, 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。
示例 1:
输入:head = [1,2,3,3,4,4,5]
输出:[1,2,5]
示例 2:
输入:head = [1,1,1,2,3]
输出:[2,3]
解决方案
定义虚拟头结点dummy,操作节点curr指向dummy
移动curr,防止越界 curr.next !=null && curr.next.next!=null,
获取当前节点,使用中间节点tmp记录 ListNode tmp = curr.next;
判断是和相邻的节点是否相等(curr.next.next: 节点2)
if(curr.next.next.val ==val){
//循环删除节点
while(curr.next !=null && curr.next.val == val){
curr.next = curr.next.next;
}
}
从链表中移除节点
问题
[力扣2487] 2487. 从链表中移除节点 - 力扣(LeetCode)
题目描述
给你一个链表的头节点
head
。移除每个右侧有一个更大数值的节点。返回修改后链表的头节点head
。示例 1:
输入:head = [5,2,13,3,8] 输出:[13,8] 解释:需要移除的节点是 5 ,2 和 3 。 - 节点 13 在节点 5 右侧。 - 节点 13 在节点 2 右侧。 - 节点 8 在节点 3 右侧。
示例 2:
输入:head = [1,1,1,1] 输出:[1,1,1,1] 解释:每个节点的值都是 1 ,所以没有需要移除的节点。
解决方案
给你一个链表的头节点
head
。移除每个右侧有一个更大数值的节点。返回修改后链表的头节点head
。示例 1:
[外链图片转存中…(img-1wS0djH7-1739015221466)]
输入:head = [5,2,13,3,8] 输出:[13,8] 解释:需要移除的节点是 5 ,2 和 3 。 - 节点 13 在节点 5 右侧。 - 节点 13 在节点 2 右侧。 - 节点 8 在节点 3 右侧。
示例 2:
输入:head = [1,1,1,1] 输出:[1,1,1,1] 解释:每个节点的值都是 1 ,所以没有需要移除的节点。