203. 移除链表元素
时间复杂度 O(n) 空间复杂度 O(1)
要求: 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
思路
采用虚拟头节点的方法,不需要单独处理头节点==val时的情况。
处理的是当前节点的后一个即cur.next,所以要判断的是cur.next!= null,如果存在cur.next.val == val,那么则移除cur.next节点,如图,链表中移除D节点是将其C节点的指针指向E节点,C.next = C.next.next。
/**
* @param {ListNode} head
* @param {number} val
* @return {ListNode}
*/
var removeElements = function(head, val) {
let ret = new ListNode(0, head) //虚拟头节点
let cur = ret
while(cur.next!= null){
if(cur.next.val == val){
cur.next = cur.next.next
}else{
cur = cur.next
}
}
return ret.next
};
707. 设计链表
要求:在链表类中实现这些功能:
- get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
- addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
- addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
- addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
- deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。
思路
还不熟练,找了很久的bug
var MyLinkedList = function() {
this.head = new ListNode(0, null)
this.size = 0
};
/**
* @param {number} index
* @return {number}
*/
MyLinkedList.prototype.get = function(index) {
if(index<0 || index>this.size-1){
return -1
}
let cur = this.head.next
while(index--){
cur = cur.next
}
return cur.val
};
/**
* @param {number} val
* @return {void}
*/
MyLinkedList.prototype.addAtHead = function(val) {
this.addAtIndex(0, val)
};
/**
* @param {number} val
* @return {void}
*/
MyLinkedList.prototype.addAtTail = function(val) {
this.addAtIndex(this.size, val)
};
/**
* @param {number} index
* @param {number} val
* @return {void}
*/
MyLinkedList.prototype.addAtIndex = function(index, val) {
if(index >this.size) return
if(index < 0) index = 0
let cur = this.head
while(index--){
cur = cur.next
}
let tmp = cur.next
let node = new ListNode(val, tmp)
cur.next = node
this.size++
console.log(this.head.next)
};
/**
* @param {number} index
* @return {void}
*/
MyLinkedList.prototype.deleteAtIndex = function(index) {
if(index < 0 || index >=this.size) return
let cur = this.head
while(index--){
cur = cur.next
}
cur.next = cur.next.next
this.size--
};
/**
* Your MyLinkedList object will be instantiated and called as such:
* var obj = new MyLinkedList()
* var param_1 = obj.get(index)
* obj.addAtHead(val)
* obj.addAtTail(val)
* obj.addAtIndex(index,val)
* obj.deleteAtIndex(index)
*/
206. 反转链表
要求:给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
思路
1.双指针法
链表反转其实只需要修改next指针指向
首先定义一个pre指针,初始化为null,cur指针指向head;
然后就开始循环了,需先将cur.next用tmp指针保存,因为后面需要修改cur.next指针的指向;
将cur.next指向pre,则是直接将链表的第一个节点反转;
继续向前移动pre、cur,直到cur指向null,返回pre即可。
时间复杂度 O(n) 空间复杂度 O(1)
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
let pre = null, cur = head
while(cur != null){
let tmp = cur.next
cur.next = pre
pre = cur
cur = tmp
}
return pre
};
2.递归法
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverse = function(pre, cur) {
if(!cur) return pre;
const temp = cur.next;
cur.next = pre;
// 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步
// pre = cur;
// cur = temp;
return reverse(cur, temp);
}
var reverseList = function(head) {
return reverse(null, head);
};