LeetCode周赛复盘(第343场周赛)


提示:以下是本篇文章正文内容,下面案例可供参考

1、 保龄球游戏的获胜者

1.1 题目链接

点击跳转到题目位置

1.2 题目描述

给你两个下标从 0 开始的整数数组 player1 和 player2 ,分别表示玩家 1 和玩家 2 击中的瓶数。

保龄球比赛由 n 轮组成,每轮的瓶数恰好为 10 。

假设玩家在第 i 轮中击中 xi 个瓶子。玩家第 i 轮的价值为:

如果玩家在前两轮中击中了 10 个瓶子,则为 2xi 。
否则,为 xi 。
玩家的得分是其 n 轮价值的总和。

返回

如果玩家 1 的得分高于玩家 2 的得分,则为 1 ;
如果玩家 2 的得分高于玩家 1 的得分,则为 2 ;
如果平局,则为 0 。

1.3 解题代码

class Solution {
public:
    int isWinner(vector<int>& player1, vector<int>& player2) {
        int sum0 = 0;
        int sum1 = 0;
        for(int i = 0; i < player1.size(); ++i){
            if(i == 0){
                sum0 += player1[i];
            } else if(i == 1){
                if(player1[0] == 10){
                    sum0 += (2*player1[i]);
                } else{
                    sum0 += player1[i];
                }
            } else{
                if(player1[i-1] == 10 || player1[i-2] == 10){
                    sum0 += (2*player1[i]);
                } else{
                    sum0 += player1[i];
                }
            }
        }
        for(int i = 0; i < player2.size(); ++i){
            if(i == 0){
                sum1 += player2[i];
            } else if(i == 1){
                if(player2[0] == 10){
                    sum1 += (2*player2[i]);
                } else{
                    sum1 += player2[i];
                }
            } else{
                if(player2[i-1] == 10 || player2[i-2] == 10){
                    sum1 += (2*player2[i]);
                } else{
                    sum1 += player2[i];
                }
            }
        }
        if(sum0 < sum1){
            return 2;
        } else if(sum0 > sum1){
            return 1;
        }
    return 0;
    }
};

1.4 解题思路

(1) 其实该段代码写的不好,实际上可以把算分合并成一个函数来解决即可。

(2) 直接一遍模拟算分即可,如果下标为0,则直接把对应的分数加上即可,如果下标为1的话,则判断下标为0的地方是否为10分,为10分,则加双倍分,否则加单倍分。如果下标大于1的时候,判断前两次得分是否有10分的,有的话则加双倍分,否则加单倍分。

(3) 最后比较得出结果即可。

2、找出叠涂颜元素

2.1 题目链接

点击跳转到题目位置

2.2 题目描述

给你一个下标从 0 开始的整数数组 arr 和一个 m x n 的整数 矩阵 mat 。arr 和 mat 都包含范围 [1,m * n] 内的 所有 整数。

从下标 0 开始遍历 arr 中的每个下标 i ,并将包含整数 arr[i] 的 mat 单元格涂色。

请你找出 arr 中在 mat 的某一行或某一列上都被涂色且下标最小的元素,并返回其下标 i 。

2.3 解题代码

class Solution {
    unordered_map<int, int> line;
    unordered_map<int, int> row;
    unordered_map<int, int> row1;
    unordered_map<int, int> line1;
public:
    int firstCompleteIndex(vector<int>& arr, vector<vector<int>>& mat) {
        int m = mat.size();
        int n = mat[0].size();
        int len = arr.size();
        int judge_row = n;
        int judge_line = m;
        for(int i = 0; i < m; ++i){
            for(int j = 0; j < n; ++j){
                row1[mat[i][j]] = i;
                line1[mat[i][j]] = j;
            }
        }
        for(int i = 0; i < len; ++i){
            int x = row1[arr[i]];
            int y = line1[arr[i]];
            row[x]++;
            line[y]++;
            if(row[x] == judge_row || line[y] == judge_line){
                return i;
            }
        }
    return 0;
    }
};

2.4 解题思路

(1) 用四个哈希表分别来记录某一行的元素个数,某一列的元素个数,该数字在哪一行,该数字在哪一列。

