模拟算法专题——算法介绍&算法讲解&力扣实战应用

目录

1、模拟算法介绍

2、算法应用【leetcode】

[2.1 替换所有的问号](#2.1 替换所有的问号)

[2.1.1 算法思想](#2.1.1 算法思想)

[2.1.2 算法代码](#2.1.2 算法代码)

[2.2 提莫攻击](#2.2 提莫攻击)

[2.2.1 算法思想](#2.2.1 算法思想)

[2.2.2 算法代码](#2.2.2 算法代码)

[2.3 Z字形变换](#2.3 Z字形变换)

[2.3.1 算法思想](#2.3.1 算法思想)

[2.3.2 算法代码](#2.3.2 算法代码)

[2.4 外观数列](#2.4 外观数列)

[2.4.1 算法思想](#2.4.1 算法思想)

[2.4.2 算法代码](#2.4.2 算法代码)

[2.5 数青蛙](#2.5 数青蛙)

[2.5.1 算法思想](#2.5.1 算法思想)

[2.5.2 算法代码](#2.5.2 算法代码)


1、模拟算法介绍

模拟算法其实就是------比葫芦画瓢。

模拟算法的思想很简单,解题思路一般在题目上就给了,我们只需用代码将题目的要求模拟出来就可以了,所以模拟算法对代码能力要求较强,模拟算法并没有固定的模版,我们只需将题目要求用代码模拟出来即可。

模拟算法是一种计算机算法,用于模拟或仿真现实世界中的某个过程、系统或现象。它通过运行一系列的步骤或规则来模拟目标对象的行为,并生成与真实情况相似的结果。


2、算法应用【leetcode】

2.1 替换所有的问号

. - 力扣(LeetCode)

2.1.1 算法思想

本题为简单模拟题,只需将字符'?'替换为前后不连续的字符即可。

  1. 从'a'~'z'中寻找字符,与i-1位置和i+1位置比较,判断是否出现连续的字符(字符重复)
  2. 注意:0下标处和n-1下标处要额外处理,避免越界访问

2.1.2 算法代码

java 复制代码
class Solution {
    public String modifyString(String s) {
        char[] ss = s.toCharArray();
        int len = ss.length;
        for (int i = 0; i < len; i++) {
            //替换字符
            if (ss[i] == '?') {
                for (char j = 'a'; j < 'z'; j++) {
                    if ((i == 0 || ss[i - 1] != j) && (i == len - 1 || ss[i + 1] != j) ) {
                        ss[i] = j;
                        break;
                    }
                }
            }
        }
        return String.valueOf(ss);
    }
}

2.2 提莫攻击

. - 力扣(LeetCode)

2.2.1 算法思想

计算出每两次发动攻击之间的时间差x,判断是否 >= 持续时间d秒:

  1. 若x >= d,则说明时间充裕,d秒时间内会一直中毒,中毒时间ret += d
  2. 若x < d,则说明时间不够,中毒时间会重复,中毒时间ret += 时间差x
  3. 最后一次攻击,时间必然充裕,必然中毒d秒,中毒时间ret += d

2.2.2 算法代码

java 复制代码
class Solution {
    public int findPoisonedDuration(int[] timeSeries, int duration) {
        int ret = 0;
        for(int i = 0; i < timeSeries.length - 1; i++) {
            int x = timeSeries[i + 1] - timeSeries[i];
            if(x < duration) ret += x;
            else ret += duration;
        }
        //最后一次攻击,必然中毒d秒
        ret += duration;
        return ret;
    }
}

2.3 Z字形变换

. - 力扣(LeetCode)

2.3.1 算法思想

在模拟算法中,若想要寻得时空效率高的算法,只能通过找规律来做优化。

我们将字符的下标放在矩阵中,求得公差d = 2*n - 2,且发现字符在矩阵中和下标有以下规律:

  • ①:当k==0时(第一行),k += d,拿到下一个要打印的字符的下标,直到k >= 字符串.len
  • ②:当k == n-1时(最后一行),k += d,拿到下一个要打印的字符的下标,直到k >= 字符串.len
  • ③:当k为中间行时,k和d-k为一组,(k,d-k)-->(k+d,d-k+d)-->...,直到k >= 字符串.len

2.3.2 算法代码

java 复制代码
class Solution {
    public String convert(String s, int numRows) {
        if (numRows == 1) return s;
        char[] ss = s.toCharArray();
        int len = ss.length;
        StringBuilder stringBuilder = new StringBuilder();
        int d = 2 * numRows - 2;//公差
        for (int i = 0; i < numRows; i++) {
            int k = i;
            if (k == 0) {
                while (k < len) {
                    stringBuilder.append(ss[k]);
                    k += d;
                }
            } else if (k == numRows - 1) {
                while (k < len) {
                    stringBuilder.append(ss[k]);
                    k += d;
                }
            } else {
                int k2 = d - k;
                while (k < len || k2 < len) {
                    if (k < len) stringBuilder.append(ss[k]);
                    if (k2 < len) stringBuilder.append(ss[k2]);
                    k += d;
                    k2 += d;
                }
            }
        }
        return stringBuilder.toString();
    }
}

2.4 外观数列

. - 力扣(LeetCode)

2.4.1 算法思想

外观数列其实就是从2开始(1的外观数列就是1)用口头的语言将前一个数的表述出来,比如:

1 --> 1

2 --> 11(1个1)

3 --> 21(2个1)

4 --> 1211(1个2、1个1)

5 --> 111221(1个1、1个2、2个1)

....

使用双指针法求解:

  1. 从数字以1开始
  2. 定义left和right指针,起始位置均为0下标
  3. 当ret[right] != ret[left]时,记录长度(相同元素的个数),且更新left = right,继续向后遍历,直至遍历完成当前字符串
  4. 更新ret字符串,更新数字,直至数字n,返回数字n的外观数列

2.4.2 算法代码

java 复制代码
class Solution {
    public String countAndSay(int n) {
        String ret = "1";
        for(int i = 0; i < n - 1; i++) {
            StringBuilder sb = new StringBuilder();
            int left = 0, right = 0;
            int len = ret.length();
            while(right < len) {
                while(right < len && ret.charAt(right) == ret.charAt(left)) right++;
            sb.append(right - left);
            sb.append(ret.charAt(left));
            left = right;
            }
            ret = sb.toString();
        }
        return ret;
    }
}

2.5 数青蛙

. - 力扣(LeetCode)

2.5.1 算法思想

  • 若下标为1~4的字符(r、o、a、k),则去哈希表中查看其前驱字符,若存在则:前驱个数--,当前字符个数++;若不存在:返回-1
  • 若下标为0的字符(c),说明蛙叫刚刚开始,查看最后一个字符的个数,若存在则:最后一个字符个数--,当前字符个数++; 若不存在则:当前字符++
  • 注意:当遍历完成后,除最后一个字符外,哈希表中仍有其他字符存在个数,则不成立,返回-1

2.5.2 算法代码

java 复制代码
class Solution {
    public int minNumberOfFrogs(String croakOfFrogs) {
        char[] s = croakOfFrogs.toCharArray();
        int n = "croak".length();
        int[] hash = new int[n];
        // 绑定字符和其下标
        Map<Character, Integer> map = new HashMap<>();
        for (int i = 0; i < n; i++)
            map.put("croak".charAt(i), i);
        for (char ch : s) {
            int index = map.get(ch);
            if (index == 0) {
                if (hash[n - 1] != 0)
                    hash[n - 1]--;
                hash[0]++;
            } else {
                if (hash[index - 1]-- == 0)
                    return -1;
                hash[index]++;
            }
        }
        //除最后一个字符外,哈希表中仍有其他字符存在个数
        for (int i = 0; i < n - 1; i++) {
            if (hash[i] != 0)
                return -1;
        }
        return hash[n - 1];
    }
}

END

相关推荐
骆晨学长2 分钟前
基于springboot的智慧社区微信小程序
java·数据库·spring boot·后端·微信小程序·小程序
是小Y啦3 分钟前
leetcode 106.从中序与后续遍历序列构造二叉树
数据结构·算法·leetcode
LyaJpunov4 分钟前
C++中move和forword的区别
开发语言·c++
AskHarries7 分钟前
利用反射实现动态代理
java·后端·reflect
@月落8 分钟前
alibaba获得店铺的所有商品 API接口
java·大数据·数据库·人工智能·学习
程序猿练习生9 分钟前
C++速通LeetCode中等第9题-合并区间
开发语言·c++·leetcode
liuyang-neu14 分钟前
力扣 42.接雨水
java·算法·leetcode
z千鑫17 分钟前
【人工智能】如何利用AI轻松将java,c++等代码转换为Python语言?程序员必读
java·c++·人工智能·gpt·agent·ai编程·ai工具
一名路过的小码农19 分钟前
C/C++动态库函数导出 windows
c语言·开发语言·c++
y_dd21 分钟前
【machine learning-12-多元线性回归】
算法·机器学习·线性回归