1. 移除链表元素(lc203)
题目描述:
给你一个链表的头节点 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
输出:[]
提示:
列表中的节点数目在范围 [0, 10 ^ 4] 内
1 <= Node.val <= 50
0 <= val <= 50
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/remove-linked-list-elements
解题思路:
解法一:
遍历链表去判断节点元素是不是要删除的元素即可 , 做题需要提醒注意的是如果要删除的元素是头节点或者尾节点的处理 ;
由于每次循环遍历都需要去访问节点中的元素 , 所以循环遍历的条件应当使用 cur.next != null 而不是 cur = null , 以保证在最后一次遍历时不会出现空指针异常的情况 ;
从题目中可以知道要处理的链表是单链表 , 所以如果要删除节点 , 那么需要先找到要删除节点的前一个结点 ; 所以使用 cur.next.val == val 来判断当前节点的下一个节点是不是要删除的节点 , 此时cur指向的就是要删除节点的前一个节点 , 修改cur.next引用的指向即可 ;
还需要注意当遍历结束后 , 此时头节点还没有判断 , 这里不能忽略 , 再去判断一下即可 .
解法二:
遍历链表依次获取每一个节点,如果该节点中的值域与val相等,则删除
在删除时候一定要分情况:删除的节点为第一个节点 和 不是第一个节点,两种方式删除是不一样的
代码实现:
解法一:
/**
* 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 removeElements(ListNode head, int val) {
if(head == null){
return null;
}
ListNode cur = head;
while(cur.next != null){
if(cur.next.val == val){
ListNode curNext = cur.next.next;
cur.next = curNext;
} else{
cur = cur.next;
}
}
if(head.val == val){
head = head.next;
}
return head;
}
}
解法二:
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode cur = head;
ListNode prev = null; // 标记cur的前一个
while(null != cur){
if(val == cur.val){
if(null == prev){
// 删除的是第一个节点
head = cur.next;
}else{
// 删除的不是第一个节点
prev.next = cur.next;
}
}else{
prev = cur;
}
cur = cur.next;
}
return head;
}
}
提交结果:
2. 链表的中间节点(lc876)
题目描述:
给定一个头结点为 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
示例 1:
输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.
示例 2:
输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 (序列化形式:[4,5,6])
由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。
提示:
给定链表的结点数介于 1 和 100 之间。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/middle-of-the-linked-list
解题思路:
快慢引用
fast一次走两步,slow一次走一步,当fast走到末尾的时候,slow刚好是中间节点
注意:while循环条件
代码实现:
class Solution {
public ListNode middleNode(ListNode head) {
if(head == null){
return null;
}
ListNode fast = head;
ListNode slow = head;
while( fast!=null && fast.next!= null ){
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
}
提交结果:
3. 合并两个有序链表(lc21)
题目描述:
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例 1:
输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.
示例 2:
输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 (序列化形式:[4,5,6])
由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。
提示:
给定链表的结点数介于 1 和 100 之间。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/middle-of-the-linked-list
解题思路:
1. 如果两个链表中有一个为空,则返回另外一个
2. 遍历两个链表,将较小的节点往新链表中尾插,注意:为了实现方便,新链表使用带头节点的链表
3. 循环结束之后,肯定有一个链表先走到末尾,将另外一个不空的链表直接连接在tail之后
代码实现:
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
/*if(list1 == null && list2 == null){
return null;
}
if(list1 == null){
return list2;
}
if(list2 == null){
return list1;
}*/
ListNode node = new ListNode(5);
ListNode tmp = node;
while(list1 != null && list2 != null){
if(list1.val <= list2.val){
tmp.next = list1;
tmp = tmp.next;
list1 = list1.next;
}else {
tmp.next = list2;
tmp = tmp.next;
list2 = list2.next;
}
}
if(list1 != null) {
tmp.next = list1;
}
if(list2 != null) {
tmp.next = list2;
}
return node.next;
}
}