力扣第334场周赛 6469、6368、6367、6366 个人题解

6369 左右元素和的差值

前缀和

class Solution {
public:
vector<int> leftRigthDifference(vector<int>& nums)
{
    int n = nums.size();
    vector<int> pre_sum(n + 2);
    for(int i = 0; i < n; i ++)
        pre_sum[i + 1] = pre_sum[i] + nums[i];
    pre_sum[n + 1] = pre_sum[n];

    vector<int> ans(n);
    for(int i = 0; i < n; i ++)
        ans[i] = std::abs(pre_sum[i] - pre_sum[n + 1] + pre_sum[i + 1]);
    return ans;
}
};

6368 找出字符串的可整除数组

class Solution {
public:
vector<int> divisibilityArray(string word, int m)
{
    int n = word.length();
    vector<int> ans(n);
    long long cur = 0;
    for(int i = 0; i < n; i ++)
    {
        cur *= 10;
        cur %= m;
        cur += word[i] - '0';
        cur %= m;
        if(cur == 0) ans[i] = 1;
    }
    return ans;
}
};

6367 求出最多标记下标

题目描述:

给你一个下标从 0 开始的整数数组 nums 。

一开始,所有下标都没有被标记。你可以执行以下操作任意次:

  • 选择两个 互不相同且未标记 的下标 i 和 j ,满足 2 * nums[i] <= nums[j] ,标记下标 i 和 j 。

请你执行上述操作任意次,返回 nums 中最多可以标记的下标数目。

思路:

如果对原数组进行排序,假设最多被标记的数有m对,则有这2*m个数必然是排序后数组的前m个和后m个(做题时的总结能力实在太重要了,这个当时做的时候自己也没想到)。故只需要对排序后的数组进行搜索这个m即可(其中第一个数与倒数第m个数配对标记、最后一个数与第m个数配对标记),可以通过二分法对数组前半段进行搜索,但这里主要的时间复杂度在于排序,搜索没有决定性影响。

int maxNumOfMarkedIndices(vector<int>& nums)
{
    int n = nums.size();
    sort(nums.begin(), nums.end());

    // 二分法查找
    int l = 0, r = n / 2, mid;
    while(l <= r)
    {
        mid = (l + r) / 2;

        bool sign = true;
        for(int i = 0; i < mid; i ++)
            if(2 * nums[i] > nums[n + i - mid])
                sign = false;
        if(sign) l = mid + 1;
        else r = mid - 1;
    }
    return r * 2;
}

6366

题目描述:

给你一个 m x n 的矩阵 grid ,每个元素都为 非负 整数,其中 grid[row][col] 表示可以访问格子 (row, col) 的 最早 时间。也就是说当你访问格子 (row, col) 时,最少已经经过的时间为 grid[row][col] 。

你从 最左上角 出发,出发时刻为 0 ,你必须一直移动到上下左右相邻四个格子中的 任意 一个格子(即不能停留在格子上)。每次移动都需要花费 1 单位时间。

请你返回 最早 到达右下角格子的时间,如果你无法到达右下角的格子,请你返回 -1 。

思路:

  • 只有当grid[0][1]和grid[1][0]都大于1时,才会无法到达并返回-1,其他情况下都可以通过来回移动等待时间限制
  • 到达任意坐标的时间的最小值,必然大于等于到达其相邻坐标的时间+1
  • 故到达一个坐标的最短时间,是该坐标时间限制与其相邻坐标到达时间+1这两者的最大值,但是同时,其奇偶性必须与横纵坐标的和一致
  • 在此基础上,使用广度优先搜索(Dijkstra)
class Solution {
public:
typedef pair<int, pair<int, int>> piii;

int directions[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};

struct cmp{
   bool operator()(piii& a, piii& b) {
       return a.first > b.first;
   }
};

int minimumTime(vector<vector<int>>& grid)
{
    if(grid[0][1] > 1 && grid[1][0] > 1) return -1;

    int m = grid.size(), n = grid[0].size();
    vector<vector<int>> dp(m, vector<int>(n, 0));

    priority_queue<piii, vector<piii>, cmp> bfs_queue;
    bfs_queue.push({0, {0, 0}});

    pair<int, pair<int, int>> cur_pos;
    while(!bfs_queue.empty())
    {
        cur_pos = bfs_queue.top();
        bfs_queue.pop();
        for(int i = 0; i < 4; i ++)
        {
            int new_x = cur_pos.second.first + directions[i][0], new_y = cur_pos.second.second + directions[i][1];
            if(new_x < m && new_x >= 0 && new_y < n && new_y >= 0)
            {
                int new_dis = std::max(cur_pos.first + 1, grid[new_x][new_y]);  // 到达时间必须大于等于限制的时间
                new_dis += (new_dis + new_x + new_y) % 2;  // 奇偶性需要与坐标相同
                if(new_dis < dp[new_x][new_y] || dp[new_x][new_y] == 0)
                {
                    dp[new_x][new_y] = new_dis;
                    if(new_x == m - 1 && new_y == n - 1) return new_dis;
                    bfs_queue.push({new_dis, {new_x, new_y}});
                }
            }
        }
    }
    return -1;
}
};

参考:

https://leetcode.cn/circle/discuss/ldt5CI/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值