[Algorithms Series] Simulation Algorithms

insert image description here

foreword

The algorithm we learned earlier, after reading the topic, you may know which algorithm to use. This algorithm is similar to a template, but there is a type of algorithm that cannot be called a specific template. This is called a simulation algorithm. . The simulation algorithm refers to: according to the information provided by the question, the final result can be obtained by simulating the solving process of the question. The simulation algorithm is relatively simple. As long as the question can be simulated according to the meaning of the question, the problem can generally be solved.

A simulation algorithm is a computer algorithm used to simulate or emulate a process, system or phenomenon in the real world. It simulates the behavior of the target object by running a series of steps or rules, and produces results similar to the real situation.

1. Replace all question marks

https://leetcode.cn/problems/replace-all-s-to-avoid-consecutive-repeating-characters/

1.1 Topic Requirements

Given a string s that only contains lowercase English letters and '?' characters, please convert all the '?' into several lowercase letters so that the final string does not contain any consecutive repeated characters.

NOTE: You cannot modify non-'?' characters.

The title test case guarantees that there are no consecutive repeated characters except for the '?' character.

Returns the final string after all conversions (possibly without conversions). If there are multiple solutions, return any of them. It can be shown that under the given constraints, the answer always exists.

Example 1:

输入:s = "?zs"
输出:"azs"
解释:该示例共有 25 种解决方案,从 "azs" 到 "yzs" 都是符合题目要求的。
只有 "z" 是无效的修改,因为字符串 "zzs" 中有连续重复的两个 'z' 。

Example 2:

输入:s = "ubv?w"
输出:"ubvaw"
解释:该示例共有 24 种解决方案,只有替换成 "v" 和 "w" 不符合题目要求。
因为 "ubvvw" 和 "ubvww" 都包含连续重复的字符。

hint:

  • 1 <= s.length <= 100

  • s contains only lowercase English letters and '?' characters

class Solution {
    
    
    public String modifyString(String s) {
    
    

    }
}

1.2 Ideas for doing the questions

The idea of ​​this question is very simple, we only need to traverse the string once, and then change the characters whose characters are ? to other 26 lowercase English letters except ?, and ensure that adjacent characters cannot be repeated. Through the simulation algorithm, we can directly solve this problem. What needs to be paid more attention to is the out-of-bounds problem of the subscript. When the subscript is the first character of the string, it only has one adjacent character on the right; when the character is the middle When there are n characters, it needs to consider two adjacent characters on the left and right; and when the character is the last character, there is only one adjacent character on the left.

1.3 Java code implementation

class Solution {
    
    
    public String modifyString(String ss) {
    
    
    //因为Java代码操作字符串较复杂,所以我们可以将字符串转换为数组来操作
        char[] s = ss.toCharArray();
        int n = s.length;
        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 String.valueOf(s);
    }
}

insert image description here

2. Teemo Attack

https://leetcode.cn/problems/teemo-attacking/

2.1 Topic Requirements

