目录
1.移除链表元素(203)
题目: 给你一个链表的头节点 head 和一个整数val,请你删除链表中所有满足Node.val == val的节点,并返回新的头节点。
输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]
方法一:这道题是删除链表中所有等于val的元素,需要考虑两种情况。
- 头节点是要删除的节点,这时候我们循环判断head的值,但是head不能为空,这样就是链表中没元素了。
- 头节点确定不是要删除的结点,我们就遍历链表判断后面的值,因为我们找的是前驱结点,所以我们要保证待删除的结点不能为空,否则会造成空指针异常。造成了pre遍历到最后一个结点,已经没有要判断的结点了。
public ListNode removeElements(ListNode head, int val) {
while(head != null && head.val == val){
head = head.next;
}
for (ListNode pre = head; pre != null; pre = pre.next) {
while(pre.next != null && pre.next.val == val) {
pre.next = pre.next.next;
}
}
return head;
}
方法二:递归
三步骤:首先,判断是否能拆分:这道题可以拆成head.val == val和剩下结点是否有val
其次:拆封后解决思路相同
最后:存在终止条件
- 理解函数的语义:传入头结点和待删除的值,函数就能删除所有等于val的元素
- 将链表分为头结点和其他结点,因为我们只能知道头结点。
- 把除头结点之后的链表的删除工作交给子函数运行,子函数就能把元素删除
- 判断头结点是否为需要删除的结点,若是,返回头结点的下一个结点;反之,返回头结点
public ListNode removeElements(ListNode head, int val) {
//链表内没有元素,终止条件
if (head == null){
return null;
}
head.next = removeElements(head.next,val);
//删除操作
if (head.val == val){
return head.next;
}
return head;
}
2.删除排序链表中的重复元素(83)
题目:给定一个已排序的链表的头head, 删除所有重复的元素,使每个元素只出现一次 。返回已排序的链表。
输入:head = [1,1,2]
输出:[1,2]
方法一:
- 这道题我们不知道要删除的元素是谁,所以我们需要引入两个指针去比较。
- 当pre.val == cur.val,说明pre是第一个重复的元素,所以我们保留这个元素,而cur是要删除的元素,所以pre.next = cur.next,然后让cur向后走,等于走一步删一步。
- 当pre.val!=cur.val,说明他们不是要删除的元素,一起向后走。直到cur==null,循环完毕,返回头结点。
public ListNode deleteDuplicates(ListNode head) {
//当链表为空或者只有一个元素的时候,不可能有重复的元素
if (head == null || head.next == null){
return head;
}
ListNode pre = head;
ListNode cur = pre.next;
while(cur != null){
if (pre.val != cur.val) {
pre = pre.next;
cur = cur.next;
} else {
pre.next = cur.next;
cur = cur.next;
}
}
return head;
}
方法二:递归
- 将题目拆封成头结点和之后的结点两部分。
- 理解函数语义:一个有序的链表,传入头结点,可以将重复元素删除,只保留一个重复的元素,返回删除后的头结点
- 第二个结点之后的删除交给子函数去运行。
- 由于我们只知道头结点,所以我们将当前的头结点和返回后的头结点相比较,如果相等,就把当前头结点删了,返回head.next;反之,返回head。
public ListNode deleteDuplicates(ListNode head) {
if (head == null || head.next == null) {
return head;
}
head.next = deleteDuplicates(head.next);
if (head.val == head.next.val) {
return head.next;
}
return head;
}
3.删除排序链表中的重复元素 II(82)
题目:给定一个已排序的链表的头head,删除原始链表中所有重复数字的节点,只留下不同的数字。返回已排序的链表 。
输入:head = [1,2,3,3,4,4,5]
输出:[1,2,5]
方法一:
- 这里引入了三个指针.如果两个指针的话,当pre指向重复元素的话,就删不掉了。因为重复元素都要删除,所以pre要指向不重复的元素,我们就让剩下两个指针判断结点是否重复。
- 当cur.val != next.val,三指针同时向后移动
- 当cur.val == next.val,循环让next向后移动,移动到第一个和cur不相等的元素,意味着pre之后next之前的元素都是要删除的元素。所以pre.next = next把元素删除
- 删除后cur和next向后移动一个结点。pre不能向后移动,因为有可能cur和next依旧相等。
public ListNode deleteDuplicates(ListNode head) {
ListNode dummyHead = new ListNode();
dummyHead.next = head;
ListNode pre = dummyHead;
ListNode cur = pre.next;
while(cur != null) {
ListNode next= cur.next;
if (next == null){
//链表内只有一个节点或者链表遍历完了
break