前文
继上篇链表简单篇结束,我们继续分享完剩余的中等难度篇。话不多说,让我们开始吧!
2. Add Two Numbers
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
class Solution(object):
def addTwoNumbers(self, l1, l2):
"""
题意是求两个链表的各个数相加的和,如果高于10,则往下一个数+1
解法围绕divmod这个求解+余数来完成,如果有carry值,则表明高于10,此时carry为1
所以每个节点就是v1+v2+carry的和
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
root = n = ListNode(0)
carry = 0
while l1 or l2 or carry:
v1 = v2 = 0
if l1:
v1 = l1.val
l1 = l1.next
if l2:
v2 = l2.val
l2 = l2.next
carry, val = divmod(v1 + v2 + carry, 10)
n.next = ListNode(val)
n = n.next
return root.next
19. Remove Nth Node From End of List
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
class Solution(object):
"""
定义快慢指针,让快指针先跑n个格,这样当快指针跑完的时候,慢指针刚好停在从end开始的n个格,然后直接跳过即可
Runtime: 16 ms, faster than 95.44% of Python online submissions for Remove Nth Node From End of List.
Memory Usage: 11.8 MB, less than 26.64% of Python online submissions for Remove Nth Node From End of List.
"""
def removeNthFromEnd(self, head, n):
"""
:type head: ListNode
:type n: int
:rtype: ListNode
"""
fast = slow = head
for _ in range(n):
fast = fast.next
if not fast:
return head.next
while fast.next:
fast = fast.next
slow = slow.next
slow.next = slow.next.next
return head
class Solution2(object):
"""
用递归来完成,这个思路也是很强。当递归到链表结尾时,此时的i即表示最后1个数的开始索引即1,当i>n,即表示位于要删除的前一位,
然后跳过即表示删除。最后再判断当n过大的情况,直接反馈head.next
Runtime: 24 ms, faster than 62.50% of Python online submissions for Remove Nth Node From End of List.
Memory Usage: 11.9 MB, less than 7.94% of Python online submissions for Remove Nth Node From End of List.
"""
def removeNthFromEnd(self, head, n):
"""
:type head: ListNode
:type n: int
:rtype: ListNode
"""
def index(node):
if not node:
return 0
i = index(node.next) + 1
if i > n:
node.next.val = node.val
return i
index(head)
return head.next
24. Swap Nodes in Pairs
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
class Solution(object):
"""
pre is the previous node. Since the head doesn't have a previous node, I just use self instead. Again,
a is the current node and b is the next node.To go from pre -> a -> b -> b.next to pre -> b -> a -> b.next
Runtime: 16 ms, faster than 93.29% of Python online submissions for Swap Nodes in Pairs.
Memory Usage: 11.8 MB, less than 50.85% of Python online submissions for Swap Nodes in Pairs.
"""
def swapPairs(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
pre,pre.next = self,head
while pre.next and pre.next.next:
a = pre.next
b = a.next
pre.next, b.next, a.next = b,a,b.next
pre = a
return self.next
61. Rotate List
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
"""
题目需要根据给定的数字依次反转链表,根据如下代码还是蛮清晰的,先求出总长度n,然后求出需要从
哪个位置开始反转,要注意的是k%n来求余避免k>n的情况!接着通过tail=tail.next找到开始反转的上一个位置。
比较难理解的是最后一步:先指定开始反转的tail.next,然后把该链表的tail.next重置为None,这样返回的结果就截止在反转,
最后再把pre这原本指向链表最后位置的重置到开头,形成一个循环!
Runtime: 20 ms, faster than 95.00% of Python online submissions for Rotate List.
Memory Usage: 11.6 MB, less than 94.65% of Python online submissions for Rotate List.
"""
def rotateRight(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
n ,pre ,current = 0 ,None ,head
while current:
pre ,current = current ,current.next
n += 1
while not n or not k % n:
return head
tail = head
for i in range( n - k % n -1):
tail = tail.next
next, tail.next, pre.next = tail.next, None, head
return next
82. Remove Duplicates from Sorted List II
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
class Solution(object):
"""
题意是要删除重复项,指定两个节点指向head,然后判断当前head和head.next值是否相等,相等则继续;
整体的思路是比较清晰的,就是指针的指向相对比较复杂
Runtime: 32 ms, faster than 64.44% of Python online submissions for Remove Duplicates from Sorted List II.
Memory Usage: 11.7 MB, less than 70.21% of Python online submissions for Remove Duplicates from Sorted List II.
"""
def deleteDuplicates(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
tmp = dummy = ListNode(0)
tmp.next = head
while head and head.next:
if head.val == head.next.val:
while head and head.next and head.val == head.next.val:
head = head.next
head = head.next
dummy.next = head
else:
dummy = dummy.next
head = head.next
return tmp.next
86. Partition List
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
class Solution(object):
"""
这个解法太简洁易懂了!一开始我的想法就是只定义一条链表,但我发现没办法插入小于x的值到链表最前方,
看到这个解法直接定义两条链表,小的归小的,大的归大的,最后合并即可,简直太强!
Runtime: 20 ms, faster than 90.18% of Python online submissions for Partition List.
Memory Usage: 11.8 MB, less than 68.50% of Python online submissions for Partition List.
"""
def partition(self, head, x):
"""
:type head: ListNode
:type x: int
:rtype: ListNode
"""
l1 = h1 = ListNode(0)
l2 = h2 = ListNode(0)
while head:
if head.val < x:
l1.next = head
l1 = l1.next
else:
l2.next = head
l2 = l2.next
head = head.next
l2.next = None
l1.next = h2.next
return h1.next
92. Reverse Linked List II
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
class Solution(object):
"""
题目要求按照索引m和n将这之间的链表反转,所以思路很清晰,先定位到m的位置,然后对到n之间的链表用单链表反转
也就是leetcode第206的方法来做,反转后指定链表的指向即可
Runtime: 16 ms, faster than 92.06% of Python online submissions for Reverse Linked List II.
Memory Usage: 12.1 MB, less than 11.07% of Python online submissions for Reverse Linked List II.
"""
def reverseBetween(self, head, m, n):
"""
:type head: ListNode
:type m: int
:type n: int
:rtype: ListNode
"""
if m == n:
return head
dummyNode = ListNode(0)
dummyNode.next = head
pre = dummyNode
for i in range(m - 1):
pre = pre.next
# reverse the [m, n] nodes
reverse = None
cur = pre.next
for i in range(n - m + 1):
next = cur.next
cur.next = reverse
reverse = cur
cur = next
pre.next.next = cur
pre.next = reverse
return dummyNode.next
109. Convert Sorted List to Binary Search Tree
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
# Definition for a binary tree node.
class TreeNode(object):
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution(object):
"""
题意是将有序链表转为二叉树,因为没有要求二叉树是有序的,所以相对简单很多。
先依次将链表的值插入列表,最后利用递归直接根据长度的一半生成二叉树即可,效率也是非常快
Runtime: 100 ms, faster than 99.58% of Python online submissions for Convert Sorted List to Binary Search Tree.
Memory Usage: 23.9 MB, less than 38.87% of Python online submissions for Convert Sorted List to Binary Search Tree.
"""
def sortedListToBST(self, head):
"""
:type head: ListNode
:rtype: TreeNode
"""
ls = []
while head:
ls.append(head.val)
head = head.next
return self.helper(ls, 0, len(ls) - 1)
def helper(self, ls, start, end):
if start > end:
return None
if start == end:
return TreeNode(ls[start])
mid = (start + end) >> 1
root = TreeNode(ls[mid])
root.left = self.helper(ls, start, mid - 1)
root.right = self.helper(ls, mid + 1, end)
return root
class Solution2(object):
"""
解法二则是定义快慢指针,快指针定位结尾,慢指针定位中间,然后根据中间和头部分别生成树的右边和左边,可以说和第一种差别不大
Runtime: 120 ms, faster than 64.52% of Python online submissions for Convert Sorted List to Binary Search Tree.
Memory Usage: 18.1 MB, less than 99.23% of Python online submissions for Convert Sorted List to Binary Search Tree.
"""
def sortedListToBST(self, head):
"""
:type head: ListNode
:rtype: TreeNode
"""
if not head:
return
if not head.next:
return TreeNode(head.val)
dummy = ListNode(0)
dummy.next = head
slow, fast = dummy, head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
root = TreeNode(slow.next.val)
root.right = self.sortedListToBST(slow.next.next)
slow.next = None
root.left = self.sortedListToBST(head)
return root
138. Copy List with Random Pointer
# Definition for a Node.
class Node(object):
def __init__(self, val, next, random):
self.val = val
self.next = next
self.random = random
class Solution(object):
"""
先构造字典,将老链表和新链表一一对应,这样就构造了一个纯next的链表,然后再循环即可
Runtime: 392 ms, faster than 33.67% of Python online submissions for Copy List with Random Pointer.
Memory Usage: 14.6 MB, less than 100.00% of Python online submissions for Copy List with Random Pointer.
"""
def copyRandomList(self, head):
"""
:type head: Node
:rtype: Node
"""
nodeDict = dict()
new_head = dummy = Node(0, None, None)
pointer = head
while pointer:
val_node = Node(pointer.val, pointer.next, None)
nodeDict[pointer] = val_node
new_head.next = val_node
new_head, pointer = new_head.next, pointer.next
while head:
if head.random:
nodeDict[head].random = nodeDict[head.random]
head = head.next
return dummy.next
142. Linked List Cycle II
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head: return None
visited = set()
while head:
if head in visited:
return head
visited.add(head)
head = head.next
return None
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
slow, fast = head, head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
if fast == slow:
break
if not fast or not fast.next:
return None
slow = head
while slow != fast:
slow = slow.next
fast = fast.next
return fast
143. Reorder List
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
"""
For linked list 1->2->3->4-5, the code first makes the list to be 1->2->3->4<-5 and 4->None, then make 3->None,
for even number linked list: 1->2->3->4, make first 1->2->3<-4 and 3->None, and lastly do not forget to make 2->None.
Runtime: 84 ms, faster than 84.57% of Python online submissions for Reorder List.
Memory Usage: 29.5 MB, less than 93.87% of Python online submissions for Reorder List.
"""
def reorderList(self, head):
"""
:type head: ListNode
:rtype: None Do not return anything, modify head in-place instead.
"""
if not head:
return
# ensure the first part has the same or one more node
fast, slow = head.next, head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
# reverse the second half
p = slow.next
slow.next = None
node = None
while p:
nxt = p.next
p.next = node
node = p
p = nxt
# combine head part and node part
p = head
while node:
tmp = node.next
node.next = p.next
p.next = node
p = p.next.next #p = node.next
node = tmp
147. Insertion Sort List
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
class Solution(object):
"""
题意是插入排序 注释也是写的非常清楚了
Runtime: 156 ms, faster than 81.60% of Python online submissions for Insertion Sort List.
Memory Usage: 15.1 MB, less than 78.57% of Python online submissions for Insertion Sort List.
"""
def insertionSortList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
cur = dummy = ListNode(0)
while head:
if cur and cur.val > head.val: # reset pointer only when new number is smaller than pointer value
cur = dummy
while cur.next and cur.next.val < head.val: # classic insertion sort to find position
cur = cur.next
cur.next, cur.next.next, head = head, cur.next, head.next # insert
return dummy.next
148. Sort List
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
class Solution(object):
"""
题意是对链表排序,用归并排序来做链表,也是相当易懂的
Runtime: 236 ms, faster than 52.04% of Python online submissions for Sort List.
Memory Usage: 26.3 MB, less than 65.08% of Python online submissions for Sort List.
"""
def merge(self, h1, h2):
dummy = tail = ListNode(None)
while h1 and h2:
if h1.val < h2.val:
tail.next, tail, h1 = h1, h1, h1.next
else:
tail.next, tail, h2 = h2, h2, h2.next
tail.next = h1 or h2
return dummy.next
def sortList(self, head):
if not head or not head.next:
return head
pre, slow, fast = None, head, head
while fast and fast.next:
pre, slow, fast = slow, slow.next, fast.next.next
pre.next = None
return self.merge(*map(self.sortList, (head, slow)))
总结
本次分享到此,拜拜~