模拟算法 (算法详解+例题)

news2024/11/30 8:49:12

目录

  • 一、什么是模拟
  • 二、模拟算法的特点和技巧
  • 三、模拟OJ题
    • 3.1、替换所有的问号
    • 3.2、提莫攻击
    • 3.3、N字形变换
    • 3.4、外观数列
    • 3.5、数青蛙

一、什么是模拟

模拟是对真实事物或者过程的虚拟。在编程时为了实现某个功能,可以用语言来模拟那个功能,模拟成功也就相应地表示编程成功。

二、模拟算法的特点和技巧

特点:

  • 代码量大

  • 操作多

  • 思路复杂

  • 较为复杂的模拟题出错后难定位错误

技巧:

  • 在动手写代码之前,在草纸上尽可能地写好要实现的流程.

  • 在代码中,尽量把每个部分模块化,写成函数、结构体或类

  • 对于一些可能重复用到的概念,可以统一转化,方便处理:如,某题给你"YY-MM-DD 时:分" 把它抽取到一个函数,处理成秒,会减少概念混淆

  • 调试时分块调试。模块化的好处就是可以方便的单独调某一部分

  • 写代码的时候一定要思路清晰,不要想到什么写什么,要按照落在纸上的步骤写

三、模拟OJ题

3.1、替换所有的问号

1576. 替换所有的问号

在这里插入图片描述

算法思路

纯模拟。从前往后遍历整个字符串,找到问号之后,就⽤ a ~ z 的每⼀个字符去尝试替换即可。

算法代码

class Solution {
public:
    string modifyString(string s) {
        for(int i = 0; i<s.size(); i++)//遍历每一个字符
        {
            if(s[i] == '?')
            {
                for(char ch = 'a'; ch <= 'z'; ch++)//a ~ z都试试
                {
                    if(i == 0 && ch != s[i+1]) //头位置是'?',不能和后一个相等
                        s[i] = ch;
                    else if(i == s.size()-1 && ch != s[i-1])//尾位置是'?' ,不能和前一个相等
                        s[i] = ch;
                    else if(ch != s[i+1] && ch != s[i-1]) //中间情况, 不能和两边相等
                        s[i] = ch;
                }
            }
        }
        return s;
    }
};

3.2、提莫攻击

495. 提莫攻击

在这里插入图片描述

算法思路

模拟 + 分情况讨论。

计算相邻两个时间点的差值

  • i. 如果差值 ⼤于等于 中毒时间,说明上次中毒可以持续 duration 秒;

  • ii. 如果差值 ⼩于 中毒时间,那么上次的中毒只能持续两者的差值。

算法代码

class Solution {
public:
    int findPoisonedDuration(vector<int>& timeSeries, int duration) {
        int ans = 0;
        for(int i = 0; i<timeSeries.size(); i++) //遍历每一个中毒time,计算差值与duration比较
        {
            // 如果差值 ⼤于等于 中毒时间,说明上次中毒可以持续 duration 秒,
            if(i + 1 < timeSeries.size() && timeSeries[i+1] - timeSeries[i] >= duration)
                ans+=duration;
            //如果差值 ⼩于 中毒时间,那么上次的中毒只能持续两者的差值
            //因为中毒中不完,到下个时间就会重置,这轮中毒时间就是两者的差值
            if(i + 1 < timeSeries.size() && timeSeries[i+1] - timeSeries[i] < duration)
                ans+=timeSeries[i+1] - timeSeries[i];
        }
        ans+=duration; //最后还需要加一个duration,因为最后一次攻击的中毒时间可以全部中毒完
        return ans;
    }
};

3.3、N字形变换

Z 字形变换

在这里插入图片描述

  • 对于前面的 3 行的 示例1 , 它的字符数分布是这样的
    在这里插入图片描述
  • 对于前面的 4 行的 示例2 , 它的字符数分布是这样的:
    在这里插入图片描述
  • 那么对于 n 行的字符数分布是这样的:
    在这里插入图片描述
    如上图所示,我们可以发现:

公差为 2n - 2

  1. 当前行 curRow 为 0 时 ,下标变化是 0 -> 0+d -> 0+2d -> … ->0+kd;

  2. 当前行 curRow 为 n-1 时 ,下标变化是n-1 -> n-1+d -> n-1+2d -> … ->n-1+kd;

  3. 当前行 curRow 为 k 时 ,下标变化是( k , d-k ) -> ( k+d , d-k+d ) -> ( k+ 2d, d-k+2d ) -> …

