# 链表 LC.19/83/92/61/143/21/160/141/147/138/142

### LC.19 Remove Nth Node Form End of List

#### Description

Given a linked list, remove the n-th node from the end of list and return its head.

Example:

``````Given linked list: 1->2->3->4->5, and n = 2.

After removing the second node from the end, the linked list becomes 1->2->3->5.
``````

Note:

Given n will always be valid.

Could you do this in one pass?

#### Solution

• one-pass (trivial) 实际上有两个指针，所以是2-pass
``````# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
count = 1
while count < n:
temp = temp.next
count += 1
if temp.next == None:
return target.next
else:
temp = temp.next
while temp.next != None:
target = target.next
temp = temp.next
target_d = target.next
target.next = target_d.next

``````
• recursive

``````# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
rec = self.helper(head, n)
if rec == n:

def helper(self, head: ListNode, n: int) -> int:
if head.next == None:
return 1
rec = self.helper(head.next, n)
if rec == n:
return rec + 1
``````

递归做法，实际上这道题本质上必须遍历整个链表直到最后一个node，所以用递归的方法查看之后还剩多少个元素，如果正好是n的话，那么当前的结点(倒数第n+1个)的下一个结点(倒数第n个)就需要被删除。和另外一个方法比起来并不会增大memory的占用。runtime还更低（我猜是因为少了一个移动的指针）

### LC.83 Remove Duplicates from Sorted List

#### Description

Given a sorted linked list, delete all duplicates such that each element appear only once.

Example 1:

``````Input: 1->1->2
Output: 1->2
``````

Example 2:

``````Input: 1->1->2->3->3
Output: 1->2->3
``````

#### Solution

• straight solution (两个指针)

• ``````# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
if head == None:
while node_b.next != None:
if node_b.val != node_b.next.val:
node_a.next = node_b.next
node_a = node_a.next
node_b = node_b.next
if not node_a == node_b:
node_a.next = node_b.next
``````

或者一个指针：

``````class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
while temp != None and temp.next != None:
if temp.val == temp.next.val:
temp.next = temp.next.next
else:
temp = temp.next
``````
• 递归做法

``````class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
if head == None or head.next == None:
else:
``````

### LC. 92 Reversed Linked List

Reverse a linked list from position m to n. Do it in one-pass.

Note: 1 ≤ mn ≤ length of list.

Example:

``````Input: 1->2->3->4->5->NULL, m = 2, n = 4
Output: 1->4->3->2->5->NULL
``````

#### Solution

• 直接从前往后走，只要还在reverse的范围内，看见一个拎出来一个，添加到旁边的翻转新链表的表头。所有需要翻转的都翻转完之后，把新的链表插在原来的链表里面

``````class Solution(object):
def reverseBetween(self, head, m, n):
"""
:type m: int
:type n: int
:rtype: ListNode
"""
holder = ListNode(-1)
count = 1
while count < m:
count += 1
new = None
while count < n+1:
if count == m:
tail = new
count += 1
tail.next = temp
return holder.next

``````

在表的最前面加一个holder可以方便计数，并且corner case少了很多！！第17-20行是翻转表头的操作

• 递归做法

``````class Solution(object):
def reverseBetween(self, head, m, n):
"""
:type m: int
:type n: int
:rtype: ListNode
"""
self.successor = None
if m == 1:

def reverseHelper(self, head, m):
if m == 1:
new = self.reverseHelper(head.next, m-1)
return new
``````

是LC.206的变形，递归的时候加入一个变量k，reverse当前链表的前k个元素。递归现在还写得乱七八糟的！！

### LC. 61 Rotate List

Given a linked list, rotate the list to the right by k places, where k is non-negative.

Example 1:

``````Input: 1->2->3->4->5->NULL, k = 2
Output: 4->5->1->2->3->NULL
Explanation:
rotate 1 steps to the right: 5->1->2->3->4->NULL
rotate 2 steps to the right: 4->5->1->2->3->NULL
``````

