给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
分析:
- 如果head.val = val,则需要跳过当前head以及和head相连的所有val相同的节点
- 声明l两个变量cur、pre = head,老head作为新的head返回。如果整个单链表中元素都相同,并且val都相等,那么跳过之后的head为null,就作为null进行返回。
- 如果剩余节点中,依然有val相等的,则继续遍历,如果相等。则pre.next = cur.next一起向下移。
- 如果不相等,pre = cur
- 最后,不论是否相等,cur = cur.next;保证链表完整性,并且可以顺畅循环。
代码:
//删除链表中给定值
public static ListNode removeValue(ListNode head, int value) {
while (head != null) {
if (head.val != value) {
break;
}
head = head.next;
}
ListNode cur = head;
ListNode pre = head;
while (cur != null) {
if (cur.val == value) {
pre.next = cur.next;
}else{
pre = cur;
}
cur = cur.next;
}
return head;
}
对数器
//生成单链表的同时生成数组,根据要删除的值,从数组转换成LinkedList。
public static ListNode generateRandomNode(int max, int len, int removeValue, List<Integer> testList) {
int[] arr = new int[len];
int index = 0;
int headValue = (int)( Math.random() * max) + 1;
ListNode head = new ListNode(headValue);
ListNode pre = head;
ListNode sout = head;
arr[index] = headValue;
index++;
len--;
while (len != 0) {
int value = (int)( Math.random() * max) + 1;
ListNode cur = new ListNode(value);
pre.next = cur;
pre = cur;
arr[index++] = value;
len--;
}
for (int i = 0; i < arr.length; i++) {
if (arr[i] != removeValue) {
testList.add(arr[i]);
}
}
return head;
}
测试类
public static boolean test(List<Integer> testList, ListNode head, int value) {
ListNode pre = head;
for (int i = 0; i < testList.size(); i++) {
if ((testList.get(i) != pre.val) || testList.contains(value)) {
return false;
}
head = head.next;
}
return true;
}
总流程
//生成随机链表的同时生成随机数组
//将数组遍历,去掉数组中对应的value元素,将剩余元素放入LinkedList
public static void main(String[] args) {
int maxNum = 50;
int testNum = 2000000;
for (int i = 0; i < testNum; i++) {
//每次随机数组长度
int len = (int) (Math.random() * 5) + 2;
//每次随机要remove的值
int removeValue = (int) (Math.random() * maxNum);
List<Integer> testList = new LinkedList<>();
//生成链表节LinkedList
ListNode listNode = generateRandomNode(maxNum, len, removeValue, testList);
//移除链表中对应值
ListNode listNode1 = removeValue(listNode, removeValue);
//对数器
if (!test(testList, listNode1, removeValue)) {
System.out.println("测试失败");
}
}
}
如果不给定头结点,只给定要删除的节点,可以进行删除么?
如果给定的节点,不是链表中的尾节点,可以用取巧的方式进行删除。
首先,获取给定节点的next节点的值,将next的值覆盖要删除的节点,将next置为null,将删除节点的next指针指向next.next。
这种方式比较取巧,因为是将要删除节点的值进行了覆盖操作,删除的是next节点。
那如果要删除的是链表的尾节点呢?还可以正常进行删除么?
删除不了!!!!!,根本无法删除,因为是单链表,不能获取到last指针,而又无法将对象置为null,因为传递的是对象的引用地址,对对象本身的修改不会影响原来的对象,如果可以获取到属性中的next指针、last指针则可以进行删除。
但是!!就算可以删除也不建议删除,假设链表 1 -》 2 -》 3 -》 4,要删除的节点是3。
如果在项目中,还更加要考虑,如果next节点(4)的数据是保密性质的,copy不出来怎么办?如果3 、4 节点在不同的服务,对外提供数据,就算可以copy出来,将要删除的节点进行了覆盖,那4节点的引用怎么办?所以,如果只给定要删除的值,不建议进行删除!!