[Algorithm][模拟][替换所有问号][提莫攻击][N字形变换][外观数列][数青蛙] + 模拟原理详细讲解


0.原理讲解

  • 模拟:依照题目要求,照葫芦画瓢:P
  • 如果模拟题的时间复杂度和空间复杂度过高,则一般都需要进行优化
  • 优化:一般都是找规律

1.替换所有的问号

1.题目链接


2.代码实现

string ModifyString(string s) 
{
    for(int i = 0; i < s.size(); i++)
    {
        if(s[i] == '?')
        {
            for(char ch = 'a'; ch <= 'z'; ch++)
            {
                // || 短路设计比较精髓
                if((i == 0 || ch != s[i - 1]) && (i == n - 1 || ch != s[i + 1]))
                {
                    s[i] = ch;
                }
            }
        }
    }

    return s;
}

2.提莫攻击

1.题目链接


2.算法原理详解

  • 计算相邻两个时间点的差值:
    • 如果差值⼤于等于中毒时间,说明上次中毒可以持续duration
    • 如果差值⼩于中毒时间,那么上次的中毒只能持续两者的差值
      请添加图片描述

3.代码实现

int FindPoisonedDuration(vector<int>& timeSeries, int duration) 
{
    int ret = 0;
    for(int i = 1; i < timeSeries.size(); i++)
    {
        int interval = timeSeries[i] - timeSeries[i - 1];
        if(interval >= duration)
        {
            ret += duration;
        }
        else
        {
            ret += interval;
        }
    }

    return ret + duration;
}

3.N 字形变换

1.题目链接


2.算法原理详解

  • 本题可以照本宣科的按照要求存储 && 读取,但是此时时间复杂度和空间复杂度都很高
  • 模拟题优化:找规律
    请添加图片描述

3.代码实现

string Convert(string s, int numRows) 
{
    // 处理边界情况
    if(numRows == 1)
    {
        return s;
    }

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

    // 第一行
    for(int i = 0; i < n; i += d)
    {
        ret += s[i]; 
    }

    // 第二行 -- 倒数第二行
    for(int k = 1; k < numRows - 1; k++) // 枚举每一行
    {
        for(int i = k, j = d - k; i < n || j < n; i += d, j += d)
        {
            if(i < n)
            {
                ret += s[i];
            }

            if(j < n)
            {
                ret += s[j];
            }
        }
    }

    // 最后一行
    for(int i = numRows - 1; i < n; i += d)
    {
        ret += s[i];
    }

    return ret;
}

4.外观数列

1.题目链接


2.算法原理详解

  • 思路:模拟 + 双指针

3.代码实现

// 控制逻辑 v1.0
// 自己控代码的逻辑
string CountAndSay(int n) 
{
    string src = "1";
    for(int i = 2; i <= n; i++) // 控制行
    {
        // 双指针
        string ret;
        int left = 0, right = 0;

        for(; right < src.size(); right++)
        {
            if(src[left] != src[right])
            {
                ret += to_string(right - left) + src[left];
                left = right;
            }
        }

        // 处理最后的一组数
        ret += to_string(right - left) + src[left];

        src = ret;
    }

    return src;
}
--------------------------------------------------
// 控制逻辑 v2.0
// 此逻辑比较优秀,不需求额外处理结尾情况
string CountAndSay(int n) 
{
    string src = "1";
    for(int i = 2; i <= n; i++) // 控制行
    {
        // 双指针
        string ret;
        for(int left = 0, right = 0; right < src.size();)
        {
            while(right < src.size() && src[left] == src[right])
            {
                right++;
            }
            ret += to_string(right - left) + src[left];

            left = right;
        }

        src = ret;
    }

    return src;
}

5.数青蛙

1.题目链接

2.算法原理详解

  • 用哈希表来存储叫声

    请添加图片描述


3.代码实现

int MinNumberOfFrogs(string croakOfFrogs) 
{
    string str = "croak";
    int n = str.size();
    vector<int> hash(n); // 用数组模拟哈希

    unordered_map<char, int> index; // <ch, index>
    for(int i = 0; i < n; i++)
    {
        index[str[i]] = i;
    }

    for(auto& ch : croakOfFrogs)
    {
        if(ch == 'c')
        {
            if(hash[n - 1]) // k已存在
            {
                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];
}
  • 14
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DieSnowK

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值