Example 2:

``````Input: 0->1->2->NULL, k = 4
Output: 2->0->1->NULL
Explanation:
rotate 1 steps to the right: 2->0->1->NULL
rotate 2 steps to the right: 1->2->0->NULL
rotate 3 steps to the right: 0->1->2->NULL
rotate 4 steps to the right: 2->0->1->NULL
``````

#### Solution

• 直接解：

先数一下一共有多少个元素，再用总数减去模k的值求left rotate多少个。找到新的头元素，把tail和原来的头元素串起来就好了

``````class Solution(object):
def rotateRight(self, head, k):
"""
:type k: int
:rtype: ListNode
"""
count = 1
while key.next:
count += 1
key = key.next
k = count - k % count

while k > 1:
k -= 1
return new
``````

### LC. 143 Reorder List

Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→LnL1→Ln-1→L2→Ln-2→…

You may not modify the values in the list's nodes, only nodes itself may be changed.

Example 1:

``````Given 1->2->3->4, reorder it to 1->4->2->3.
``````

Example 2:

``````Given 1->2->3->4->5, reorder it to 1->5->2->4->3.
``````

#### Solutions

• 这题还蛮容易错的，主要是reverse list的时候不能反转原链表，这样正序的链表就没了；首先找到链表中点，然后反转后一半的链表，前一半的链表a和后一半的反转链表b交替插在一块儿就好了

``````class Solution(object):
"""
:rtype: None Do not return anything, modify head in-place instead.
"""
return
a = b = head
move_a = False
while b.next:
b = b.next
if move_a == True:
a = a.next
move_a = False
else:
move_a = True
list_b = self.reverseList(a.next)
a.next = None
while list_b:
a_temp = list_a.next
b_temp = list_b.next
list_a.next = list_b
list_b.next = a_temp
list_a = a_temp
list_b = b_temp
return

return new
``````

优化：

第7-17行可以优化成如下，复杂度降了好多，我也不确定为什么，大概是更改变量的次数变少了。。

`````` while b.next.next:
b = b.next.next
a = a.next
if not b.next:
break
``````
• 感觉这道没必要用递归，因为每次都得找最尾端的元素，性价比很低 （？

### LC. 21. Merge Two Sorted Lists

Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.

Example:

``````Input: 1->2->4, 1->3->4
Output: 1->1->2->3->4->4、
``````

#### Solutions

• 直接解（超级丑）

• ``````class Solution(object):
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
if not l1:
return l2
if not l2:
return l1
if l1.val <= l2.val:
l1 = l1.next
else:
l2 = l2.next
while l1 and l2:
if l1.val <=l2.val:
key.next = l1
key = key.next
l1 = l1.next
else:
key.next = l2
key = key.next
l2 = l2.next
if l1 or l2:
key.next = l1 if l1 else l2
``````
• 递归（似乎叫动态规划了这里)

``````class Solution(object):
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
if not l1:
return l2
if not l2:
return l1
if l1.val <= l2.val:
l1.next = self.mergeTwoLists(l1.next, l2)
return l1
else:
l2.next = self.mergeTwoLists(l1, l2.next)
return l2
``````

### LC. 160. Intersection of Two Linked Lists

Write a program to find the node at which the intersection of two singly linked lists begins.

Notes:

If the two linked lists have no intersection at all, return null.
The linked lists must retain their original structure after the function returns.
You may assume there are no cycles anywhere in the entire linked structure.
Your code should preferably run in O(n) time and use only O(1) memory.

#### Solutions

• 一个超简洁的解法：

``````class Solution(object):
"""
:rtype: ListNode
"""
return None

while a != b:
a = headB if a == None else a.next
b = headA if b == None else b.next
return a
``````
• 思路是a+b = b+a，如果遍历两遍，他们会同时到达终点，自动对齐

• 第12行很重要，这和两个链表intersect的方式有关，如果只是一个node的val相同，这个语句是false的。必须后面是同一个链才是true

