今日题目:
- 203. 移除链表元素
- 206. 反转链表
解题思想:
- 虚拟头结点
添加虚拟头结点
dummyHead
,操作链表的时候有利于链表操作的统一。
- 链表双指针
用两个指针,一个pre指针,一个cur指针。206反转链表这道题要想清楚的一个点,是循环终止的条件:反转最后pre指向原链表的最后一个节点,cur指向null,故循环结束的条件可以为
while(cur)
。除此之外,还需要一个临时变量temp,保存每次遍历中cur的值。
- 递归
反转链表可以拆解为两个问题,1 反转头结点 2. 反转除了头结点之外的剩余子节点,解决第二个小问的时候,问题还是可以拆解为,反转头结点和除头结点外的剩余子节点,最后只剩下一个最后一个节点
最后一个节点是不需要反转的。所以是存在最小子问题的
代码:
- 203 . 移除链表元素
//迭代
var removeElements = function(head, val) {
const dummyHead = new ListNode(0, head)
let cur = dummyHead
while(cur.next) {
if(cur.next.val == val) {
cur.next = cur.next.next
} else {
cur = cur.next
}
}
return dummyHead.next
};
//递归
var removeElements = function(head, val) {
if(!head) return null
head.next = removeElements(head.next, val)
return head = head.val == val?head.next:head
};
- 206 . 反转链表
//迭代
var reverseList = function(head) {
let pre = null
let cur = head
//这里注意循环结束的条件,反转最后,pre指向新的头结点,cur指向null
while(cur) {
let temp = cur.next
cur.next = pre
pre = cur
cur = temp
}
return pre
};
//递归
var reverseList = function(head) {
if(!head || !head.next) return head
const newHead = reverseList(head.next)
head.next.next = head
head.next = null
return newHead
};
总结:
链表问题迭代法不难,通常使用添加虚拟头结点来使操作链表方式统一。递归法做的时候,需要把大的问题拆解成小问题,想清楚到底哪些步骤是递归项、想清楚每一小步的细节。