(原来整理了部分,参考这篇博客http://blog.csdn.net/tinkle181129/article/details/79332331(博主知道啦),决定对这篇文章进行补充)
1. 链表的基础知识
2. 链表逆序 (LeetCode 206)
3. 链表中间段逆序(LeetCode 92)
4. 求两个链表的交点(LeetCode 160)
5. 排序链表的合并(LeetCode 21,23)
6. 链表求环(LeetCode 142)
7. 链表划分(LeetCode 86)
8. 复杂链表的深度拷贝(LeetCode 138)
9. 从链表中删除元素(LeetCode 83,82,237,203,19)
10. 链表求和(LeetCode2,445)
11. 交换链表节点(LeetCode24,25)
12. 旋转链表(LeetCode61)
13. 链表拆分(LeetCode725)
14. 改写链表(LeetCode109,328)
15. 链表重排序(LeetCode143)
16. 判断回文链表(LeetCode234)
17. 链表排序(LeetCode147,148)
链表的结构:
data为定义数据,next为下一个节点的位置。
python实现链表的方法为:
class Node:
'''
data: 节点保存的数据
_next: 保存下一个节点对象
'''
def __init__(self, data, pnext=None):
self.data = data
self._next = pnext
Reverse a singly linked list.
以0—>1—>2—>3为例
初始化,newhead=None
1. p=head:p=0—>1—>2—>3,head=head.next:head=1—>2—>3
2. p.next=newhead:p=0—>None
3. newhead=p:newhead=0—>None
循环直到head为空
class Solution(object):
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
new_head = None
while head:
p = head
head = head.next
p.next = new_head
new_head = p
return new_head
Reverse a linked list from position m to n. Do it in-place and in one-pass.
For example:
Given 1->2->3->4->5->NULL, m = 2 and n = 4,
return 1->4->3->2->5->NULL.
新建一个ListNode,先遍历前m-1个,m-n之间进行逆序,使用上面的方法
class Solution(object):
def reverseBetween(self, head, m, n):
"""
:type head: ListNode
:type m: int
:type n: int
:rtype: ListNode
"""
if m == n:
return head
new_head = ListNode(-1)
new_head.next = head
q = new_head
for i in range(m-1):
head = head.next
new_head = new_head.next
t = None
for i in range(n - m+1):
p = head
head = head.next
p.next = t
t = p
new_head.next = t
for i in range(n - m+1):
new_head = new_head.next
new_head.next = head
return q.next
Write a program to find the node at which the intersection of two singly linked lists begins.
For example, the following two linked lists:
A: a1 → a2
↘
c1 → c2 → c3
↗
B: b1 → b2 → b3
begin to intersect at node c1.
遍历两个链表分别统计其长度,让长链先走|m-n|步,则公共节点必定存在于后面,依次遍历,则第一个相等的点则为公共点。
class Solution(object):
def getIntersectionNode(self, headA, headB):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
p1 = headA
p2 = headB
m = 0
n = 0
while p1:
p1 = p1.next
m += 1
while p2:
p2 = p2.next
n += 1
if m > n:
for i in range(m - n):
headA = headA.next
else:
for i in range(n - m):
headB = headB.next
while headA:
if headA.val == headB.val:
return headA
headA = headA.next
headB = headB.next
return None
from Queue immport PriorityQueue
,优先队列在插入元素的时候已经对元素做了排序,把最小的元素放在队尾。 class Solution(object):
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
ans = ListNode(0)
p = ans
while l1 and l2:
if l1.val <= l2.val:
p.next = l1
l1 = l1.next
else:
p.next = l2
l2 = l2.next
p = p.next
if l1:
p.next = l1
elif l2:
p.next = l2
return ans.next
from Queue import PriorityQueue
class Solution(object):
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
q = PriorityQueue()
ans = ListNode(None)
temp = ans
for list1 in lists:
if list1:
q.put((list1.val, list1))
while q.qsize() > 0:
temp.next = q.get()[1]
temp = temp.next
if temp.next:
q.put((temp.next.val, temp.next))
return ans.next
leetcode141. Linked List Cycle
Given a linked list, determine if it has a cycle in it.
leetcode142. Linked List Cycle II
Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
Follow up:
Can you solve it without using extra space?
leetcode141. Linked List Cycle 判断链表中是否存在环
使用快慢指针方法,起始时,快慢指针都位于链表头部,快指针以慢指针两倍的速度向后遍历,若链表存在环,则快慢指针会相遇,否则不会相遇
注:当快指针指向None或者next为None,则说明不存在环
leetcode142. Linked List Cycle II 返回环的起始位置
还是使用快慢指针的方法,快指针以慢指针2倍的速度向后依次遍历
fast = 2slow,假设环的起始位置距离链表起始位置的距离为K,相遇点距离环的起始位置的距离为M,环的周长为L
则在相遇点:
lslow = K + M
lfast = K + M + nL
lfast = 2* lslow
整理上式可以得到:K=(n-1)L + L-M
即从相遇点开始,再走K步一定能回到环的起始点,故此时可以将lslow回到head,lfast在相遇点,二者以相同的速度(单倍速度)向后遍历,再次相遇的位置即为环起始的位置
leetcode141. Linked List Cycle 判断链表中是否存在环
class Solution(object):
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
fast = head
slow = head
while True:
if fast == None or fast.next == None:
return False
slow = slow.next
fast = fast.next.next
if fast and slow and fast.val == slow.val:
return True
leetcode142. Linked List Cycle II 返回环的起始位置
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if head == None or head.next == None:
return None
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if fast == slow:
break
if slow == fast:
slow = head
while slow != fast:
slow = slow.next
fast = fast.next
return slow
return None
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.
You should preserve the original relative order of the nodes in each of the two partitions.
For example,
Given 1->4->3->2->5->2 and x = 3,
return 1->2->2->4->3->5.
创建两个链表,一个用于存放小于x值的链表,另一个用于存放大于x值的链表,最后将两个链表合并
class Solution(object):
def partition(self, head, x):
"""
:type head: ListNode
:type x: int
:rtype: ListNode
"""
head1 = ListNode(0)
head2 = ListNode(0)
Tmp = head
phead1 = head1
phead2 = head2
while Tmp:
if Tmp.val < x:
phead1.next = Tmp
Tmp = Tmp.next
phead1 = phead1.next
phead1.next = None
else:
phead2.next = Tmp
Tmp = Tmp.next
phead2 = phead2.next
phead2.next = None
phead1.next = head2.next
return head1.next
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.
# Definition for singly-linked list with a random pointer.
# class RandomListNode(object):
# def __init__(self, x):
# self.label = x
# self.next = None
# self.random = None
利用字典存储每个结点的具体信息,技巧是使用python的collection.defaultdict(lambda: RandomListNode(0))
class Solution(object):
def copyRandomList(self, head):
"""
:type head: RandomListNode
:rtype: RandomListNode
"""
dict1 = collections.defaultdict(lambda: RandomListNode(0))
t = head
dict1[None] = None
while t:
dict1[t].label = t.label
dict1[t].next = dict1[t.next]
dict1[t].random = dict1[t.random]
t = t.next
return dict1[head]
class Solution(object):
def removeNthFromEnd(self, head, n):
"""
:type head: ListNode
:type n: int
:rtype: ListNode
"""
ans = ListNode(0)
ans.next = head
temp1 = ans
temp2 = ans
i = 0
while i < n:
temp1 = temp1.next
i += 1
while temp1.next:
temp1 = temp1.next
temp2 = temp2.next
temp2.next = temp2.next.next
return ans.next
class Solution(object):
def deleteDuplicates(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if head == None or head.next == None:
return head
ans = ListNode(0)
ans.next = head
pre = ans.next
cur = ans.next
while cur != None:
if pre.val != cur.val:
pre.next = cur
pre = pre.next
else:
pre.next = cur.next
cur = cur.next
return ans.next
class Solution(object):
def deleteDuplicates(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if head == None or head.next == None:
return head
ans = ListNode(0)
ans.next = head
pre = ans
cur = ans.next
while cur != None:
while cur.next and cur.next.val == pre.next.val:
cur = cur.next
if pre.next == cur:
pre = pre.next
else:
pre.next = cur.next
cur = cur.next
return ans.next
class Solution(object):
def deleteNode(self, node):
"""
:type node: ListNode
:rtype: void Do not return anything, modify node in-place instead.
"""
if node.next:
node.val = node.next.val
node.next = node.next.next
class Solution(object):
def removeElements(self, head, val):
"""
:type head: ListNode
:type val: int
:rtype: ListNode
"""
if head == None:
return None
pre = ListNode(0)
pre.next = head
ans = pre
cur = head
while cur:
if cur.val == val:
if cur.next == None:
pre.next = None
cur = cur.next
else:
pre.next = cur.next
cur = cur.next
else:
pre = pre.next
cur = cur.next
return ans.next
class Solution(object):
def addTwoNumbers(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
nHead, flag = ListNode(0), 0
head = nHead
while flag or l1 or l2:
node = ListNode(flag)
if l1:
node.val += l1.val
l1 = l1.next
if l2:
node.val += l2.val
l2 = l2.next
flag = node.val // 10
node.val %= 10
head.next, head = node, node
return nHead.next
class Solution(object):
def addTwoNumbers(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
c1, c2 = '', ''
while l1:
c1 += str(l1.val)
l1 = l1.next
while l2:
c2 += str(l2.val)
l2 = l2.next
num = str(int(c1) + int(c2))
dummy = ListNode(0)
c = dummy
for i in range(len(num)):
c.next = ListNode(num[i])
c = c.next
return dummy.next
class Solution(object):
def swapPairs(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
ans = ListNode(0)
ans.next = head
temp = ans
i = 0
if head == None:
return None
while temp.next and temp.next.next:
t = temp.next.next
temp.next.next = t.next
t.next = temp.next
temp.next = t
temp = temp.next.next
return ans.next
class Solution(object):
def reverseKGroup(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
dummy = jump = ListNode(0)
dummy.next = l = r = head
while True:
i = 0
while r and i < k:
r = r.next
i += 1
if i == k:
pre = r
cur = l
for j in range(k):
cur.next, cur, pre = pre, cur.next, cur
jump.next, jump, l = pre, l, r
else:
return dummy.next
Given a list, rotate the list to the right by k places, where k is non-negative.
Example:
Given 1->2->3->4->5->NULL and k = 2,
return 4->5->1->2->3->NULL.
相当于链表依次右移k次,首先定位到旋转后链尾节点的位置,size-k%size,原来链尾指向原来的链表的起始节点
class Solution(object):
def rotateRight(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
if k == 0 or head ==None:
return head
temp = ListNode(0)
temp.next = head
t = temp
size = 0
while t.next:
size += 1
t = t.next
t.next = temp.next
for i in range(size - k % size):
t = t.next
head = t.next
t.next = None
return head
Given a (singly) linked list with head node root, write a function to split the linked list into k consecutive linked list “parts”.
The length of each part should be as equal as possible: no two parts should have a size differing by more than 1. This may lead to some parts being null.
The parts should be in order of occurrence in the input list, and parts occurring earlier should always have a size greater than or equal parts occurring later.
Return a List of ListNode’s representing the linked list parts that are formed.
Examples 1->2->3->4, k = 5 // 5 equal parts [ [1], [2], [3], [4], null ]
Example 1:
Input:
root = [1, 2, 3], k = 5
Output: [[1],[2],[3],[],[]]
Explanation:
The input and each element of the output are ListNodes, not arrays.
For example, the input root has root.val = 1, root.next.val = 2, \root.next.next.val = 3, and root.next.next.next = null.
The first element output[0] has output[0].val = 1, output[0].next = null.
The last element output[4] is null, but it’s string representation as a ListNode is [].
Example 2:
Input:
root = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], k = 3
Output: [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
Explanation:
The input has been split into consecutive parts with size difference at most 1, and earlier parts are a larger size than the late
首先求解链表的长度L,L/k即为每段链表的基本长度,L%k为除去k段基本长度之后剩余部分的长度,由于每段之间相差的长度不超多1,故将剩余部分添加到前面几段上,每段在基本长度的节点上添加一个节点,直到剩余部分的长度为0,后面每段的长度为基本长度。
class Solution(object):
def splitListToParts(self, root, k):
"""
:type root: ListNode
:type k: int
:rtype: List[ListNode]
"""
L = 0
head = root
temp2 = root
while head:
L += 1
head = head.next
n = L / k
left = L % k
ans = []
for i in range(k):
nhead = ListNode(0)
nhead.next = temp2
if nhead:
temp1 = nhead.next
else:
temp1 = None
temp2 = nhead
for j in range(n):
nhead = nhead.next
temp2 = temp2.next
if left > 0:
nhead = nhead.next
temp2 = temp2.next
left -= 1
if nhead:
nhead = nhead.next
temp2.next = None
ans.append(temp1)
temp2 = nhead
return ans
0
/ \
-3 9
/ /
-10 5
class Solution(object):
def sortedListToBST(self, head):
"""
:type head: ListNode
:rtype: TreeNode
"""
if not head:
return None
if not head.next:
return TreeNode(head.val)
slow = head
fast = head.next.next
while fast and fast.next:
slow = slow.next
fast = fast.next.next
temp = slow.next
slow.next = None
root = TreeNode(temp.val)
root.left = self.sortedListToBST(head)
root.right = self.sortedListToBST(temp.next)
return root
class Solution(object):
def oddEvenList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head:
return head
odd_list = head
# temp1 = odd_list
even_list = head.next
temp2 = even_list
while odd_list.next and even_list.next:
odd_list.next = even_list.next
odd_list = odd_list.next
if odd_list:
even_list.next = odd_list.next
even_list = even_list.next
odd_list.next = temp2
return head
Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
You must do this in-place without altering the nodes’ values.
For example,
Given {1,2,3,4}, reorder it to {1,4,2,3}.
首先将链表拆分为长度相等的左右两部分,拆分技巧,使用快慢指针的方法,快指针的速度是慢指针速度的两倍。然后将右边的链表进行翻转,最后将两个链表归并,生成结果。
class Solution(object):
def reorderList(self, head):
"""
:type head: ListNode
:rtype: void Do not return anything, modify head in-place instead.
"""
if not head or not head.next or not head.next.next:
return
slow = head
fast = head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
head2 = slow.next
slow.next = None
dummy = None
while head2:
p = head2
head2 = head2.next
p.next = dummy
dummy = p
head2 = dummy
head1 = head
while head2:
temp1 = head1.next
temp2 = head2.next
head1.next = head2
head2.next = temp1
head1 = temp1
head2 = temp2
Given a singly linked list, determine if it is a palindrome.
Follow up:
Could you do it in O(n) time and O(1) space?
利用快慢指针的思想,将链表分为左右等长链表,再将右部分链表逆序,与左部分逐一比较,判断是否是回文串
class Solution(object):
def isPalindrome(self, head):
"""
:type head: ListNode
:rtype: bool
"""
if not head or not head.next:
return True
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
head2 = slow
head1 = head
nhead = None
while head2:
p = head2
head2 = head2.next
p.next = nhead
nhead = p
head2 = nhead
while head2:
if head2.val != head1.val:
return False
head1 = head1.next
head2 = head2.next
return True
LeetCode 147 Insertion Sort List
Sort a linked list using insertion sort.
LeetCode148 Sort List
Sort a linked list in O(n log n) time using constant space complexity.
LeetCode 147 Insertion Sort List
插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。思路是对原链中的每个节点进行判断,找到合适的插入位置进行插入。
LeetCode148 Sort List
时间复杂度O(n log n) time ,空间复杂度是常数,使用归并排序,链表的中点可以通过快慢指针法求得。
class Solution(object):
def insertionSortList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
p = dummy = ListNode(0)
cur = dummy.next = head
while cur and cur.next:
val = cur.next.val
if cur.val < val:
cur = cur.next
continue
if p.next.val > val:
p = dummy
while p.next.val < val:
p = p.next
new = cur.next
cur.next = new.next
new.next = p.next
p.next = new
return dummy.next
class Solution(object):
def sortList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head or not head.next:
return head
mid = self.getmiddle(head)
rhead = mid.next
mid.next = None
return self.merge(self.sortList(head), self.sortList(rhead))
def merge(self, lhead, rhead):
temp = dummy = ListNode(0)
while lhead and rhead:
if lhead.val < rhead.val:
temp.next = lhead
lhead = lhead.next
else:
temp.next = rhead
rhead = rhead.next
temp = temp.next
if lhead:
temp.next = lhead
if rhead:
temp.next = rhead
return dummy.next
def getmiddle(self, head):
if not head:
return head
slow = fast = head
while fast.next and fast.next.next:
fast = fast.next.next
slow = slow.next
return slow