算法代码

class Solution {
public:
    string convert(string s, int numRows) {
        if(numRows == 1) return s;
        int d = 2 * numRows - 2; //公差d = 2n-1
        string ret;
        for(int i = 0; i<s.size(); i+=d) //当前行 curRow 为 0 
            ret += s[i];
        for(int k = 1; k<numRows-1; k++) //当前行 curRow 为 k
        {
            //( k , d-k ) -> ( k+d , d-k+d ) -> ( k+ 2d, d-k+2d ) -> .....
            for(int i = k ,j = d - k; i < s.size() || j < s.size(); i+=d,j+=d)
            {
                if(i < s.size()) ret+=s[i];
                if(j < s.size()) ret+=s[j];
            }
        }

        for(int i = numRows-1; i<s.size(); i+=d) //当前行 curRow 为 n-1
            ret+=s[i];

        return ret;
    }
};

3.4、外观数列

38. 外观数列

在这里插入图片描述

算法思路

所谓「外观数列」,其实只是依次统计字符串中连续且相同的字符的个数。依照题意,依次模拟即可。

算法代码

class Solution {
public:
    string countAndSay(int n) {
        string ret = "1" ; //countAndSay(1) = "1"
        for(int i = 1; i<n; i++)//循环n-1次
        {
            string tmp; //用tmp暂存,进行替换
            int left = 0 ,right = 0;
            while(right < ret.size()) //right出ret,双指针结束
            {
                while(ret[right] == ret[left]) right++; //到不相等的那个数结束
                //然后加上有几个这个数 right - left,再加上这个数本身
                tmp+= to_string(right-left);
                tmp+= ret[left];

                left = right;//更新left位置,进行下一次双指针
            }
            ret = tmp; //更新ret,进行下一次循环
        }
        return ret;
    }
};

3.5、数青蛙

1419. 数青蛙

在这里插入图片描述

算法思路

将青蛙分成 5 种:

  • 刚才发出了 c 的声音。
  • 刚才发出了 r 的声音。
  • 刚才发出了 o 的声音。
  • 刚才发出了 a 的声音。
  • 刚才发出了 k 的声音。

遍历 croakOfFrogs,例如当前遍历到 r,那么就看看有没有青蛙刚才发出了 c 的声音,如果有,那么让它接着发出 r 的声音。换句话说,我们需要消耗一个 c,产生一个 r。

所以我们使用一个哈希表(数组)hash 来维护这 5 种青蛙的个数,并分类讨论:

  • 遍历到 c 时,看看有没有青蛙刚才发出了 k 的声音,如果有,那么复用这只青蛙,让它接着发出 c 的声音,即 hash[‘k’]-- 和 hash[‘c’]++;如果没有这种青蛙,那么新产生一只青蛙发出 c 的声音,即 hash[‘c’]++。

  • 遍历到 r , o,a,k ,找到该字母在 croak 的上一个字母的 hash 值,如果 hash 值大于 0,那么将其减一,同时当前字母的 hash 值加一;如果上一个字母的 hash 值等于 0,那么就返回 −1。

  • 遍历结束后,所有青蛙必须在最后发出 k 的声音。如果有青蛙在最后发出的声音不是 k(也就是 cnt 值大于 0),那么返回 −1,否则返回 hash[k]。

算法代码

