Leetcode第314场周赛

在这里插入图片描述

题目链接

竞赛 - 力扣 (LeetCode)

题目解析

A.6200. 处理用时最长的那个任务的员工

AC代码

class Solution {
public:
    int hardestWorker(int n, vector<vector<int>>& logs) {
        vector<int> cnt(n, 0);
        int ans = -1, ansCnt = -1;
        int last = 0, t;
        for (auto &arr : logs) {
            t = arr[1] - last;
            if (t > ansCnt) {
                ansCnt = t;
                ans = arr[0];
            } else if (t == ansCnt && arr[0] < ans) {
                ans = arr[0];
            }
            last = arr[1];
        }
        return ans;
    }
};

思路分析

其实是一道很简单的题目,但是我没有认真读题竟然还wa了两次,觉得非常不应该。一直以来觉得第一道题非常简单于是写的时候都没有想太多,今天抱着同样的态度结果没有搞清楚题目意思就开始写,wa两次的罚时远远大于认真思考的时间。一定要认真谨慎,不管在面对什么问题。

B.6201. 找出前缀异或的原始数组

AC代码

class Solution {
public:
    vector<int> findArray(vector<int>& pref) {
        int n = pref.size();
        vector<int> ans(n);
        ans[0] = pref[0];
        for (int i = 1; i < n; ++i) {
            ans[i] = pref[i] ^ pref[i - 1];
        }
        return ans;
    }

};

思路分析

根据异或的性质很快可以得出ans[i]=pref[i]^pref[i - 1]

C.6202. 使用机器人打印字典序最小的字符串

AC代码

class Solution {
public:
    string robotWithString(string s) {
        int n = s.size();
        vector<pair<char, int>> cnt(n);
        cnt[n - 1] = make_pair(s[n - 1], n - 1);
        for (int i = n - 2; i >= 0; --i) {
            if (s[i] <= cnt[i + 1].first) {
                cnt[i] = make_pair(s[i], i);
            } else {
                cnt[i] = cnt[i + 1];
            }
        }
        string t;
        t.push_back('z' + 1);
        string ans;
        int idx = 0;
        while (idx < n) {
            auto [c, small] = cnt[idx];
            if (c < t.back()) {
                for (int i = idx; i < small; ++i) t.push_back(s[i]);
                ans.push_back(c);
                idx = small + 1;
            } else {
                ans.push_back(t.back());
                t.pop_back();
            }
        }
        int nn = t.size();
        for (int i = nn - 1; i > 0; --i) ans.push_back(t[i]);
        return ans;
    }
};

思路分析

一个贪心+模拟,主要的贪心策略就是:为当前位置放置可以放置的最小字符。这个字符的来源有两个:一个是s,一个是t,如果在s中,那么我们就要将最小字符前面的字符放在t中,而t只能取最后一个字符。为了确定来自哪里,我们从后往前处理出s当前位置后面最小的字符是哪个

初始情况下s中的任意字符都比t小,为了避免复杂的判断,这里技巧性地给t中先验性地填入了一个最大字符(’z’ + 1)。总体来说还是实现的比较优雅的。

D.6203. 矩阵中和能被 K 整除的路径

AC代码

class Solution {
public:
    int numberOfPaths(vector<vector<int>>& grid, int k) {
        using ll = long long;
        static constexpr ll MOD = 1e9 + 7;
        int n = grid.size();
        int m = grid[0].size();
        vector<vector<ll>> dp(m, vector<ll>(k));
        auto update0 = [&](vector<ll> &now, int t) {
            vector<ll> last(k);
            for (int i = 0; i < k; ++i) {
                last[(i + t) % k] += now[i];
            }
            now.swap(last);
        };
        auto update1 = [&](vector<ll> &now, const vector<ll> &last, int t) {
            for (int i = 0; i < k; ++i) {
                int tmp = (i + t) % k;
                now[tmp] += last[i];
                if (now[tmp] > MOD) {
                    now[tmp] %= MOD;
                }
            }
        };
        auto deal = [&](int x, int y, int dir) {
            if (dir == 0) {
                //从上方更新
                update0(dp[y], grid[x][y]);
            } else {
                //从左方更新
                update1(dp[y], dp[y - 1], grid[x][y]);
            }
        };
        dp[0][grid[0][0] % k] = 1;
        for (int j = 1; j < m; ++j) {
            deal(0, j, 1);
        }
        for (int i = 1; i < n; ++i) {
            deal(i, 0, 0);
            for (int j = 1; j < m; ++j) {
                deal(i, j, 0);
                deal(i, j, 1);
            }
        }
        return dp[m - 1][0];
    }
};

思路分析

很浓重的dp色彩,每一个位置从上边或者左边转移而来。可能朴素的做法是维护所有路径的和,但是由于我们要判断的是是否整除,因此技巧性地不断对和取余,维护的是k的剩余系,这样有效地缩小了每个状态的大小。

除此之外,由于我们是按照从左到右,从上到下的搜索顺序,所以我们可以利用滚动数组优化空间复杂度,只保存每一行的状态,然后优先从上边更新(也就是自身),再从左边更新。

自己在优先的时间内还能够想到这种优化空间复杂度的做法,的确是很机智。

整体代码的实现也是比较好的,用lambda表达式封装更新动作。

就是在初始状态的更新上犯了一点点错误。而且还把1e9+7写成了109+7,我记得我之前就因为这个问题wa过,这次又犯。。。主要是题面给的就是109+7,我吐了。害得我debug好久才发现这个问题。

周赛总结

优点

  • 思路敏捷,代码实现快速,代码结构清晰

缺点

  • 轻视简单题造成不必要的罚时
  • 因为细节问题导致出错,应该再小心谨慎些

改进方案

小心谨慎,注意题面,注意数据范围,注意初始状态

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值