算法--链表--移除链表元素
链表操作中,可以使用原链表来直接进行删除操作,也可以设置一个虚拟头结点再进行删除操作,接下来看一看哪种方式更方便。
题意:删除链表中等于给定值 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 输出:[]
1 解答
先写再看噢~
解答
这个讲得很详细👉代码随想录
1.1 思路-数组与链表的转换
心路历程:
- 需要写链表,但提供的 head 不是数组么,再看 js 的类型,输入输出都是 ListNode
- 那写代码,自测的时候直接用数组?显然不行
- 用链表思维写数组?整一个对象数组?
[{val: 'a',next: 1},{val: 'b',next: 2},{val: 'b',next: null}]去掉一个节点,next 指向再下一个节点,那去掉的这个节点还在数组内... 这么操作起来还是在整数组 - 先转换吧,把数组变成链表,把抽象的概念实际打印出来
class ListNode {
constructor(val, next) {
this.val = val === undefined ? 0 : val;
this.next = next === undefined ? null : next;
}
}
// 数组转链表
function arrayToListNode(array) {
if (array.length === 0) {
return null; // 如果数组为空,返回 null
}
let dummy = new ListNode(0); // 创建一个哑节点作为链表的起点
let current = dummy; // current 指针用于遍历链表
for (let val of array) {
current.next = new ListNode(val); // 为每个数组元素创建新节点并链接到当前节点后面
current = current.next; // 移动 current 指针到下一个节点
}
return dummy.next; // 返回哑节点的下一个节点作为链表的头节点
}
// 链表转数组
function listNodeToArray(head) {
const array = [];
let current = head;
while (current) {
array.push(current.val); // 将当前节点的值推入数组
current = current.next; // 移动到下一个节点
}
return array; // 返回转换后的数组
}
// 示例
const array = [1, 2, 6];
console.log(arrayToListNode(array));
// ListNode {
// val: 1,
// next: ListNode {
// val: 2,
// next: ListNode { val: 6, next: null }
// }
// }
const node = new ListNode(1, new ListNode(2, new ListNode(6)));
console.log(listNodeToArray(node));
// [1, 2, 6]
1.2 思路--链表去除节点
题目转换为
/**
* @param {ListNode} head
* @param {number} val
* @return {ListNode}
*/
var removeElements = function (head, val) {
// ...
};
const val = 6;
const array = [1, 2, 6, 3, 4, 5, 6];
const node = arrayToListNode(array); // 数组转链表
const returnNode = removeElements(node, val); // 删除节点
const returnArray = listNodeToArray(returnNode); // 链表转数组
console.log(returnArray);
要去掉某个节点时,应当是前一个的指针指向再后一个
var removeElements = function (head, val) {
// 加一个节点,如果head的第一个节点需要去掉,可以改加的这个节点的next
const startNode = new ListNode(0, head);
let currtentNode = startNode;
while (currtentNode?.next) {
// 要去掉某个节点时,应当是前一个的指针指向再后一个
if (currtentNode.next.val === val) {
currtentNode.next = currtentNode.next.next;
} else {
currtentNode = currtentNode.next;
}
}
return startNode.next;
};
时间复杂度 o(n)
空间复杂度 o(1)
测试注意用空数组 [] ,首个节点就需要删掉的数组测试下 [6,6,6]