算法—模拟

目录

替换所有的问号

提莫攻击

[Z 字形变换](#Z 字形变换)

外观数列

数青蛙


注意: 模拟算法其实就是将题目描述的流程转换为代码,当根据题目流程转换后时间复杂度或者空间复杂度特别高时通常可以通过找规律来优化代码。

替换所有的问号

**思路:**遍历字符串,碰到 '?' 就进行替换,替换时从 a~z 尝试即可,只要不和前后的字符重复即可,但是需要考虑一些特殊情况,第一个字符如果是 '?' 替换时就不需要比前面的字符了,最后一个字符如果是 '?' 替换时就不需要比后面的字符了。

代码:

cpp 复制代码
class Solution {
public:
    string modifyString(string s) {
        for(int i = 0; i < s.size(); i++){
            if(s[i] == '?'){
                for(int j = 0; j < 26; j++){
                    if(i - 1 >= 0)
                        if(s[i - 1] == 'a' + j)
                            continue;

                    if(i + 1 < s.size())
                        if(s[i + 1] == 'a' + j)
                            continue;

                    s[i] = 'a' + j;
                    break;
                }
            }
        }

        return s;
    }
};

提莫攻击

**思路:**当两次攻击时间的差值 >= duration 时,说明第二次攻击是在第一次中毒状态结束后攻击的,此时第一次攻击的中毒时间按 duration 算;当两次攻击时间的差值 < duration 时,说明第二次攻击是在第一次中毒状态还没结束就攻击了,此时第一次攻击中毒的持续时间只需要按两次攻击的时间差算就行。以此类推,直到最后一次攻击,因为最后一次攻击持续时间一定是 duration,所以最后一次攻击不需要像前面那样比较,直接向结果中加 duration 即可。

代码:

cpp 复制代码
class Solution {
public:
    int findPoisonedDuration(vector<int>& timeSeries, int duration) {
        int ret = 0;
        for(int i = 0; i < timeSeries.size(); i++){
            if(i == timeSeries.size() - 1 || timeSeries[i + 1] - timeSeries[i] >= duration)
                ret += duration;
            else 
                ret += timeSeries[i + 1] - timeSeries[i];
        }

        return ret;
    }
};

Z 字形变换

思路: 这道题主要是找给定的行数和字符按照Z形排列后的下标之间的关系,然后根据这个关系,在遍历字符串的时候直接依次取出相应的字符拼接成结果字符串。具体如图:

代码:

cpp 复制代码
class Solution 
{
public:
    string convert(string s, int numRows) 
    {
        if(numRows == 1)
            return s;

        string ret;
        int n = s.size();
        int d = numRows * 2  - 2;

        for(int i = 0; i < n; i += d)
        {
            ret += s[i];
        }
        for(int i = 1; i < numRows - 1; i++)
        {
            for(int k = i, j = d - k; k < n || j < n; k += d, j += d)
            {
                if(k < n)
                    ret += s[k];
                if(j < n)
                    ret += s[j];
            }
        }
        for(int i = numRows - 1; i < n; i += d)
        {
            ret += s[i];
        }

        return ret;
    }
};

外观数列

**思路:**还是模拟的思想,直接将题目描述的过程转化成代码,另外还需要使用双指针来配合模拟的过程,方便确定连续的相同数字的区间。具体如图:

  • left 指针指向的数字就是当前需要描述的数字。
  • right - left 就是当前要描述的数字的个数。
  • 当前区间描述完让 left 移动到 right 位置,继续找下一个区间即可。

代码:

cpp 复制代码
class Solution {
public:
    string countAndSay(int n) {
        string ret = "1";
        for(int i = 1; i < n; i++){
            int left = 0;
            int right = 0;
            string tmp;
            while(right < ret.size()){
                while(ret[left] == ret[right])
                    right++;
                tmp += (right - left) + '0';
                tmp += ret[left];
                left = right;
            }
            ret = tmp;
        }

        return ret;
    }
};

数青蛙

**思路:**创建一个哈希表,存储 croak 中每个字符和对应出现次数的映射关系,遍历字符串,当前遍历的字符是 roak 中的任意一个时,找一下哈希表中当前字符的前驱字符是否在哈希表中存在,如果存在,说明有青蛙叫了上一个字符,让这个青蛙接下来叫这个字符,即前面的字符个数自减 1,当前字符数量自加 1,如果前面字符不存在,说明字符串不是有效组合,因为题目要求字符串必须由若干有效的croak组成,而当前字符的前驱字符不存在,说明当前遍历的这个 croak 是不完整的,返回 -1。如果当前遍历的字符是 c,找 k 对应次数是否大于 0,如果大于零,让 k 自减 1,c 对应个数自加 1,否则只让 c 的个数自加 1即可,因为题目要求最少的青蛙,叫到 k 的青蛙已经叫完了完整的一声,所以当遇到 c 时,如果有青蛙叫完了,可以让叫完的青蛙去继续叫。

代码:

cpp 复制代码
class Solution {
public:
    int minNumberOfFrogs(string croakOfFrogs) {
        string t = "croak";
        int n = t.size();
        vector<int> hash(n); //用数组模拟哈希表

        unordered_map<char, int> index; //存放每个字符和对应的下标
        for(int i = 0; i < n; i++) 
            index[t[i]] = i;

        for(auto ch : croakOfFrogs)
        {
            if(ch == 'c')
            {
                if(hash[n - 1] != 0)
                    hash[n - 1]--;
                hash[0]++;
            }
            else
            {
                int i = index[ch];
                if(hash[i - 1] == 0)
                    return -1;
                hash[i - 1]--;
                hash[i]++;
            }
        }

        for(int i = 0; i < n - 1; i++)
        {
            if(hash[i] != 0)
                return -1;
        }

        return hash[n - 1];
    }
};
相关推荐
志尊宝1 分钟前
Vue3 零基础每日笔记(071):暗黑模式与主题切换——CSS 变量 + Element Plus 暗黑方案
前端·css·笔记·vue·html·前端开发·软件开发
不会就选b5 分钟前
算法日常・每日刷题--<动态规划>19
算法·leetcode·职场和发展
沫璃染墨1 小时前
《Qt从零入门系列(十三):QSS样式表详解——从选择器与层叠规则到控件美化实战》
开发语言·css·c++·qt·ui·qt6.3·qss
没有钱的钱仔1 小时前
协方差矩阵含义
算法·机器学习·矩阵
垆边人似月.1 小时前
华为机试题 :和为 K 的子数组个数
算法·leetcode·华为
沪上企服通2 小时前
历史账套科目重映射与规则版本重算:旧账梳理的“口径复位”工程
笔记·架构
三*一2 小时前
优化修整算法
前端·javascript·算法
上海广测检测科技有限公司2 小时前
标签打印机CE与台湾BSMI+NCC双轨认证详解:多射频模块与电气安全叠加路径
经验分享
达子6662 小时前
RUST 图解 第 3 章:通用编程概念(Common Programming Concepts)
开发语言·算法·rust