leetcode1738

题目大意:

给你一个二维矩阵 matrix 和一个整数 k,矩阵大小为 m x n 由非负整数组成。

矩阵中坐标 (a, b)的 值 可由对所有满足 0 <= i <= a < m0 <= j <= b < n 的元素 matrix[i][j]下标从 0 开始计数)执行异或运算得到。

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

来源:力扣(LeetCode
链接:https://leetcode-cn.com/problems/find-kth-largest-xor-coordinate-value/


解决思路:

这题的思路是使用动态规划进行优化,再使用选择算法进行求第K大的数。

设定 dp[n][m] = ∑ i = 0 , j = 0 n , m \sum_{i=0, j=0}^{n, m} i=0,j=0n,m^matrix[i][j] ,该dp数组可以在O(nm)复杂度内计算。故所求矩阵也就是dp。将其带入第K大选择算法中即可。

时间复杂度:O(nm) 空间复杂度:O(nm)

class Solution {
public:
    int kthLargestValue(vector<vector<int>>& matrix, int k) {
        int dp[1005][1005];
        memset(dp, 0, sizeof dp);
        int s[1005 * 1005], tot = 0;
        int n = matrix.size(), m = matrix[0].size();
        for (int i = 1; i <= n; i++) {
            int pre = 0;
            for (int j = 1; j <= m; j++) {
                pre ^= matrix[i - 1][j - 1];
                dp[i][j] = pre ^ dp[i - 1][j];
                s[tot++] = dp[i][j];
            }
        }
        return select(s, tot, tot - k + 1);
    }
    int select(int a[], int len, int k) {
        if (len <= 38) {
            sort(a, a + len);
            return a[k - 1];
        }
        int i, j, z, ans;
        int *p = new int[3 * len / 4], *q = new int[3 * len / 4];
        for (i = 0; i < len / 5; i++) {
            p[i] = Mid(a, i);
        }
        int middle = select(p, i, (i + 1) / 2);
        i = j = z = 0;
        for (int t = 0; t < len; t++) {
            if (a[t] < middle)
                p[i++] = a[t];
            else if (a[t] == middle)
                j++;
            else    
                q[z++] = a[t];
        }
        if (i >= k)
            ans = select(p, i, k);
        else if (i + j >= k)
            ans = middle;
        else    
            ans = select(q, z, k - i - j);
        delete[] p, q;
        return ans;
    }
    int Mid(int a[], int i) {
        int k = i * 5;
        if (a[k] > a[k + 2])
            swap(a[k], a[k + 2]);
        if (a[k + 1] > a[k + 3])
            swap(a[k + 1], a[k + 3]);
        if (a[k] > a[k + 1])
            swap(a[k], a[k + 1]);
        if (a[k + 2] > a[k + 3])
            swap(a[k + 2], a[k + 3]);
        if (a[k + 1] > a[k + 2])
            swap(a[k + 1], a[k + 2]);
        if (a[k + 4] > a[k + 2])
            return a[k + 2];
        else if (a[k + 4] > a[k + 1])    
            return a[k + 4];
        else 
            return a[k + 1];
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值