(2) 然后遍历一维数组,然后将该数字所在的行的元素数目+1,该数字所在的列的元素数目+1,如果出现行或者列涂满,在输出该数字的下标即可。

3、前往目标的最小代价(未来补充)

3.1 题目链接

点击跳转到题目位置

3.2 题目描述

给你一个数组 start ,其中 start = [startX, startY] 表示你的初始位置位于二维空间上的 (startX, startY) 。另给你一个数组 target ,其中 target = [targetX, targetY] 表示你的目标位置 (targetX, targetY) 。

从位置 (x1, y1) 到空间中任一其他位置 (x2, y2) 的代价是 |x2 - x1| + |y2 - y1| 。

给你一个二维数组 specialRoads ,表示空间中存在的一些特殊路径。其中 specialRoads[i] = [x1i, y1i, x2i, y2i, costi] 表示第 i 条特殊路径可以从 (x1i, y1i) 到 (x2i, y2i) ,但成本等于 costi 。你可以使用每条特殊路径任意次数。

返回从 (startX, startY) 到 (targetX, targetY) 所需的最小代价。

3.3 解题代码

3.4 解题思路

4、字典序最小的美丽字符串

4.1 题目链接

点击跳转到题目位置

4.2 题目描述

如果一个字符串满足以下条件,则称其为 美丽字符串

它由英语小写字母表的前 k 个字母组成。
它不包含任何长度为 2 或更长的回文子字符串。
给你一个长度为 n 的美丽字符串 s 和一个正整数 k 。

请你找出并返回一个长度为 n 的美丽字符串,该字符串还满足:在字典序大于 s 的所有美丽字符串中字典序最小。如果不存在这样的字符串,则返回一个空字符串。

对于长度相同的两个字符串 a 和 b ,如果字符串 a 在与字符串 b 不同的第一个位置上的字符字典序更大,则字符串 a 的字典序大于字符串 b 。

例如,“abcd” 的字典序比 “abcc” 更大,因为在不同的第一个位置(第四个字符)上 d 的字典序大于 c 。

4.3 解题代码

class Solution {
public:
    string smallestBeautifulString(string s, int k) {
        int n = s.size();
        string res = s;
        k--;
        for(int i = n-1; i >= 0; --i){
            int flag = 0;
            if(s[i] - 'a' == k){
                continue;
            } 
            if(i == 1){
                for(int j = s[i] - 'a' + 1; j <= k; ++j){
                    if(j != s[0] - 'a'){
                        s[i] = char(j + 'a');
                        flag = 1;
                        break;
                    }    
                }
            } else if(i == 0){
                flag = 1;
                s[i] = char(++s[i]);
            } else{
                for(int j = s[i] - 'a' + 1; j <= k; ++j){
                    if(j != s[i-1] - 'a' && j != s[i-2] - 'a'){
                        s[i] = char(j + 'a');
                        flag = 1;
                        break;
                    }
                }
            }
            if(flag == 1){
                for(int j = i + 1; j < n; ++j){
                    if(j == 1){
                        for(int t = 0; t <= k; ++t){
                            if(t != s[j-1] - 'a'){
                                s[j] = char(t + 'a');
                            }
                            break;
                        }
                    } else{
                        for(int t = 0; t <= k; ++t){
                            if(t != s[j-1] - 'a' && t != s[j-2] - 'a'){
                                s[j] = char(t + 'a');
                                break;
                            }
                        }
                    }
                }
                return s;
            }
        }
    return "";
    }
};

4.4 解题思路

(1) 字典序越小,所以要从后往前遍历去修改。

(2) 因为遍历到的位置要修改,遍历到位置后面的字母都需要修改,所以只需要考虑以该字符为末尾,前面的字符串是否为完美字符串,当前位置的字母修改能成为字典序最大的完美字符串,则修改该字母。修改的范围为s[i] + 1~ ‘a’ + k - 1.

(3) 接着修改修改位置~最后的字母,修改的范围为’a’ ~ ‘a’ + k - 1。

(4) 按照上述策略去修改,就能得到字典序最小且符合要求的完美字符串。如果没得到,则输出“”即可。

打鸡血

心若在,梦就在,只不过是从头再来。哪怕每次周赛一题都做不出来,都得努力去研究,因为未来的某一天

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值