zoukankan      html  css  js  c++  java
  • 378. Kth Smallest Element in a Sorted Matrix

    Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth smallest element in the matrix.

    Note that it is the kth smallest element in the sorted order, not the kth distinct element.

    Example:

    matrix = [
       [ 1,  5,  9],
       [10, 11, 13],
       [12, 13, 15]
    ],
    k = 8,
    
    return 13.
    

    Note: 
    You may assume k is always valid, 1 ≤ k ≤ n2.

    M1: heap,建立一个min heap,先把最小元素{0, 0}放进heap。用cnt计数,如果++cnt == k时,找到第k小的元素,返回。

    因为数组每行每列都是有序的,每次循环时把heap中的最小值poll出来,为了避免重复,如果是第一行,把该元素右边的元素加入heap,然后把该元素下方的元素加入heap。用一个参数cnt计数,当++cnt = k里,返回matrix对应坐标的值。

    time: O(klogk), space: O(k) 

    class Solution {
        public int kthSmallest(int[][] matrix, int k) {
            PriorityQueue<int[]> minHeap = new PriorityQueue<>(k, (a, b) -> matrix[a[0]][a[1]] - matrix[b[0]][b[1]]);
            int cnt = 0;
            minHeap.add(new int[] {0, 0});
            while(true) {
                int[] pair = minHeap.poll();
                if(++cnt == k)
                    return matrix[pair[0]][pair[1]];
                
                if(pair[0] == 0 && pair[1] + 1 < matrix[0].length)
                    minHeap.add(new int[] {pair[0], pair[1] + 1});
                    
                if(pair[0] + 1 < matrix.length)
                    minHeap.add(new int[] {pair[0] + 1, pair[1]});                
            }
        }
    }

    另一种写法:

    从最小的元素开始,依次访问最小元素的neighbor(当neighbor下标不越界且没被访问过,入队,并标记为已访问),循环k次。最后最小堆的堆顶元素就是第k小元素的坐标

    time: O(klogk), space: O(k + n^2)

    class Solution {
        public int kthSmallest(int[][] matrix, int k) {
            boolean[][] visited = new boolean[matrix.length][matrix[0].length];
            PriorityQueue<int[]> minHeap = new PriorityQueue<>((a, b) -> matrix[a[0]][a[1]] - matrix[b[0]][b[1]]);
            minHeap.offer(new int[] {0, 0});
            
            for(int i = 0; i < k - 1; i++) {
                int[] idx = minHeap.poll();
                int row = idx[0], col = idx[1];
                visited[row][col] = true;
                
                if(row + 1 < matrix.length && !visited[row+1][col]) {
                    minHeap.offer(new int[] {row + 1, col});
                    visited[row+1][col] = true;
                }
                if(col + 1 < matrix[0].length && !visited[row][col+1]) {
                    minHeap.offer(new int[] {row, col + 1});
                    visited[row][col+1] = true;
                }
            }
            
            int[] res = minHeap.peek();
            return matrix[res[0]][res[1]];
        }
    }

    M2: binary search,原理同 287. find the duplicate number https://www.cnblogs.com/fatttcat/p/9986854.html

    在number value的基础上进行binary search,范围是min~max。每次计算matrix中有多少个<= mid值的数并缩小搜索范围:如果cnt < k,说明只有不到k个数小于等于mid,第k个数应该在mid之后的部分,left=mid+1;反之如果cnt >= k,说明第k个数在mid之前,right=mid-1

    time: O(Nlog(max - min)), space: O(1)

    class Solution {
        public int kthSmallest(int[][] matrix, int k) {
            int n = matrix.length;
            int left = matrix[0][0], right = matrix[n - 1][n - 1];
            while(left <= right) {
                int mid = left + (right - left) / 2;
                int cnt = lessEqualK(matrix, mid);
                if(cnt < k) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
            return left;
        }
        
        public int lessEqualK(int[][] matrix, int val) {
            int i = matrix.length - 1, j = 0;
            int cnt = 0;
            while(i >= 0 && j <= matrix.length - 1) {
                if(matrix[i][j] > val) {
                    i--;
                } else {
                    cnt += i + 1;
                    j++;
                }
            }
            return cnt;
        }
    }
  • 相关阅读:
    SQL Server Code tips (持续更新)
    Oracle 函数 “判断数据表中不存在的数据,才允许通过”
    Oracle 函数 “把当前的用户(审核人,审核通过后)插入到数据表中”
    Oracle 函数 “自动生成订单号”
    Oracle中的instr()函数 详解及应用
    Oracle中的substr()函数 详解及应用
    Spring实战(三)Spring中装配Bean的三种方式---XML、JavaConfig、AutoWire
    Spring实战(二)Spring容器和bean的生命周期
    Spring实战(一)Spring简介---呕心沥血只为让Java开发更简单。
    git、git bash、git shell
  • 原文地址:https://www.cnblogs.com/fatttcat/p/9992882.html
Copyright © 2011-2022 走看看