• 第12行到14行的另外一种错误写法：

``````if a.next == None:
if b.next == None:
a = a.next
b = b.next
``````

原因是第2/4行会导致链表的终端不指向None，会形成一个环形链表，这样后到达的指针就出不来了！

### LC. 141. Linked List Cycle

Given a linked list, determine if it has a cycle in it.

To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.

Example 1:

Input: head = [3,2,0,-4], pos = 1
Output: true
Explanation: There is a cycle in the linked list, where tail connects to the second node.

#### Solutions

• 一个作弊解法：（which 我觉得肯定有毛病）

``````class Solution(object):
"""
:rtype: bool
"""
marker = ListNode(-1)
return False
while head.next and not head.next == marker:
return False
return True
``````

走过的点就标记为走过，通过把它指向一个marker点。但这样链表就被损坏了

• 龟兔赛跑的解法：一个指针以步长1移动，另一个以步长2移动。如果有环的话，fast指针一定会追上另外一个

``````class Solution(object):
"""
:rtype: bool
"""
try:
while not slow == fast:
slow = slow.next
fast = fast.next.next
return True
except:
return False
``````

这里用try/except的写法写会更快，不必每次显式地检查是否有指针到达终点

class Solution(object):
"""
:rtype: ListNode
"""
helper = ListNode(0)
pre = helper

``````    while head:
if pre.next and head.val < pre.next.val:
pre = helper
while pre.next and head.val >= pre.next.val:
pre = pre.next

return helper.next
``````

### LC. 138 Copy List with Random Pointer

A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.

Return a deep copy of the list.

#### Solution

• 交替索引

``````class Solution(object):
"""
:rtype: Node
"""
return None
helper = Node(0, head, None)

new = Node(0, None, None)
new = new.next

return helper.random
``````
• keep an hash table for each node in the list: 原链表的每一个node索引到它的copy上，然后再次从头到位遍历原来的链表，写入新结点们的next和random

``````class Solution(object):
"""
:rtype: Node
"""
return None
copy = dict()
m = n = head
while m:
copy[m] = Node(m.val, m.next, m.random)
m = m.next
while n:
copy[n].next = copy.get(n.next)
copy[n].random = copy.get(n.random)
n = n.next
``````

需要注意的是，在第15/16行都用的是dict.get(key)而不是直接dict[key], 这是为了当key等于None的时候，返回default value None而不是报错。如果事先定义copy[None]=None的话，这两处也可以直接用dict[key]

这种方法还有一个很trick的只遍历一次的写法，使用collections.defaultdict来访问(及创建)存在(或不存在)的结点

``````class Solution(object):
"""
:rtype: Node
"""
copy = collections.defaultdict(lambda: Node(0, None, None))
copy[None] = None
while m:
copy[m].val = m.val
copy[m].next = copy[m.next]
copy[m].random = copy[m.random]
m = m.next
``````

注意这里的12/13行是直接调用的方式，且在第9行定义了key=None的情况。这是因为现在的default是RandomNode(0)而不是None了

### LC. 142 Linked List Cycle II

Given a linked list, return the node where the cycle begins. If there is no cycle, return `null`.

To represent a cycle in the given linked list, we use an integer `pos` which represents the position (0-indexed) in the linked list where tail connects to. If `pos` is `-1`, then there is no cycle in the linked list.

#### Solution

• hash table that records the visited nodes

``````class Solution(object):
"""
:rtype: ListNode
"""
info = dict()
while m:
if not info.get(m):
info[m] = True
else:
return m
m = m.next
return None
``````
• hare-tortoise method

``````class Solution(object):
"""
:rtype: ListNode
"""
fast = slow = helper = head
try:
fast = fast.next.next
slow = slow.next
while not fast == slow:
fast = fast.next.next
slow = slow.next
while not helper == slow:
helper = helper.next
slow = slow.next
return helper
except:
return None
``````

这里最重要的就是fast步长=2，slow=1。。。这样保证了fast恰好超slow一圈