美文网首页算法
1738. 找出第 K 大的异或坐标值

1738. 找出第 K 大的异或坐标值

作者: 红树_ | 来源:发表于2023-07-06 19:28 被阅读0次

    参考1738. 找出第 K 大的异或坐标值,难度分1671。

    题目

    给你一个二维矩阵 matrix 和一个整数 k ,矩阵大小为 m x n 由非负整数组成。矩阵中坐标 (a, b) 可由对所有满足 0 <= i <= a < m0 <= j <= b < n 的元素 matrix[i][j]下标从 0 开始计数)执行异或运算得到。

    请你找出 matrix 的所有坐标中第 k 大的值(k 的值从 1 开始计数)。

    输入:matrix = [[5,2],[1,6]], k = 1
    输出:7
    解释:坐标 (0,1) 的值是 5 XOR 2 = 7 ,为最大的值。
    输入:matrix = [[5,2],[1,6]], k = 2
    输出:5
    解释:坐标 (0,0) 的值是 5 = 5 ,为第 2 大的值。
    输入:matrix = [[5,2],[1,6]], k = 3
    输出:4
    解释:坐标 (1,0) 的值是 5 XOR 1 = 4 ,为第 3 大的值。
    输入:matrix = [[5,2],[1,6]], k = 4
    输出:0
    解释:坐标 (1,1) 的值是 5 XOR 2 XOR 1 XOR 6 = 0 ,为第 4 大的值。
    

    解题思路

    • 动态规划+排序:使用动态规划快速计算出所有坐标值,也可用前缀和,然脏排序后返回第n-k个元素。
    • 动态规划+快速选择:动态规划计算出坐标值后,进行快速选择算法。

    动态规划+排序

    class Solution {
        public int kthLargestValue(int[][] matrix, int k) {
            int m = matrix.length, n = matrix[0].length;
            //先动态规划计算所有坐标值
            int[][] values = new int[m][n];
            int[] cols = new int[n];
            for(int i = 0; i < m; i++) {
                for(int j = 0; j < n; j++) {
                    cols[j] ^= matrix[i][j]; //记录j列的坐标值
                    if(j == 0) values[i][j] = cols[j];
                    else values[i][j] = values[i][j-1] ^ cols[j];
                }
            }
            int[] res = new int[m*n];
            for(int i = 0; i < m; i++) {
                for(int j = 0; j < n; j++) res[i*n+j] = values[i][j];
            }
            //考虑对所有值排序
            Arrays.sort(res);
            return res[m*n-k];
        }
    }
    

    复杂度分析

    • 时间复杂度:O(mnlogmn),m/n分别为矩阵行/列数,动态规划为O(mn),排序为O(mnlogmn)
    • 空间复杂度:O(mn),主要为动态规划空间。

    动态规划+快速选择

    class Solution {
        int[] res;
        int k;
        public int kthLargestValue(int[][] matrix, int k) {
            int m = matrix.length, n = matrix[0].length;
            //先动态规划计算所有坐标值
            int[][] values = new int[m][n];
            int[] cols = new int[n];
            res = new int[m*n];
            for(int i = 0; i < m; i++) {
                for(int j = 0; j < n; j++) {
                    cols[j] ^= matrix[i][j]; //记录j列的坐标值
                    if(j == 0) res[i*n+j] = cols[j];
                    else res[i*n+j] = res[i*n+j-1] ^ cols[j];
                }
            }
            // for(int i = 0; i < m; i++) {
            //     for(int j = 0; j < n; j++) res[i*n+j] = values[i][j];
            // }
            //考虑快速选择
            // int left = 0,right = res.length-1;
            // while(true) {
            //     int index = quickSelect(left,right);
            //     if(index == k-1) return res[index];
            //     else if(index < k-1) left = index+1;
            //     else right = index-1;
            // }
            this.k = k;
            return quickSelect(0,res.length-1);
        }
    
        Random random = new Random();
        int quickSelect(int start,int end) {
            int pos = start + random.nextInt(end-start+1);
            int base = res[pos];
            swap(start,pos);
            int index = start;
            for(int i = start+1; i <= end; i++) {
                if(res[i] > base && ++index != i) swap(i,index);
            }
            swap(start,index);
            if(index == k-1) return res[index];
            else if(index < k-1) return quickSelect(index+1,end);
            return quickSelect(start,index-1);
        }
        void swap(int x,int y) {
            int tmpx = res[x];
            res[x] = res[y];
            res[y] = tmpx;
        }
    }
    

    复杂度分析

    • 时间复杂度:O(mn),动态规划遍历和快速选择都为O(mn)
    • 空间复杂度:O(mn),主要为动态规划空间。

    相关文章

      网友评论

        本文标题:1738. 找出第 K 大的异或坐标值

        本文链接:https://www.haomeiwen.com/subject/buifudtx.html