In the world of "League of Legends", there is a hero named "Teemo". His attack can make the enemy hero Ashe (Editor's Note: Ice Archer) into a poisoned state.

When Teemo attacks Ashe, Ashe is poisoned for exactly duration seconds.

Formally speaking, Teemo's attack at t means that Ashe is in a poisoned state during the time interval [t, t + duration - 1] (including t and t + duration - 1). If Teemo attacks again before the poison effect ends, the poison state timer will reset, and the poison effect will end in duration seconds after the new attack.

You are given a non-decreasing integer array timeSeries, where timeSeries[i] indicates that Teemo will attack Ashe at timeSeries[i] seconds, and an integer duration indicating the duration of the poisoning.

Returns the total number of seconds Ashe has been poisoned.

Example 1:

输入:timeSeries = [1,4], duration = 2
输出:4
解释:提莫攻击对艾希的影响如下:
- 第 1 秒,提莫攻击艾希并使其立即中毒。中毒状态会维持 2 秒,即第 1 秒和第 2 秒。
- 第 4 秒,提莫再次攻击艾希,艾希中毒状态又持续 2 秒,即第 4 秒和第 5 秒。
艾希在第 1、2、4、5 秒处于中毒状态,所以总中毒秒数是 4 。

Example 2:

输入:timeSeries = [1,2], duration = 2
输出:3
解释:提莫攻击对艾希的影响如下:
- 第 1 秒,提莫攻击艾希并使其立即中毒。中毒状态会维持 2 秒,即第 1 秒和第 2 秒。
- 第 2 秒,提莫再次攻击艾希,并重置中毒计时器,艾希中毒状态需要持续 2 秒,即第 2 秒和第 3 秒。
艾希在第 1、2、3 秒处于中毒状态,所以总中毒秒数是 3 。

hint:

  • 1 <= timeSeries.length <= 104
  • 0 <= timeSeries[i], duration <= 107
  • timeSeries in non-decreasing order
class Solution {
    
    
    public int findPoisonedDuration(int[] timeSeries, int duration) {
    
    

    }
}

2.2 Ideas for doing the questions

This question is to calculate the time of being damaged according to the time and times of Teemo's attacks. You only need to know the number of times of being attacked according to the timeSeries array given in the question, and then combine the given duration to calculate the total time.
insert image description here

However, we need to consider a special case, when the interval between two attacks is less than the duration of the damage, then the duration of the damage will be reset.
insert image description here

According to the above two situations, we can divide Teemo's attack interval into two situations: the attack interval is greater than the damage duration; the attack interval is less than or equal to the damage duration. When the attack interval is greater than the damage duration, we only need to add the duration. When the interval is less than or equal to the damage duration, add the difference between the two attack intervals instead of the duration.

2.3 Java code implementation

class Solution {
    
    
    public int findPoisonedDuration(int[] timeSeries, int duration) {
    
    
        int ret = 0;
        for(int i = 0; i < timeSeries.length - 1; i++) {
    
    
            if(timeSeries[i + 1] - timeSeries[i] > duration) ret += duration;
            else ret += timeSeries[i + 1] - timeSeries[i];
        }

        return ret += duration;
    }
}

insert image description here

3. N-shape transformation

https://leetcode.cn/problems/zigzag-conversion/

3.1 Topic Requirements

Arrange a given string s in zigzag from top to bottom and from left to right according to the given number of rows numRows.

For example, when the input string is "PAYPALISHIRING" and the number of lines is 3, the arrangement is as follows:

After PAHN
APLSIIG
YIR
, your output needs to be read line by line from left to right to produce a new string, for example: "PAHNAPLSIIGYIR".

Please implement this function to convert a string to a specified number of rows:

string convert(string s, int numRows);

Example 1:

输入:s = "PAYPALISHIRING", numRows = 3
输出:"PAHNAPLSIIGYIR"

Example 2:

输入:s = "PAYPALISHIRING", numRows = 4
输出:"PINALSIGYAHRPI"
解释:
P     I    N
A   L S  I G
Y A   H R
P     I

Example 3:

输入:s = "A", numRows = 1
输出:"A"

hint:

  • 1 <= s.length <= 1000
  • s consists of English letters (lowercase and uppercase), ',' and '.'
  • 1 <= numRows <= 1000
class Solution {
    
    
    public String convert(String s, int numRows) {
    
    

    }
}

3.2 Ideas for doing the questions

What does this topic mean? It is to transform the given string into numRows N-type graphics. For example:
insert image description here
we can use a two-dimensional array to simulate the result, but the time complexity and space complexity are very high. Then there is a way to What about reducing time complexity and space complexity? Yes, we just need to observe more, and then find out the rules: which characters are in the first line, which characters are in the last line, and then these recombined characters can be spliced ​​together, so the problem of this question The key is how to find the law.

insert image description here

3.3 Java code implementation

class Solution {
    
    
    public String convert(String ss, int numRows) {
    
    
        if(numRows == 1) return ss;
        char[] s = ss.toCharArray();
        int n = s.length;
        int d = 2 * numRows - 2;
        StringBuilder ret = new StringBuilder();
        //处理第一行数据
        for(int i = 0; i < n; i += d) ret.append(s[i]);
        //处理中间 numRows-2 行数据
        for(int i = 1; i < numRows - 1; i++) {
    
    
            for(int j = i, k = d - j; j < n || k < n; j += d, k += d) {
    
    
                if(j < n) ret.append(s[j]);
                if(k < n) ret.append(s[k]);
            }
        }
        //处理最后一行数据
        for(int i = numRows - 1; i < n; i += d) ret.append(s[i]);

        return ret.toString();
    }
}

insert image description here

4. Appearance array

https://leetcode.cn/problems/count-and-say/

4.1 Topic Requirements

Given a positive integer n, output the nth item of appearance sequence.

The "appearance sequence" is a sequence of integers, starting from the number 1, and each item in the sequence is a description of the previous item.

You can think of it as a sequence of numeric strings defined by a recursive formula:

countAndSay(1) = "1"
countAndSay(n) is a description of countAndSay(n-1), then converted into another string of numbers.
The first five are as follows:

  1. 1
    
  2. 11
    
  3. 21
    
  4. 1211
    
  5. 111221
    

The first item is the number 1
to describe the previous item. This number is 1, which means "one 1", which is recorded as "11"
to describe the previous item. This number is 11, which means "two 1s", which is recorded as "21"
to describe the previous item. Item, this number is 21, namely "one 2 + one 1", recorded as "1211"
to describe the previous item, this number is 1211, namely "one 1 + one 2 + two 1", recorded as "111221"
to describe a For numeric strings, first split the string into a minimum number of groups, each group consisting of at most consecutive identical characters. Then for each group, first describe the number of characters, and then describe the characters, forming a description group. To convert a description to a numeric string, replace the number of characters in each group with a number, then concatenate all description groups.

For example, the description of the numeric string "3322251" is as follows:
insert image description here

Example 1:

输入:n = 1
输出:"1"
解释:这是一个基本样例。

Example 2:

输入:n = 4
输出:"1211"
解释:
countAndSay(1) = "1"
countAndSay(2) = 读 "1" = 一 个 1 = "11"
countAndSay(3) = 读 "11" = 二 个 1 = "21"
countAndSay(4) = 读 "21" = 一 个 2 + 一 个 1 = "12" + "11" = "1211"

hint:

  • 1 <= n <= 30
class Solution {
    
    
    public String countAndSay(int n) {
    
    

    }
}

4.2 Ideas for doing the questions

This question can use double pointers to manage the interval of the same number. Both the left pointer and the right pointer start from 0. When the content pointed by right is the same as that pointed by left, right continues to move backward. If they are not equal, Then the content in the string can be updated. After the update is completed, the left pointer points to the position pointed by the right pointer, and then the right pointer continues to move backward until right points to the end of the string.

4.3 Java code implementation

class Solution {
    
    
    public String countAndSay(int n) {
    
    
        String ret = "1";
        for(int i = 1; i < n; i++) {
    
    
            StringBuilder tmp = new StringBuilder();
            int left = 0, right = 0;
            while(right < ret.length()) {
    
    
                while(right < ret.length() && ret.charAt(left) == ret.charAt(right)) right++;
                //相同数字的数量
                tmp.append(Integer.toString(right - left));
             	//数字
                tmp.append(ret.charAt(left));
                left = right;
            }
            ret = tmp.toString();
        }
        return ret;
    }
}

insert image description here

5. Count Frogs

https://leetcode.cn/problems/minimum-number-of-frogs-croaking/

5.1 Topic Requirements

You are given a string croakOfFrogs that represents a combination of croaks made by different frogs (the string "croak"). Since multiple frogs can croak at the same time, multiple "croaks" are mixed in croakOfFrogs .

Please return the minimum number of different frogs required to simulate all frog calls in the simulated string.

To make a frog cry "croak", the frog must output the 5 letters 'c', 'r', 'o', 'a', 'k' in sequence. If it doesn't output all five letters, then it won't make a sound. Return -1 if the string croakOfFrogs is not a mixture of valid "croak" characters.

Example 1:

输入:croakOfFrogs = "croakcroak"
输出:1 
解释:一只青蛙 “呱呱” 两次

Example 2:

输入:croakOfFrogs = "crcoakroak"
输出:2 
解释:最少需要两只青蛙,“呱呱” 声用黑体标注
第一只青蛙 "crcoakroak"
第二只青蛙 "crcoakroak"

Example 3:

输入:croakOfFrogs = "croakcrook"
输出:-1
解释:给出的字符串不是 "croak" 的有效组合。

hint:

  • 1 <= croakOfFrogs.length <= 105
  • The only characters in the string are 'c', 'r', 'o', 'a' or 'k'
class Solution {
    
    
    public int minNumberOfFrogs(String croakOfFrogs) {
    
    

    }
}

5.2 Ideas for doing the questions

The meaning of this question is to judge the minimum number of frogs based on their calls, so how can we judge whether it is a frog? According to his cry, when hearing 'c', if the characters 'r' 'o' 'a' 'k' appear in sequence, then this can be counted as a frog, if it appears after croak croak, it can be considered as a frog croaking twice, "croakcroak", but if 'c' appears during the first frog croaking, it can only be the croaking of the second frog—— "crocakroak", which means there are two frogs. Because 'c' 'r' 'o' 'a' 'k' needs to appear in order, so when you encounter 'r', you need to know whether the previous 'c' appears at least once, and the following 'o'' The same is true for a' 'k', if the previous letter does not appear, just return -1 directly.

insert image description here
But in this way, the count is not the least number of frogs. If you want to count the least number of frogs, when you encounter the character 'c', you can judge whether the character 'k' exists. If it exists, it means that a frog has called When it's over, it can call a second time, that is, the number of k –, the number of c++.

5.3 Java code implementation

class Solution {
    
    
    public int minNumberOfFrogs(String croakOfFrogs) {
    
    
        String s = "croak";
        int n = s.length();
        Map<Character,Integer> map = new HashMap<>();
        //这个哈希表中存放叫声对应的字符和下标
        for(int i = 0; i < n; i++) {
    
    
            map.put(s.charAt(i),i);
        }
        //这个哈希表用来统计字符出现的次数,也就是模拟出蛙叫的过程
        int[] hash = new int[n];
        for(int i = 0; i < croakOfFrogs.length(); i++) {
    
    
            char ch = croakOfFrogs.charAt(i);
            //当遇到 'c' 字符的时候,需要判断 'k' 字符是否出现
            if(map.get(ch) == 0) {
    
    
                if(hash[n - 1] != 0) {
    
    
                    hash[n - 1]--;
                    hash[0]++;
                }else {
    
    
                    hash[0]++;
                }
            }else {
    
    
                if(hash[map.get(ch) - 1] == 0) return -1;
                hash[map.get(ch) - 1]--;
                hash[map.get(ch)]++;
            }
        }

		//当字符串遍历完之后,如果除 k 位置可以不为0之外,其他字符位置数量如果不为0,
		//则说明有不正确的叫声,直接返回-1
        for(int i = 0; i < n - 1; i++) {
    
    
            if(hash[i] != 0) return -1;
        }

        return hash[n-1];
    }
}

insert image description here

Summarize

In this blog, we delved into the definition, application, and implementation of simulation algorithms. Simulation algorithms are powerful tools that help us simulate complex systems, solve optimization problems, and verify and test the behavior of systems.

Through simulation algorithms, we can simulate various processes, systems or phenomena in the real world and generate results similar to the real situation. This allows us to better understand and predict the behavior of complex systems, optimize solutions, and verify the correctness and performance of systems.

When designing and implementing a simulation algorithm, we need to select an appropriate model, define appropriate steps and rules, and conduct data collection and result analysis. Correctness and accuracy of these steps are critical to producing reliable simulation results.

Simulation algorithms are widely used in many fields, including scientific research, engineering design, optimization and decision-making. They provide us with a powerful tool for understanding and exploring the behavior of complex systems and enabling us to make more informed decisions.

Although simulation algorithms have many advantages, we also need to recognize their limitations. Simulation algorithms are often based on assumptions and simplifications and may not simulate real-world conditions with complete accuracy. Therefore, when using simulation algorithms, we need to carefully evaluate the reliability of the results and conduct a comprehensive analysis combining domain knowledge and actual data.

To summarize, a simulation algorithm is a powerful computer algorithm that simulates the behavior and rules of a target object to produce results that resemble real situations. It plays an important role in the fields of scientific research, engineering design, optimization and decision-making. By making good use of simulation algorithms, we can better understand and deal with complex systems, providing strong support for future development and innovation.

Guess you like

Origin blog.csdn.net/m0_73888323/article/details/132643811