LeetCode第261场周赛题解

本文介绍了四道算法题目的解题思路和代码实现,包括字符串的最少转换次数、缺失观测数据的寻找、石子游戏的策略分析以及含特定字母的最小子序列的构造。涉及的主要算法思想有贪心、遍历、动态规划等,展示了在不同问题中如何运用编程技巧解决问题。

2021.10.3第261场周赛

2027. 转换字符串的最少操作次数

思路

从前往后遍历一遍,如果当前字符为X,进行转换,转换一个改变三个字符

代码

class Solution {
public:
    int minimumMoves(string s) {
        int ans = 0;
        int n = s.size();
        for (int i = 0; i < n; i ++ ) {
            if (s[i] == 'X') {
                ans ++ ;
                s[i] == 'O';
                if (i + 1 < n)
                    s[i + 1] = 'O';
                if (i + 2 < n)
                    s[i + 2] = 'O';
            }
        }
        return ans;
    }
};

2028. 找出缺失的观测数据

思路

目的是构造一个长度为 n 的序列,使这个序列的和为给定的值 sum,且序列的值在[1, 6]之间
sum 小于 1 * n 或大于 6 * n,该序列不存在
否则给每个值赋初值为 1,随后按照应赋尽赋进行其他的值的安排

代码

class Solution {
public:
    vector<int> missingRolls(vector<int>& rolls, int mean, int n) {
        int m = rolls.size();
        int sum = (m + n) * mean;
        for (int x : rolls)
            sum -= x;
        vector<int> ans;
        if (sum < n || sum > n * 6)
            return ans;
        sum -= n; //给每个值赋初值1
        for (int i = 0; i < n; i ++ ) {
            if (sum == 0) //为0则赋1
                ans.push_back(1);
            else {
                ans.push_back(min(sum, 5) + 1); //赋不超过6的数
                if (sum >= 5)
                    sum -= 5; //最初都减过1 这里最多减5
                else
                    sum = 0;
            }
        }
        return ans;
    }
};

2029. 石子游戏 IX

思路

由于题目只需判断是和是否为3的倍数,故可将所有数模3后记录数量
主要思想:让对手凑成3
先手不能选0,只能选1或2
选1时,序列为1121212…
选2时,序列为22121212…
期间选0不影响顺序
记1和2数量大的数为large,小的为small
此序列必定导致1或2数量不足,此时考虑0的个数的奇偶性,若为偶,先手必胜,条件为small>0
small等于0时可能存在

  • 1或2数量为0,对手无法通过1+2凑成3,由于先手必选1或2,对手选0即可,0数量为偶数,交替选完后,石子被选完或者我方选到3个相同,故必败
  • 1和2全为0,只能选0,必败

当0的数量时奇数时,先手不一定必败,由于是奇数选完0后双方状态交换,1和2相互抵消后,若剩余的相同数字大于2个,则先手必胜,否则提前选完所有数,先手必败

代码

class Solution {
public:
    bool stoneGameIX(vector<int>& stones) {
        vector<int> a(3);
        for (int x : stones)
            a[x % 3] ++ ;
        int small = min(a[1], a[2]), large = max(a[1], a[2]);
        if (a[0] % 2 == 0) {
            if (small > 0)
                return true;
            return false;
        }
        else {
            if (large - small > 2)
                return true;
            return false;
        }
    }
};

2030. 含特定字母的最小子序列

思路

类似 316. 去除重复字母 的思路
用贪心的思想,构造一个单调栈,按照特定情况进行弹栈和压栈操作,具体看注释

代码

class Solution {
public:
    string smallestSubsequence(string s, int k, char letter, int repetition) {
        int n = s.size();
        int all_letter = 0; //当前位及当前位后面letter的数量和
        for (char c : s)
            if (c == letter)
                all_letter ++ ;
        string ans;
        int cur = 0; //答案序列中letter的数量
        for (int i = 0; i < n; i ++ ) {
        	//弹栈
        	//如果当前位比栈中最后一位字符更优 且 弹出最后一位字符后仍能满足答案序列的长度k
            while (ans.size() && ans.back() > s[i] && (ans.size() - 1 + n - i >= k)) {
            	//如果要弹出的为目标字符 且 弹出后目标字符的个数无法满足重复次数 此时不能弹出
                if (ans.back() == letter && all_letter + cur - 1 < repetition)
                    break;
                //否则可以弹出 并记录答案序列中letter的数量
                if (ans.back() == letter)
                    cur -- ;
                ans.pop_back();
            }
            //记录当前位及当前位后面letter的数量和
            if (s[i] == letter)
                all_letter -- ;
            //压栈
            //数量不足时才压栈
            if (ans.size() < k) {
            	//如果当前位为目标字符 压栈
            	//如果当前位不为目标字符 但答案序列除了能放进缺少的目标字符外还有空余位置 压栈
                if (s[i] == letter || (k - ans.size()) > max(0, repetition - cur)) {
                    ans.push_back(s[i]);
                    cur += s[i] == letter;
                }
            }
        }
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值