当前位置:   article > 正文

算法思想总结:模拟算法_算法模拟法总结

算法模拟法总结

一、模拟算法的总结

1、本质:比葫芦画瓢

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

3、解决方法:

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

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

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

二、替换所有的问号

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

  1. class Solution {
  2. public:
  3. string modifyString(string s)
  4. {
  5. int n=s.size();
  6. for(int i=0;i<n;++i)
  7. if(s[i]=='?')//如果发现有字符为?,就要去替换
  8. for(char ch='a';ch<='z';++ch) //不能跟前面后面数相同,但是要注意边界情况
  9. if((i==0||ch!=s[i-1])&&(i==n-1||ch!=s[i+1]))
  10. {
  11. s[i]=ch;
  12. break;
  13. }
  14. return s;
  15. }
  16. };

三、提莫攻击

. - 力扣(LeetCode)提莫攻击

  1. class Solution {
  2. public:
  3. int findPoisonedDuration(vector<int>& timeSeries, int duration)
  4. {
  5. int n=timeSeries.size();
  6. int ret=0;//记录总中毒时间
  7. for(int i=1;i<n;++i)
  8. {
  9. int temp=timeSeries[i]-timeSeries[i-1];
  10. //如果后一次的中毒时间没有被覆盖,就是+duration 覆盖了就是+temp
  11. if(temp>=duration) ret+=duration; else ret+=temp;
  12. }
  13. return ret+duration;//最后还有一次持续时间!!
  14. }
  15. };

四、Z字形变换

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

  1. class Solution {
  2. public:
  3. string convert(string s, int numRows)
  4. {
  5. if(numRows==1) return s;//处理边界情况
  6. string ret;
  7. int n=s.size(),d=2*numRows-2;//d是公差
  8. //先处理第一行
  9. for(int i=0;i<n;i+=d) ret+=s[i];
  10. //处理中间的行
  11. for(int k=1;k<numRows-1;++k)//遍历行
  12. for(int i=k,j=d-k;i<n;i+=d,j+=d)
  13. {
  14. ret+=s[i];
  15. if(j<n) ret+=s[j];//可能i没越界但是j越界了
  16. }
  17. //处理最后一行;i+=d) ret+=s[i];
  18. for(int i=numRows-1;i<n;i+=d) ret+=s[i];
  19. return ret;
  20. }
  21. };

五、外观数列

. - 力扣(LeetCode)外观数列

  1. class Solution {
  2. public:
  3. string countAndSay(int n)
  4. {
  5. string ret("1");//基准样例
  6. for(int i=1;i<n;++i)
  7. {
  8. string temp;//每次都要更新
  9. int len=ret.size();
  10. //定义双指针 从前往后遍历相同的区域
  11. for(int left=0,right=0;right<len;)
  12. {
  13. while(right<len&&ret[left]==ret[right]) ++right;//相等就一直走
  14. //找到该区域了,就temp加上这块区域
  15. temp+=to_string(right-left)+ret[left];
  16. left=right;//更新left;
  17. }
  18. ret=temp;//找完后,更新即可
  19. }
  20. return ret;
  21. }
  22. };

六、数青蛙

. - 力扣(LeetCode)数青蛙

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

  1. class Solution {
  2. public:
  3. int minNumberOfFrogs(string croakOfFrogs)
  4. {
  5. //对于roak来说,判断前驱字符是否在哈希表中
  6. //在就--前驱 ++当前 不在 返回1
  7. //对于c来说,要判断k是否在哈希表中,如果在就--k然后++c 如果不在就直接++c
  8. string t="croak";
  9. int n=t.size();
  10. int hash[5]={0};//存储字符信息
  11. unordered_map<char,int> index;//用来建立字符和下标的映射关系
  12. for(int i=0;i<n;++i) index[t[i]]=i;//建立t字符串各字符和下标映射关系
  13. for(auto ch:croakOfFrogs)//开始研究
  14. {
  15. if(ch=='c')
  16. {
  17. if(hash[n-1]!=0) --hash[n-1];
  18. ++hash[index[ch]];
  19. }
  20. else
  21. {
  22. int i=index[ch];
  23. if(hash[i-1]==0) return -1;
  24. ++hash[i];
  25. --hash[i-1];
  26. }
  27. }
  28. for(int i=0;i<n-1;++i) if(hash[i]!=0) return -1;//最后还要再检查一次
  29. return hash[n-1];
  30. }
  31. };

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

  1. class Solution {
  2. public:
  3. int minNumberOfFrogs(string croakOfFrogs)
  4. {
  5. //对于roak来说,判断前驱字符是否在哈希表中
  6. //在就--前驱 ++当前 不在 返回1
  7. //对于c来说,要判断k是否在哈希表中,如果在就--k然后++c 如果不在就直接++c
  8. int hash[5]={0};//0 1 2 3 4 分别对应c r o a k
  9. int n=croakOfFrogs.size();
  10. for(int i=0;i<n;++i)
  11. {
  12. switch(croakOfFrogs[i])
  13. {
  14. case 'c':
  15. if(hash[4]) --hash[4];
  16. ++hash[0];
  17. break;
  18. case 'r':
  19. if(hash[0])
  20. {
  21. --hash[0];
  22. ++hash[1];
  23. }
  24. else return -1;
  25. break;
  26. case 'o':
  27. if(hash[1])
  28. {
  29. --hash[1];
  30. ++hash[2];
  31. }
  32. else return -1;
  33. break;
  34. case 'a':
  35. if(hash[2])
  36. {
  37. --hash[2];
  38. ++hash[3];
  39. }
  40. else return -1;
  41. break;
  42. case 'k':
  43. if(hash[3])
  44. {
  45. --hash[3];
  46. ++hash[4];
  47. }
  48. else return -1;
  49. break;
  50. }
  51. }
  52. //检查一下hash的前面是否都为0
  53. for(int i=0;i<4;++i) if(hash[i]) return -1;
  54. return hash[4];
  55. }
  56. };

七、频率跟踪器

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

  1. class FrequencyTracker {
  2. public:
  3. FrequencyTracker() :freq(N),freq_count(N){}
  4. void add(int number)
  5. {
  6. --freq_count[freq[number]];//该数字原先次数的频率减少
  7. ++freq[number];//该数字次数增加
  8. ++freq_count[freq[number]];//该数字对应次数的频率增加(更新)
  9. }
  10. void deleteOne(int number)
  11. {
  12. if(freq[number]==0) return;//可能没出现过
  13. //如果出现过,数字次数减少,原来频率要减少,先有频率要增加
  14. --freq_count[freq[number]];//该数字原先次数的频率减少
  15. --freq[number];//该数字次数减少
  16. ++freq_count[freq[number]];//该数字对应次数的频率增加(更新)
  17. }
  18. bool hasFrequency(int frequency) {return freq_count[frequency];}
  19. private:
  20. static const int N=100001;
  21. vector<int> freq;//统计各个数字出现的次数
  22. vector<int> freq_count;//统计各个频率的出现次数
  23. };

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/681192
推荐阅读
相关标签
  

闽ICP备14008679号