Google面试题专题2 - leetcode48. Rotate Image/31. Next Permutation/23. Merge k Sorted Lists

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a786150017/article/details/84193473

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

猜你喜欢

转载自blog.csdn.net/a786150017/article/details/84193473
今日推荐