Find Kth题目类型总结

找第k大或者第k小的题型,也是经常面试考,这里做个总结;

首先quick select算法的模板要倒背如流,这个是通过quick sort里面提炼得到的算法;两个while一个if,condition相同;后面再递归

Kth Smallest Numbers in Unsorted Array

找到一个无序数组中第K小的数

Example

样例 1:

输入: [3, 4, 1, 2, 5], k = 3
输出: 3

样例 2:

输入: [1, 1, 1], k = 2
输出: 1

思路:quickselect标准解法:O(N);

public class Solution {
    /**
     * @param k: An integer
     * @param nums: An integer array
     * @return: kth smallest element
     */
    public int kthSmallest(int k, int[] nums) {
        if(nums == null || nums.length == 0 || k <= 0){
            return -1;
        }
        return quickselect(nums, k, 0, nums.length - 1);
    }
    
    private int quickselect(int[] nums, int k, int start, int end) {
        if(start == end) {
            return nums[start];
        }
        
        int mid = start + (end - start) / 2;
        int pivot = nums[mid];
        int i = start; int j = end;
        while(i <= j) {
            while(i <= j && nums[i] < pivot) {
                i++;
            }
            while(i <= j && nums[j] > pivot) {
                j--;
            }
            if(i <= j) {
                swap(nums, i, j);
                i++;
                j--;
            }
        }
        
        if(start + k - 1 <= j) {
            return quickselect(nums, k, start, j);
        }
        if(start + k - 1 >= i) {
            return quickselect(nums, k - (i -start), i, end);
        }
        return nums[j+1];
    }
    
    private void swap(int[] A, int i, int j) {
        int temp = A[i];
        A[i] = A[j];
        A[j] = temp;
    }
}

Kth Largest Element

在数组中找到第 k 大的元素。

Example

样例 1:

输入:
n = 1, nums = [1,3,4,2]
输出:
4

思路:是找从大到小的第k大;思路也是跟上面一样,quick select模板走起;

public class Solution {
    /**
     * @param n: An integer
     * @param nums: An array
     * @return: the Kth largest element
     */
    public int kthLargestElement(int n, int[] nums) {
        if(nums == null || nums.length == 0 || n <= 0){
            return -1;
        }
        return quickselect(nums, n, 0, nums.length - 1);
    }
    
    private int quickselect(int[] nums, int k, int start, int end) {
        if(start == end) {
            return nums[start];
        }
        
        int mid = start + (end - start) / 2;
        int pivot = nums[mid];
        int i = start; int j = end;
        while(i <= j) {
            while(i <= j && nums[i] > pivot) {
                i++;
            }
            while(i <= j && nums[j] < pivot) {
                j--;
            }
            if(i <= j) {
                swap(nums, i, j);
                i++;
                j--;
            }
        }
        
        if(start + k - 1 <= j) {
            return quickselect(nums, k, start, j);
        }
        if(start + k - 1 >= i) {
            return quickselect(nums, k - (i -start), i, end);
        }
        return nums[j+1];
    }
    
    private void swap(int[] A, int i, int j) {
        int temp = A[i];
        A[i] = A[j];
        A[j] = temp;
    }
}

Kth Smallest Element in a Sorted Matrix

给定一个 n x n 矩阵,每一行和每一列都按照升序排序,找出矩阵中的第 k 小元素。

注意是需要找将所有元素有序排列的第 k 小元素,而不是第 k 个互不相同的元素。

Example

样例1

输入:
[[ 1,  5,  9],[10, 11, 13],[12, 13, 15]]
8
输出: 13

思路:这里用priorityqueue也就是堆来实现log(k)去找 最大最小值;Comparator要会写,倒背如流,然后pq的用法也是基本考法,这题几乎就是送分题;O(klogk)

public class Solution {
    /**
     * @param matrix: List[List[int]]
     * @param k: a integer
     * @return: return a integer
     */
    private class Node {
        public int x;
        public int y;
        public int value;
        public Node(int x, int y, int value) {
            this.x = x;
            this.y = y;
            this.value = value;
        }
    }
    
    private class NodeComparator implements Comparator<Node> {
        @Override
        public int compare(Node a, Node b) {
            return (a.value - b.value);
        }
    }
    
    public int kthSmallest(int[][] A, int k) {
        if(A == null || A.length == 0 || A[0].length == 0 || k <= 0){
            return 0;
        }
        
        int[] dx = {0, 1};
        int[] dy = {1, 0};
        
        int n = A.length;
        int m = A[0].length;
        PriorityQueue<Node> pq = new PriorityQueue<Node>(n*m, new NodeComparator());
        boolean[][] visited = new boolean[n][m];
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                visited[i][j] = false;
            }
        }
        
        pq.add(new Node(0 , 0, A[0][0]));
        visited[0][0] = true;
        
        int count = 0;
        while(!pq.isEmpty()){
            Node node = pq.poll();
            count++;
            if(count == k) {
                return node.value;
            }
            int x = node.x;
            int y = node.y;
            
            for(int i = 0; i < dx.length; i++){
                int nx = x + dx[i];
                int ny = y + dy[i];
                if((0 <= nx && nx < n && 0 <= ny && ny < m && !visited[nx][ny])){
                    pq.add(new Node(nx, ny, A[nx][ny]));
                    visited[nx][ny] = true;
                }
            }
        }
        return -1;
    }
}

