Chapter 2: Linked List
Last updated
Was this helpful?
Last updated
Was this helpful?
除特别注明外,本文都使用以下所示的singly linked list。
Linked List的问题,核心在于操作 + 移动。
先考虑一轮操作,需要哪些变量,比如 prev
, next
对应操作 arr.push
,对linked list有 tail.next = curr
tail = tail.next
对应移动 idx += 1
,对linked list有 [current node] = [current node].next
,如果有 prev
变量则有 prev = prev.next
,如果有 next_node
变量则有 next_node = next_node.next
在修改linked list时,注意“先连后断”的原则。先更改原先 next 为 null 的节点,更新其next之后,就可以更改本来指向其next的节点,以此类推,最后处理的节点是需要删除next而不是更改next的
2.1.1 注意corner case ( curr == head
, curr == tail
, 或 curr == None
。凡是修改list但不改变每个node的value的操作,只需要考虑:谁的next
指针受到影响,那么就需要维护这些节点。
链表不能向后访问,所以记录prev
变量比记录curr
更普适,因为前者可以推出后者,而反之则不然。当前节点可以用prev.next
来表示,这样就不用维护两个变量。
2.1.2 遍历Linked list时,每次循环内只对一个或一对节点进行题意中的操作。(不要试图对下一个或者下一对进行操作)
e.g. Reverse the linked list and return the new head. ()
2.1.3 处理两个长度未必相等的linked list的问题,循环的条件一般用 while node1 and node2
, 再处理剩下非空的那个list。
对于涉及到Linked List头节点的操作,不妨用dummy = ListNode(0) dummy.next = head
来避开处理head发生变化的情况,最后用dummy.next
作为头节点即可。
对于寻找list某个特定位置的问题,不妨用 runner technique:chaser, runner = head, head;
chaser
与runner
以不同速率或不同起点前进,直到runner
满足一定条件时,结果由这两个共同决定。
e.g.1 Find the middle point of the linked list
交换两个node,有且仅有这两个node以及他们prev node的next指针会受到影响,那么根据2.1.1,需要a. 先交换两个prev node的next ; b. 再交换这两个node的next。无论这两个node的相对位置还是绝对位置,以上的处理总是正确的。
如果对靠前节点的处理必须在靠后节点之后,即倒序访问问题,则可视为recursion问题,或可以用stack
等效解决。
e.g Merge two sorted linked lists and return it as a new list.(
e.g. Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x. ( )
e.g.2 Find the kth to last element of a singly linked list. e.g.3 Given a circular linked list, return the node at the beginning of the loop. ( e.g.4 Given a list, rotate the list to the right by k places, where k is non-negative. ( 先查找,再拆分)
e.g. Given a linked list, swap every two adjacent nodes and return its head.( ) Given 1->2->3->4, you should return the list as 2->1->4->3.
e.g. 1 Given input ( 7->1->6 ) + ( 5->9->2 ), output 2->1->9. ( 无需递归顺序访问即可,因为靠前计算结果不依赖于靠后节点) e.g.2 Given input ( 6->1->7 ) + ( 2->9->5 ), output 9->1->2. ( 用递归或stack处理,因为靠前计算结果依赖于后面的计算结果)