LeetCode第340场周赛

2023.4.9LeetCode第340场周赛

A. 对角线上的质数

思路

枚举所有对角线上的数,判断是否为质数
使用 O ( n ) O(\sqrt n) O(n )的算法判断质数
判断x是否为质数,若x=a*b,只用考虑a<=b的情况,故只用枚举到 n \sqrt{n} n

代码

class Solution {
public:
    bool isp(int x) {
        if (x == 1) return false;
        for (int i = 2; i * i <= x; i ++ ) {
            if (x % i == 0)
                return false;
        }
        return true;
    }
    
    int diagonalPrime(vector<vector<int>>& a) {
        int m = a.size();
        int ans = 0;
        for (int i = 0; i < m; i ++ ) {
            if (isp(a[i][i]))
                ans = max(ans, a[i][i]);
            if (isp(a[i][m - i - 1]))
                ans = max(ans, a[i][m - i - 1]);
        }
        return ans;
    }
};

B. 等值距离和

思路

将所有数按照相同元素分组
枚举每个组,计算绝对值之和时数组是有序的,可以分为前半部分和后半部分,设当前数为x,前半部分x较大,绝对值和为(x*前半部分的数量-前半部分的前缀和),后半部分x较小,绝对值和为(后半部分的前缀和 - x*后半部分的数量),两部分的前缀和分别用两个变量维护

代码

class Solution {
public:
    typedef long long ll;
    
    vector<long long> distance(vector<int>& a) {
        unordered_map<int, vector<int>> mp;
        int n = a.size();
        for (int i = 0; i < n; i ++ ) {
            mp[a[i]].push_back(i);
        }
        vector<ll> ans(n);
        for (auto& [k, v] : mp) {
            int m = v.size();
            if (m == 1) continue;
            ll s = 0;
            for (int i = 0; i < m; i ++ )
                s += v[i];
            ll t = 0;
            for (int i = 0; i < m; i ++ ) {
                s -= v[i];
                ans[v[i]] = ((ll)v[i] * i) - t + (s - (ll)v[i] * (m - i - 1));
                t += v[i];
            }
        }
        return ans;
    }
};

C. 最小化数对的最大差值

思路

二分,答案越大越能满足,越小越不能满足,具有二分性
使用贪心的策略判断,将数组排序后尽量选择相邻的两个数,满足条件向后移动两位,不满足则向后移动一位

代码

class Solution {
public:
    int minimizeMax(vector<int>& a, int p) {
        sort(a.begin(), a.end());
        int n = a.size();
        int l = 0, r = 1e9;
        while (l < r) {
            int mid = l + r >> 1;
            if (check(mid, a, p)) r = mid;
            else l = mid + 1;
        }
        return l;
    }
    
    bool check(int x, vector<int>& a, int p) {
        int t = p;
        for (int i = 0; i + 1 < a.size();) {
            if (a[i + 1] - a[i] <= x) {
                p -- ;
                i += 2;                
            } else i ++ ;
        }
        return p <= 0;
    }
};

D. 网格图中最少访问的格子数

思路

优先队列,给每一列和每一行都维护一个优先队列,枚举每个点时,考虑可以从上面或者左边走过来,选择两个方向上的最优情况,即堆顶元素,若不能走到当前点,从堆中去除

代码

#define x first
#define y second

class Solution {
public:
    typedef pair<int, int> PII;

    int minimumVisitedCells(vector<vector<int>>& grid) {
        int n = grid.size(), m = grid[0].size();
        vector<priority_queue<PII, vector<PII>, greater<PII>>> row(n), col(m);
        vector<vector<int>> d(n, vector<int>(m, -1));
        d[0][0] = 1;
        for (int i = 0; i < n; i ++ )
            for (int j = 0; j < m; j ++ ) {
                //从左边来
                while (row[i].size() && row[i].top().y + grid[i][row[i].top().y] < j) {
                    row[i].pop();
                }
                if (row[i].size()) {
                    d[i][j] = d[i][row[i].top().y] + 1;
                }
                //从上面来
                while (col[j].size() && col[j].top().y + grid[col[j].top().y][j] < i) {
                    col[j].pop();
                }
                if (col[j].size()) {
                    if (d[i][j] != -1)
                        d[i][j] = min(d[i][j], d[col[j].top().y][j] + 1);
                    else
                        d[i][j] = d[col[j].top().y][j] + 1;
                }
                if (d[i][j] != -1) {
                    row[i].push({d[i][j], j});
                    col[j].push({d[i][j], i});
                }
            }
        return d[n - 1][m - 1];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值