leetcode 378(二维数组的二分法与堆排序)

解题思路:

利用二分法:
对此题用二分法,和一维数组的二分法不同,何况一维数组是一个已经排好序的数组,在磁体中,要求的是第k小元素,所以该值拥有k个小于等于他的元素。
假设有以下二维数组:
[[1, 5, 9],
[3, 10, 15],
[6, 16, 20]]
要找出第6大的值,即k = 6
首先将lo指向整个二维数组最小的值a[0][0],hi指向最大的值a[2][2]
求出lo 和 hi 所指的值的平均值(向下取整)mid,即为10
找出比小于等于 mid 的值的个数count
若count >= k, 则代表着小于等于 mid 值的数量比 目标值要多,所以目标值在某种意义上要大,所以需要将 count 减小, 在二分查找中,减小 mid 便是调降低 hi 的值, 所以此时可以将 mid 值赋给 hi。
反之,则令 lo = mid + 1
PS:为什么在count >= k 时不用 hi = mid - 1, 因为含有 等号, 而当他们相等时,并不意味着我们找到了,比如, 当mid = 11 时, 他和 a[k] = 10 时是有着相同的 count 值。
当 lo >= high 时,lo便是我们要找的值(还不知道为什么)。
伪代码:

k = 6
lo = a[0][0]
hi = a[2][2]
while lo < hi:
	mid = lo + (hi - lo)/2
	count = litter_num(a, mid)
	# 返回的值为二维数组中小于等于mid的元素的数量
	if count < k:
		lo = mid + 1
	else:
		hi = mid
		
return lo

根据伪代码写:

def kthSmallest(self, matrix, k):
        """
        :type matrix: List[List[int]]
        :type k: int
        :rtype: int
        """
        length = len(matrix)
        lo = matrix[0][0]
        hi = matrix[length - 1][length - 1]
        while lo < hi:
            count = 0
            mid = lo + (hi - lo)/2
            for i in range(0, length):
                j = length - 1
                while j >= 0 and matrix[i][j] > mid:
                    j -= 1
                count += (j + 1)
            if count < k:
                lo = mid + 1
            else:
                hi = mid
        return lo

解题思路二,利用堆排序的特性,根节点最大或最小:

class Solution(object):
    def adjust_heap(self, a, i):
      """
      查看是否存在左右子节点
      存在则继续
      右节点是否大于左节点
      是则指向右子节点
      比较父子节点的大小
      若父节点大于子节点:
        返回
      反之:
        交换数值以后,并对子节点进行调整
      """
      length = len(a)
      k = 2 * i + 1
      if k >= length:
        return
      try:
        if a[k] < a[k + 1]:
          k += 1
      except IndexError:
        k = k
      if a[i] < a[k]:
        a[i], a[k] = a[k], a[i]
        Solution.adjust_heap(self, a, k)
        
        
    def build_big_heap(self, arr):
      """
      对最后一个非叶子节点开始进行调整,
      """
      length = len(arr)
      i = int(length/2)
      while(i):
        Solution.adjust_heap(self, arr, i - 1)
        i -= 1
      
  
    def kthSmallest(self, matrix, k):
        """
        :type matrix: List[List[int]]
        :type k: int
        :rtype: int
        """
        length = len(matrix[0])
        arr =[]
        for i in range(0, len(matrix[0])):
            for j in range(0, len(matrix[0])):
                arr.append(matrix[length - i - 1][length - j - 1])
        Solution.build_big_heap(self, arr)
        i = len(arr)  - k + 1
        while(i):
            temp = arr[0]
            i -= 1
            arr[0], arr[-1] = arr[-1], arr[0]
            del arr[-1]
            Solution.adjust_heap(self, arr, 0)
        return temp

你可能感兴趣的:(leetcode)