class Solution {
public:
    int minNumberOfFrogs(string croakOfFrogs) {
        string t = "croak";
        vector<int> hash(t.size()); //[0,4]对应crock ,各个个数

        unordered_map<char,int> index; //[x,x这个字符对应的下标]
        for(int i = 0; i<t.size(); i++)
            index[t[i]] = i; //存[x,x这个字符对应的下标]
        
        for(auto ch : croakOfFrogs) //遍历
        {
            if(ch == 'c')
            {
                //看看有没有青蛙刚才发出了 k 的声音,如果有,那么复用这只青蛙 ,k--,c++;
                if(hash[4] != 0) hash[4]--; 
                hash[0]++;
            }
            else
            {
                int i = index[ch];//找出roak对应的下标
                if(hash[i-1] == 0) return -1; //找到该字母在 croak 的上一个字母的值,非0直接错
                hash[i-1]--; //不是0就--
                hash[i]++; //这个字母对应的数++,为了判断下一个字母
            }
        }

        //所有青蛙必须在最后发出 k 的声音。如果有青蛙在最后发出的声音不是 k,那么返回 −1。
        for(int i = 0; i<t.size()-1; i++) 
        {
            if(hash[i] != 0)
                return -1;
        }

        return hash[t.size()-1];//返回
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2226951.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

php后端学习,Java转php

遇到前后端跨域 php解决跨域问题可以加上下面的代码&#xff1a; header(“Access-Control-Allow-Origin:*”); 并且查看自己的数据库信息是否连接成功。 从Java转php 个人感受php跟偏向前端&#xff0c; 写后端逻辑时没有像java又springboot工具方便。 但是和前端联调很方便…

一个简单的例子,说明Matrix类的妙用

在Android、前端或者别的平台的软件开发中&#xff0c;有时会遇到类似如下需求&#xff1a; 将某个图片显示到指定的区域&#xff1b;要求不改变图片本身的宽高比&#xff0c;进行缩放&#xff1b;要求最大限度的居中填充到显示区域。 以下示意图可以简单描绘该需求 以Androi…

Zookeeper分布式锁实现

文章目录 1、zk分布式锁的实现原理1_获取锁过程2_释放锁 2、代码实现1_创建客户端对象2_使用和测试案例 1、zk分布式锁的实现原理 Z o o k e e p e r Zookeeper Zookeeper 就是使用临时顺序节点特性实现分布式锁的&#xff0c;官网。 获取锁过程 &#xff08;创建临时节点&…

基于websocket简易封装一个全局消息通知组件

期望是&#xff0c;在用户登录后台后。新的任务到来时能够及时通知到并且去处理。 效果图 前端 <template><div></div> </template><script> import { updateRead } from "/api/system/approval-notification"; export default {dat…

Android Gradle

#1024程序员节&#xff5c;征文# Gradle 是一款强大的自动化构建工具&#xff0c;广泛应用于 Android 应用开发。它通过灵活的配置和丰富的插件系统&#xff0c;为项目构建提供了极大的便利。本文只是简单的介绍 Gradle 在 Android 开发中的使用&#xff0c;包括其核心概念、构…

【mysql进阶】5-事务和锁

mysql 事务基础 1 什么是事务 事务是把⼀组SQL语句打包成为⼀个整体&#xff0c;在这组SQL的执⾏过程中&#xff0c;要么全部成功&#xff0c;要么全部失败&#xff0c;这组SQL语句可以是⼀条也可以是多条。再来看⼀下转账的例⼦&#xff0c;如图&#xff1a; 在这个例⼦中&a…

中酱集团:黑松露酱油,天然配方定义健康生活

在如今的大健康时代&#xff0c;人们对于美食的要求越来越高。不仅美味&#xff0c;更要健康。在健康美食的生态链中&#xff0c;有一个名字正逐渐成为品质与美味的代名词——中酱集团。而当中酱集团与黑松露酱油相遇&#xff0c;一场味觉的革命就此拉开帷幕。 中酱集团&#x…

生成式UI 动态化SDK的研发--开篇

这里写目录标题 1. 背景2.名词解释2.1 DSL2.2 AI大模型2.3 生成式UI 3. 前言4.未来展望 1. 背景 随着AI大模型技术的兴起&#xff0c;UI界面的开发和交互必定会发生巨大的改变。在大模型技术出现之前&#xff0c;软件的界面是通过UI设计师和交互设计师先定义好软件的UI界面&am…

如何在手机上解压7z格式文件?最佳软件推荐与使用指南

在当今数字化时代&#xff0c;手机已经成为我们生活中不可或缺的工具。随着文件数量的不断增加&#xff0c;文件管理变得尤为重要。 而在手机上解压 7z 文件具有重大的意义。 首先&#xff0c;7z 文件格式以其高压缩率而闻名。这意味着可以在有限的存储空间内存储更多的文件。…

Pseudo Multi-Camera Editing 数据集:通过常规视频生成的伪标记多摄像机推荐数据集,显著提升模型在未知领域的准确性。

2024-10-19&#xff0c;由伊利诺伊大学厄巴纳-香槟分校和香港城市大学的研究团队提出了一种创新方法&#xff0c;通过将常规视频转换成伪标记的多摄像机视角推荐数据集&#xff0c;有效解决了在未知领域中模型泛化能力差的问题。数据集的创建&#xff0c;为电影、电视和其他媒体…

每日OJ题_牛客_DP23不相邻取数_打家劫舍dp_C++_Java

目录 牛客_DP23不相邻取数_打家劫舍dp 题目解析 C代码 Java代码 牛客_DP23不相邻取数_打家劫舍dp 不相邻取数_牛客题霸_牛客网 (nowcoder.com) 描述&#xff1a; 小红拿到了一个数组。她想取一些不相邻的数&#xff0c;使得取出来的数之和尽可能大。你能帮帮她吗&#x…

飞腾X100 NPU Benchmark使用说明

【写在前面】 飞腾开发者平台是基于飞腾自身强大的技术基础和开放能力&#xff0c;聚合行业内优秀资源而打造的。该平台覆盖了操作系统、算法、数据库、安全、平台工具、虚拟化、存储、网络、固件等多个前沿技术领域&#xff0c;包含了应用使能套件、软件仓库、软件支持、软件适…

Kafka消费者故障,出现活锁问题如何解决?

大家好&#xff0c;我是锋哥。今天分享关于【Kafka消费者故障&#xff0c;出现活锁问题如何解决&#xff1f;】面试题&#xff1f;希望对大家有帮助&#xff1b; Kafka消费者故障&#xff0c;出现活锁问题如何解决&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资…

Objective-C 音频爬虫:实时接收数据的 didReceiveData_ 方法

在互联网技术领域&#xff0c;数据的获取和处理是至关重要的。尤其是对于音频内容的获取&#xff0c;实时性和效率是衡量一个爬虫性能的重要指标。本文将深入探讨在Objective-C中实现音频爬虫时&#xff0c;如何高效地使用didReceiveData:方法来实时接收数据&#xff0c;并通过…

Spring Boot 3项目创建与示例(Web+JPA)

以下是一个Spring Boot 3.3.4整合JPA的示例,它展示了如何在Spring Boot应用程序中使用JPA进行数据持久化。 版本与环境 Spring Boot 3.3.4数据库: MySQL 8.0.40, MySQL的安装使用可以参考: MySQL 8 下载与安装攻略JDK 17Maven 3.6项目创建 可以使用Spring Initializr 初始…

深度学习:SGD的缺点

首先看下述函数&#xff1a; 最小值为x0&#xff0c;y0处 先了解下它的梯度特征。了理解其梯度特征&#xff0c;我们需要计算其梯度向量。 梯度向量 ∇f 是函数 f 在每个变量方向上的偏导数组成的向量。具体来说&#xff1a; ∇f(∂f/∂x,∂f∂/y) 首先&#xff0c;我们计算 f …

时间序列预测(十五)——有关Python项目框架的实例分析

#1024程序员节&#xff5c;征文# 在之前的学习中&#xff0c;已经对时间序列预测的相关内容有了大致的了解。为了进一步加深理解&#xff0c;并能够将所学知识应用于实际中&#xff0c;我决定找一个完整的Python框架来进行深入学习。经过寻找&#xff0c;我终于找到了一篇非常具…

电脑技巧:如何进行磁盘测速?

磁盘测速是指通过专业工具或系统自带功能&#xff0c;测量硬盘的读写速度。这一过程能够帮助用户了解磁盘的性能瓶颈&#xff0c;并为硬件升级或系统优化提供数据依据。特别是在处理大量数据或运行高负载应用时&#xff0c;磁盘速度是决定系统性能的关键因素。 影响磁盘速度的因…

Web 核心指标优化之 INP 篇

这篇文章是我在公司做 INP 优化经验分享的演讲稿。 大家好&#xff0c;今天我要做的分享是关于 INP 的一些优化经验。 概念 首先&#xff0c;什么叫 INP 呢。 INP 的全称叫 Interaction to Next Pain &#xff0c;翻译过来就是从交互到下一次绘制的延迟。这是 Google 提出来的…

C#与C++互操作时的数据类型对应

C#和C在互操作时&#xff0c;会涉及到数据类型对应的问题&#xff0c;如果数据类型用得不对&#xff0c;就会得不到想要的结果&#xff0c;严重的情况下&#xff0c;可能还会导致程序崩溃。这里做一下相关知识点的总结。 说明&#xff1a; 1. 表格第一列是Visual C中的数据类型…