1. 程式人生 > >Google面試題專題2 - leetcode48. Rotate Image/31. Next Permutation/23. Merge k Sorted Lists

Google面試題專題2 - leetcode48. Rotate Image/31. Next Permutation/23. Merge k Sorted Lists

leetcode48. Rotate Image

題目描述

給定一個n*n的2維矩陣,順時針旋轉矩陣90度。(原地旋轉)
原地旋轉:直接修正矩陣,不要建立額外的2維矩陣。

例子
Example 1:

Given input matrix =
[
[1,2,3],
[4,5,6],
[7,8,9]
],
rotate the input matrix in-place such that it becomes:
[
[7,4,1],
[8,5,2],
[9,6,3]
]

Example 2:

Given input matrix =
[
[ 5, 1, 9,11],
[ 2, 4, 8,10],
[13, 3, 6, 7],
[15,14,12,16]
],
rotate the input matrix in-place such that it becomes:
[
[15,13, 2, 5],
[14, 3, 4, 1],
[12, 6, 8, 9],
[16, 7,10,11]
]

思想
拆分旋轉90°的操作。關於軸、對角線的操作容易實現。
首先以輔對角線為軸進行翻轉;然後以中心豎線為軸進行翻轉。

解法
複雜度:時間O(n^2),空間O(1)

class Solution(object):
    def rotate(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: void Do not return anything, modify matrix in-place instead.
        """
        n = len(
matrix) # 以輔對角線為軸翻轉 for i in range(n): for j in range(i+1, n): matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j] # 以中心豎線為軸翻轉 for i in range(n): for j in range(n//2): matrix[i][j], matrix[i][-j-1] = matrix[
i][-j-1], matrix[i][j]

leetcode31. Next Permutation

題目描述

實現下一個序列:重組數字得到比當前值大的下一個字典序。
如果該重組序列不存在,則重組至字典序最小的序列。

要求:原地調整,使用常數空間。

例子

1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

思想
下一個序列,肯定是要把大數移到小數前面。
1)從後往前找第一個逆序的數對(a, b),a<b。則b為要移動的大數,記boundary為a;
2)在boundary後面的數中,找到大於boundary的最小值,移到a前面;
3)boundary後的元素升序排列。

解法
複雜度:時間O(n),空間O(1)

class Solution(object):
    def nextPermutation(self, nums):
        """
        :type nums: List[int]
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        bound = -1
        for i in range(len(nums)-1, 0, -1):
            if nums[i] > nums[i-1]:
                bound = i-1
                break
                
        if bound == -1:
            nums.reverse() # nums[:] = nums[::-1]
        else:
            num = nums[bound]
            for i in range(len(nums)-1, bound, -1):
                if nums[i] > num:
                    nums[i], nums[bound] = nums[bound], nums[i]
                    nums[bound+1:] = nums[bound+1:][::-1]
                    return

leetcode23. Merge k Sorted Lists

題目描述

合併k個有序連結串列,返回成一個有序連結串列。

例子

Input:
[
1->4->5,
1->3->4,
2->6
]
Output: 1->1->2->3->4->4->5->6

思想
假設每個連結串列的平均長度是n。
(法1 - 遞迴)
合併2個有序連結串列時,可以兩兩比較,時間複雜度O(m+n)。
合併k個連結串列時,類似歸併排序。

(法2 - 非遞迴)
合併k個有序連結串列,步驟肯定如下:
1)比較k個頭指標,找到最小的一個,作為最終連結串列的頭指標;
2)比較k-1個頭指標和候選連結串列的第二個指標,找到最小的一個,作為連結串列的第二個元素

【方法】
k個元素找出最小的一個,考慮堆排序,時間複雜度O(klogk)
然後在k-1個元素中插入一個元素,調整堆,時間複雜度O(logk)

(python最小堆heap)
import heapq、heapq.heappush(heap, num) #插入元素、heapq.heappop(heap) # 彈出最小元素

解法1
遞迴,類似歸併排序。
第一次兩兩合併進行了k/2次,每次處理2n個值;
第二次兩兩合併進行了k/4次,每次處理4n個值;

最後一次兩兩合併進行了k/(2^logk)次,每次處理2^logk*n個值。
所以總時間複雜度:
O((2n) * (k / 2) + (4n) * (k / 4) + (8n) * (k / 8) + … + (2^logk*n) * (k / (2 ^logk)) )=O(nklogk)

空間複雜度O(1)。

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

class Solution(object):
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        if not lists:
            return None
        if len(lists) == 1:
            return lists[0]
        
        mid = len(lists) // 2
        left = self.mergeKLists(lists[:mid])
        right = self.mergeKLists(lists[mid:])
        return self.merge2Lists(left, right)
        
    def merge2Lists(self, head1, head2):
        p = ListNode(-1)
        pNode = p
        while head1 and head2:
            if head1.val < head2.val:
                p.next = head1
                head1 = head1.next
            else:
                p.next = head2
                head2 = head2.next
            p = p.next
        
        if head1:
            p.next = head1
        else:
            p.next = head2
        
        return pNode.next

解法2
堆調整時間複雜度為O(logk),每個元素都要取一次O(nk)。
所以總時間複雜度為O(nklogk),空間複雜度O(k)。

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

import heapq
class Solution(object):
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        heap = []
        for head in lists:
            if head:    # ★
                heapq.heappush(heap, (head.val, head))
        
        p = ListNode(-1)
        pNode = p
        while heap:
            node = heapq.heappop(heap)[1]
            if node.next:
                heapq.heappush(heap, (node.next.val, node.next))
            p.next = node
            p = p.next
        return pNode.next