前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >算法思想总结:模拟算法

算法思想总结:模拟算法

作者头像
小陈在拼命
发布2024-03-23 09:10:20
900
发布2024-03-23 09:10:20
举报

一、模拟算法的总结

1、本质:比葫芦画瓢

2、特点:思路较简单,根据题目要求即可,代码量和细节较多

3、解决方法:

(1) 模拟算法流程,在草稿纸上进行演算

(2) 认真审题,考虑细节问题和边界情况

(3) 一步步将流程转化为代码

二、替换所有的问号

. - 力扣(LeetCode)替换所有的问号

代码语言:javascript
复制
class Solution {
public:
    string modifyString(string s) 
    {
       int n=s.size();
       for(int i=0;i<n;++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;
                break;
              }
       return s;
    }
};

三、提莫攻击

. - 力扣(LeetCode)提莫攻击

代码语言:javascript
复制
class Solution {
public:
    int findPoisonedDuration(vector<int>& timeSeries, int duration) 
    {
        int n=timeSeries.size();
        int ret=0;//记录总中毒时间
        for(int i=1;i<n;++i) 
        {
            int temp=timeSeries[i]-timeSeries[i-1];
            //如果后一次的中毒时间没有被覆盖,就是+duration 覆盖了就是+temp
            if(temp>=duration) ret+=duration; else ret+=temp;
        }
        return ret+duration;//最后还有一次持续时间!!
    }
};

四、Z字形变换

. - 力扣(LeetCode)Z字形变换

代码语言:javascript
复制
class Solution {
public:
    string convert(string s, int numRows) 
    {
       if(numRows==1) return s;//处理边界情况
       string ret;
       int n=s.size(),d=2*numRows-2;//d是公差
       //先处理第一行
       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;i+=d,j+=d)
           {
                  ret+=s[i];
                  if(j<n) ret+=s[j];//可能i没越界但是j越界了
           }
       //处理最后一行;i+=d) ret+=s[i];
       for(int i=numRows-1;i<n;i+=d) ret+=s[i];
       return ret;
    }
};

五、外观数列

. - 力扣(LeetCode)外观数列

代码语言:javascript
复制
class Solution {
public:
    string countAndSay(int n) 
    {
      string ret("1");//基准样例
      for(int i=1;i<n;++i)
      {
        string temp;//每次都要更新
        int len=ret.size();
        //定义双指针 从前往后遍历相同的区域
        for(int left=0,right=0;right<len;)
        {
            while(right<len&&ret[left]==ret[right]) ++right;//相等就一直走
            //找到该区域了,就temp加上这块区域
            temp+=to_string(right-left)+ret[left];
            left=right;//更新left;
        }
        ret=temp;//找完后,更新即可
      }
      return ret;
    }
};

六、数青蛙

. - 力扣(LeetCode)数青蛙

写法1: 两个哈希表 一个存储字符和下标的映射关系,另一个用数组模拟哈希表存字符出现的次数。

代码语言:javascript
复制
class Solution {
public:
    int minNumberOfFrogs(string croakOfFrogs) 
    {
       //对于roak来说,判断前驱字符是否在哈希表中
       //在就--前驱  ++当前     不在 返回1
       //对于c来说,要判断k是否在哈希表中,如果在就--k然后++c  如果不在就直接++c
       string t="croak";
       int n=t.size();
       int hash[5]={0};//存储字符信息
       unordered_map<char,int> index;//用来建立字符和下标的映射关系
       for(int i=0;i<n;++i)  index[t[i]]=i;//建立t字符串各字符和下标映射关系
       for(auto ch:croakOfFrogs)//开始研究
       {
        if(ch=='c')
        {
           if(hash[n-1]!=0) --hash[n-1];
           ++hash[index[ch]];
        }
        else
        {
            int i=index[ch];
            if(hash[i-1]==0) return -1;
            ++hash[i];
            --hash[i-1];
        }
       }
       for(int i=0;i<n-1;++i)  if(hash[i]!=0) return -1;//最后还要再检查一次
       return hash[n-1];
    }
};

写法2:只用一个数组模拟的哈希表,手动去控制字符和下标的映射关系(用switch语句)

代码语言:javascript
复制
class Solution {
public:
    int minNumberOfFrogs(string croakOfFrogs) 
    {
       //对于roak来说,判断前驱字符是否在哈希表中
       //在就--前驱  ++当前     不在 返回1
       //对于c来说,要判断k是否在哈希表中,如果在就--k然后++c  如果不在就直接++c
       int hash[5]={0};//0 1 2 3 4 分别对应c r o a k
       int n=croakOfFrogs.size();
       for(int i=0;i<n;++i)
       {
        switch(croakOfFrogs[i])
        {
            case 'c':
            if(hash[4]) --hash[4];
            ++hash[0];
            break;
            case 'r':
            if(hash[0]) 
            {
                --hash[0];
                ++hash[1];
            }
            else return -1;
            break;
            case 'o':
            if(hash[1]) 
            {
                --hash[1];
                ++hash[2];
            }
            else return -1;
            break;
            case 'a':
            if(hash[2]) 
            {
                --hash[2];
                ++hash[3];
            }
            else return -1;
            break;
            case 'k':
            if(hash[3]) 
            {
                --hash[3];
                ++hash[4];
            }
            else return -1;
            break;
        }
       }   
       //检查一下hash的前面是否都为0
       for(int i=0;i<4;++i) if(hash[i]) return -1; 
       return hash[4]; 
    }
};

七、频率跟踪器

. - 力扣(LeetCode)频率跟踪器

代码语言:javascript
复制
class FrequencyTracker {
public:
    FrequencyTracker() :freq(N),freq_count(N){} 
    
    void add(int number) 
    {
       --freq_count[freq[number]];//该数字原先次数的频率减少
       ++freq[number];//该数字次数增加
       ++freq_count[freq[number]];//该数字对应次数的频率增加(更新)
    }
    
    void deleteOne(int number) 
    {
       if(freq[number]==0) return;//可能没出现过
       //如果出现过,数字次数减少,原来频率要减少,先有频率要增加
       --freq_count[freq[number]];//该数字原先次数的频率减少
       --freq[number];//该数字次数减少
       ++freq_count[freq[number]];//该数字对应次数的频率增加(更新)
    }
    bool hasFrequency(int frequency)  {return freq_count[frequency];}
private:
     static const int N=100001;
     vector<int>  freq;//统计各个数字出现的次数
     vector<int>  freq_count;//统计各个频率的出现次数
};
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-03-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、模拟算法的总结
  • 二、替换所有的问号
  • 三、提莫攻击
  • 四、Z字形变换
  • 五、外观数列
  • 六、数青蛙
  • 七、频率跟踪器
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档