LeetCode314周赛


第一题
找出花费时间最长的员工id号,如果花费时间相同,返回id号小那个。
在这里插入图片描述
当前完成工作时刻-上一个完成工作时刻 = 完成任务花费的时间,因此遍历一遍数组即可。时间复杂度O(n)

ac代码:

int hardestWorker(int n, vector<vector<int>>& logs) {
        int m = logs.size();
        int len = logs[0][1], id = logs[0][0];
        for(int i = 1; i < m; i++){
            int x = logs[i][1] - logs[i - 1][1];
            if(len < x){
                len = x;
                id = logs[i][0];
            }
            if(len == x){
                id = min(id, logs[i][0]);
            }
        }
        return id;
    }

第二题

在这里插入图片描述
累计异或值 ^ ans = 当前值,移项得ans = 当前值 ^ 累计异或值,遍历一遍即可,时间复杂度为O(n)

累计和的写法是模仿高精度加法来写的。

ac代码:

 vector<int> findArray(vector<int>& pref) {
        int n = pref.size();
        vector<int> res(n);
        res[0] = pref[0];
        int t = res[0];
        for(int i = 1; i < n; i++){
            //当前值异或累计和t
            res[i] = pref[i] ^ t;
            t ^= res[i];
        }
        return res;
    }

第三题

在这里插入图片描述
在这里插入图片描述
把题目意思提炼出来即为:有一个字符串s,给一个栈t,请你借助这个栈返回字典序最小的是s的排列。

方法是贪心, 因此思路比较跳跃。

由于栈顶是输出出来的第一个字符,当第一个字符的字典序越小, 整一个字符串的字典序就越小。

因此思路是:遍历s, 把当前元素push进栈, 比较栈顶和当前元素后面所有字符里字典序最小的字符。

  1. 如果栈顶小于当前元素后面所有字符,那么证明当前栈顶元素是最小的。应当优先输出。
  2. 如果栈顶大于当前元素后面所有字符,证明当前元素后面还有字符是字典序更小的存在,应该优先输出它们。

遍历完s后,如果stack里面还有字符,全部按顺序输出即可。

如果不加优化, 那么时间复杂度是O(n^2), 因为比较栈顶和当前元素后面所有字符是O(n)的。

因此可以先预处理一下,每一个以i为起点,n为结尾的序列最小的字符是什么。(这是一个简单的dp)

ac代码:

string robotWithString(string s) {
        int n = s.size();
        vector<char> f(n + 1);
        初始化
        f[n] = 'z' + 1;
        求一下dp,每一个以i为起点,n为结尾的序列最小的字符是什么
        for(int i = n - 1; i >= 0; i--) f[i] = min(f[i + 1], s[i]);

        string ans;
        stack<char> stk;
        for(int i = 0; i < n; i++){
        	把当前元素放进栈里面
            stk.push(s[i]);
            比较栈顶元素和后面的字符哪一个比较小
            while(stk.size() && stk.top() <= f[i + 1]) ans.push_back(stk.top()), stk.pop();
        }
        栈不空就全部输出出来
        while(stk.size()){
            ans.push_back(stk.top());
            stk.pop();
        }
        return ans;
    }

第四题

在这里插入图片描述
在这里插入图片描述
题型:数字三角形类型。在原有坐标上加上一个维度维护余数

状态定义:f[i][j][r] 在i, j的坐标里路径和模k余数是r
状态属性:cnt(状态之间相加)
状态转移:由于只能由左边和上边转移下来,因此状态转移方程还是类似的。
f[i][j][r] = f[i - 1][j][xxx] + f[i][j - 1][xxx]

问题就是这个xxx是什么了。可以推导一下:
在这里插入图片描述
所以
f[i][j][r] = f[i - 1][j][((r - gird[i][j] % k) + k) % k] + f[i][j - 1][((r - gird[i][j] % k) + k) % k]
这个+k模k的操作其实在数组下标–里面也用过。idx = ((idx - 1) + len) % len; 和这个类似

其实也可以这么写,既然r-grid[i][j] % k有可能小于0, 那么等式两边同时+grid[i][j] % k即可。

ac代码:

int numberOfPaths(vector<vector<int>>& grid, int k) {
        int n = grid.size(), m = grid[0].size();
        const int MOD = 1e9 + 7;
        long long f[n + 1][m + 1][k];
        memset(f, 0, sizeof f);
        f[1][1][grid[0][0] % k] = 1;
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= m; j++){
                for(int r = 0; r < k; r++){
                    if(i == 1 && j == 1) continue;
                    f[i][j][r] = (f[i - 1][j][(r - grid[i - 1][j - 1] % k + k) % k] + f[i][j - 1][(r - grid[i - 1][j - 1] % k + k) % k]) % MOD; 
                }
            }
        }
        return f[n][m][0];
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值