Kth Smallest Sum In Two Sorted Arrays

给定两个排好序的数组 AB,定义集合 sum = a + b ,其中a来自A数组,b来自B数组,求 sum 中第k小的元素

Example

样例1

输入:
a = [1, 7, 11]
b = [2, 4, 6]
k = 3
输出: 7
说明: 满足条件的所有的和有[3, 5, 7, 9, 11, 13, 13, 15, 17],其中第三个是7.

思路:这题把两个sort array每一行跟每一列元素加一下

1+2, 1+4, 1+6

7+2, 7+4, 7+6

11+2, 11+4, 11+6, 那么这题从左到右也是递增的,从上到下也是递增的,这题就完完全全变成了上面的一题;代码都不需要边多少,matrix[i][j] =  A[i] + A[j]; O(klogk)

public class Solution {
    /**
     * @param A: an integer arrays sorted in ascending order
     * @param B: an integer arrays sorted in ascending order
     * @param k: An integer
     * @return: An integer
     */
    private class Node {
        public int x;
        public int y;
        public int value;
        public Node(int x, int y, int value) {
            this.x = x;
            this.y = y;
            this.value = value;
        }
    }
    
    private class NodeComparator implements Comparator<Node> {
        @Override
        public int compare(Node a, Node b) {
            return (a.value - b.value);
        }
    }
    
    public int kthSmallestSum(int[] A, int[] B, int k) {
        if(A == null || A.length == 0 || B == null || B.length == 0 || k <= 0){
            return -1;
        }
        
        int[] dx = {0, 1};
        int[] dy = {1, 0};
        
        int n = A.length;
        int m = B.length;
        PriorityQueue<Node> pq = new PriorityQueue<Node>(n*m, new NodeComparator());
        boolean[][] visited = new boolean[n][m];
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                visited[i][j] = false;
            }
        }
        
        pq.add(new Node(0 , 0, A[0] + B[0]));
        visited[0][0] = true;
        
        int count = 0;
        while(!pq.isEmpty()){
            Node node = pq.poll();
            count++;
            if(count == k) {
                return node.value;
            }
            int x = node.x;
            int y = node.y;
            
            for(int i = 0; i < dx.length; i++){
                int nx = x + dx[i];
                int ny = y + dy[i];
                if((0 <= nx && nx < n && 0 <= ny && ny < m && !visited[nx][ny])){
                    pq.add(new Node(nx, ny, A[nx] + B[ny]));
                    visited[nx][ny] = true;
                }
            }
        }
        return -1;
    }
}

Kth Largest in N Arrays

在N个数组中找到第K大元素

Example

例1:

输入:
k = 3, [[9,3,2,4,7],[1,2,3,4,8]]
输出:
7
解释:
第三大的元素为 7。

思路:这里题目提示了,只能交换array里面的元素,那么就说明array会非常大,那么不可能combine用quick select来做,那么只能把每个array排序,然后用maxheap去做;两点注意:1. array sort之后,可以从尾巴取,也就是取最大;2. ny是可以减少到0的。

public class Solution {
    /**
     * @param arrays: a list of array
     * @param k: An integer
     * @return: an integer, K-th largest element in N arrays
     */
    
    private class Node {
        public int x;
        public int y;
        public int value;
        public Node(int x, int y, int value) {
            this.x = x;
            this.y = y;
            this.value = value;
        }
    } 
    
    private class NodeComparator implements Comparator<Node> {
        @Override
        public int compare(Node a, Node b) {
            return (b.value - a.value);
        }
    }
    
    public int KthInArrays(int[][] arrays, int k) {
        if(arrays == null || arrays.length == 0 || k <= 0){
            return -1;
        }
        
        int n = arrays.length;
        for(int i = 0; i < n; i++) {
            Arrays.sort(arrays[i]);
        }
        
        PriorityQueue<Node> pq = new PriorityQueue<Node>(n, new NodeComparator());
        for(int i = 0; i < n; i++) {
            if(arrays[i].length != 0) {
                int j = arrays[i].length - 1;
                pq.offer(new Node(i, j, arrays[i][j]));
            } 
        }
        
        int count = 0;
        while(!pq.isEmpty()) {
            Node node = pq.poll();
            count++;
            if(count == k) {
                return node.value;
            }
            int nx = node.x;
            int ny = node.y - 1;
            if(ny >= 0) { // 注意这里y是可以==0的;
                pq.offer(new Node(nx, ny, arrays[nx][ny]));
            }
        }
        return -1;
    }
}
发布了562 篇原创文章 · 获赞 13 · 访问量 17万+

猜你喜欢

转载自blog.csdn.net/u013325815/article/details/103874583