算法思想总结:模拟算法

简介: 算法思想总结:模拟算法

一、模拟算法的总结

1、本质:比葫芦画瓢

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

3、解决方法:

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

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

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

二、替换所有的问号

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

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)提莫攻击

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字形变换

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)外观数列

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: 两个哈希表  一个存储字符和下标的映射关系,另一个用数组模拟哈希表存字符出现的次数。

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语句)

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)频率跟踪器

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;//统计各个频率的出现次数
};

 

相关文章
|
6月前
|
存储 机器学习/深度学习 并行计算
95% 的算法都是基于这 6 种算法思想 (详细介绍)
95% 的算法都是基于这 6 种算法思想 (详细介绍)
147 4
|
7月前
|
算法
算法思想总结:前缀和算法
算法思想总结:前缀和算法
|
7月前
|
算法
算法思想总结:滑动窗口算法
算法思想总结:滑动窗口算法
|
7月前
|
算法 容器
算法思想总结:双指针算法
算法思想总结:双指针算法
|
算法 大数据 图形学
大数据开发基础的数据结构和算法的算法思想的递归
在大数据开发中,递归算法是一种基础算法思想。它通常用于解决复杂问题的求解和实现,通过不断地将一个问题分解成更小的子问题,最终得到问题的解决方案。
96 0
|
算法 大数据 开发者
大数据开发基础的数据结构和算法的算法思想的回溯
在大数据开发中,算法的思想对于解决各种问题都非常重要,其中回溯算法是一种非常重要的算法思想,它可以用于解决许多实际问题,并且具有高效、可扩展等优点。
131 0
|
算法 大数据 定位技术
大数据开发基础的数据结构和算法的算法思想的动态规划
当今,随着大数据的广泛应用,数据结构和算法成为了大数据开发中不可或缺的一部分。动态规划作为其中的一种算法思想,被广泛使用于求解最优化问题。本篇文章主要介绍大数据开发基础的数据结构和算法的算法思想的动态规划。
105 0
|
算法 大数据 开发者
大数据开发基础的数据结构和算法的算法思想的分治
在大数据开发中,算法的思想对于解决各种问题都非常重要,其中分治算法是一种非常常见的算法思想,特别适合处理一些复杂的问题。
104 0
|
算法 大数据 调度
大数据开发基础的数据结构和算法的算法思想的贪心
大数据开发中,算法的思想对于解决各种问题都非常重要。其中,贪心算法是一种非常常见的算法思想,特别适合处理一些最优化问题。
89 0
|
机器学习/深度学习 算法 大数据
大数据开发基础的数据结构和算法的算法思想的枚举
在大数据开发中,枚举算法是一种基础算法思想。它通常用于解决简单问题的求解和实现,通过枚举所有可能的情况并比较其结果,来找到最终的答案。
107 0