欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > 【优选算法 模拟】模拟算法入门详解 : 模拟算法小专题

【优选算法 模拟】模拟算法入门详解 : 模拟算法小专题

2025/6/17 19:59:34 来源:https://blog.csdn.net/2402_84916296/article/details/144389184  浏览:    关键词:【优选算法 模拟】模拟算法入门详解 : 模拟算法小专题

         

 



替换所有的问号


    题目描述    



    算法原理    


     解法:    


从前往后扫描数组,当扫描到 '?' 修改字符即可;

 修改的字符不要和前后两个字符相等即可;


     处理细节问题     


如果 '?' 在字符串最前面或者最后面,这个时候需要单独处理;


    编写代码    



 对于这个判断条件,我们需要解析一下: 


我们来解析一下这个判断条件,整体的架构:


 





提莫攻击


    题目描述    



    算法原理    


对于提莫相邻的两次攻击,设攻击的时间点分别是  timeSeries[ i +1 ] , timeSeries[ i ] 

 我们仅需要看 timeSeries[ i +1 ] - timeSeries[ i ] 的差值 x 与 duration 之间的大小关系:

  • 1. x >= duration,返回 ret += duration * 2

  • 2. x < duration,返回 ret += ( x + duration)

     处理细节问题     


   我们一定不要忘记最后一次攻击造成的中毒时间,最终结果要累加上一次中毒时间 duration ;


    编写代码    


  


Z 字形变换


     题目描述     



    算法原理    



     解法一:模拟过程    


想要正确模拟过程,我们需要创建一个矩阵,行数为 n,列数是可以根据周期性计算出来的, 但是计算量非常大,所以我们直接让列数等于字符串长度即可;

我们完整的模拟过程如上,每遍历到一个字符,就按照规则放入矩形对应位置;但是这样的模拟过程,时间复杂度和空间复杂度都是非常高的;


     解法二:通过模拟过程找规律     


接下来,我们在刚刚模拟过程的基础上,通过总结规律,来作优化: 

此时的 numRows = 4,我们设第一列相邻的两个元素(0,6,12)之间的差值为公差 d,此时 d=6;


虽然我们输入矩阵的字符顺序为N,但是我们输出的顺序是从左往右,从上到下进行的;

所以我们不需要把整个矩阵先按顺序填入,再按顺序填出,而是直接输出原字符串(0,0+d,0+2d....)下标的字符即可,此时我们就输出了第一列的字符;


那么这个公差 d 是多少呢?我们通过公差第一行的 0 和 6,发现它们之间的差值 d,就是 6 之前,0之后的总格子数:


如何计算这些格子数,进而确定 d 呢?


我们通过观察可以发现,d=numRows*2-2,那么最后一行也是同理;


而对于第二行,则是从第一列元素开始,+d 的元素所在列的前一列,多了一个元素:

并且 1+5 = d,第三行 2+4 = d,所以中间的行是两个两个元素进行递进;


设中间某一行第一列元素为 k:


     处理细节问题     


当 numRows = 1,要特别处理一下,否则会因为 d = 0 而写出死循环;


    编写代码    



题一定不要听一遍课就行了,要自己也过几遍,直到一次过,煮啵隔了一天再换一种方法刷错一堆,呜呜呜~~~ 


外观数列


    题目解析    



    算法原理    


      解法: 模拟  + 双指针    



要想通过 cAS( i-1 ) 求出 cAS(i),其实非常简单,我们只需要找 cAS(i) 相同部分,直到遍历完相同部分,就能得到 cAS ( i ) 对应的两个元素 [ 元素出现次数,元素 ]


     模拟步骤     


我们定义一个双指针,指向起始位置: 

 让 right 移动出相同部分(找边界):

cAS[right]==cAS[left] ?right++ : left = right;

当然,再移动 left 之前,要先记录相同部分的元素出现次数 [ right - left , cAS[left] ]


    编写代码    


 


    细节问题    


在绝对的力量面前,技巧输的一败涂地 (bushi)


数青蛙


     题目描述    



    算法原理    


从前往后遍历: 


如果遍历到 r 字符,就需要看看 r 前面有没有青蛙叫出 c 字符:


同理,我们如果在继续扫描的过程中,扫描到 o 字符,就可以看看前面有没有 r  字符 ,并且这个 o 字符没有被其他的 o 字符挡住:


所以,我们在遍历的过程中,要时刻统计前面遍历过的字符出现的次数情况,所以我们需要借助一个哈希表,<字符种类,出现次数>;


     解法:模拟  + 哈希表   


我们来模拟一下遍历字符串时,哈希表的键值变化过程:


我们在遍历下一个字符时,发现是 r ,此时我们要减去一个 c ,才可以让 r 的 val++ 

如果有不合法的字符串,会让哈希表中某一个键值对的 val = -1,此时直接返回 -1 即可;

并且,要想知道到底有多少只青蛙,看 key = k 对应的 val 是不够的,因为可能是一只青蛙叫了很多声;


继续往后遍历:


遍历到 'o' 时,我们需要看看前面是否有 'r' :


 其实本质就是如果遍历到 'o' ,就把前面 'r' 对应的 val 搬一个 1到 'o' 的 val:


具体操作就是前一个 val -1 ,后一个 val +1,但是我们模拟过程的时候,如果前面的key 对应 val =1,是可以直接把1 移动到下一个key 的 val 上的;


 此时我们向后模拟,发现 c r o a k 完整出现一次,默认就是前面两只青蛙其中一只叫的 ;


既然要前面两只青蛙中的其中一只叫,那我们的模拟过程就是,把后面 key = k 对应的 val ,把这个 val 中的一个 1 搬回到 'c' 对应的 val(这一步很关键):


所以我们的具体操作,就是让 hash.getOrDefault (k,0)--,hash.getOrDefault (c,0)++,这样就可以保证求出来的青蛙数量是最少的:

最终 k 的值就能代表青蛙的个数;

这是完美模拟的情况,并且我们的这个实例最终结果也是需要两只青蛙,并且 k 前面的所有字符,对应的 val 都为 0 ;如果前面有键值对的 val != 0 ,就能说明这个字符串不合法; 


当然,也有一些不需要遍历完所有字符串,就可以直接判定字符串不合法的情况:


 当遍历到第二个 r 时,我们我们可以观察还没有更新的哈希表的情况:

此时我们发现在遍历第二个 r 时,c.val = 0,说明这个 r 是多余的字符,可以直接返回 -1;


    总结:  


    编写代码    


对于这题,已经给出蛙声是怎么叫的了,我们可以用大量的判断语句来解决这道题;

但是如果题目不给蛙声的字符串是什么样的,而只是把蛙声作为一个参数传进来,那么我们就不能再使用判断语句来解决这道题,而应该使用通用的解法:


     处理细节问题      


    (1)  两次 return -1 筛查的字符串类型不同     



     (2)  使用 哈希表+数组 的组合简化映射关系    


在这个题,煮啵又学到了新的骚操作: 

对于使用数组来模拟哈希表,在一些特定需求导致数组的下标紊乱的情况:

如本题,如果我们直接来创建两个数组来模拟哈希表,一个数组 nums1 放蛙声中的字符,另一个数组 nums2 放的是蛙声字符的次数,每一个字符在nums2 都会有对应下标,那么它们之间的映射关系是非常混乱而复杂;


此时我们可以定义一个哈希表,来绑定字符对应在数组中的下标 :

此时映射关系简单而易于理解,使用时就不会出错; 


          

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词