算法---模拟
目录
1. 替换所有的问号
1.1 解题思路
1.2 代码实现
2. 提莫攻击
2.1 解题思路
2.2 代码实现
3. Z字形变换
3.1 解题思路
3.2 代码实现
4. 外观数列
4.1 解题思路
4.2 代码实现
5. 数青蛙
5.1 解题思路
5.2 代码实现
1. 替换所有的问号
1.1 解题思路

这道题给我们一个包含小写字母和'?’字符的字符串,让我们将字符串里面的?换成小写字母,并且保证字符串里面没有连续的字符。

那我们可以遍历字符串,在遇到?时候,要放入的小写字母不能跟当前位置的前一个位置和后一个位置的小写字母相同,这里开头是?的话就只用比较右边的那个字符,结尾是?的话就只用比较左边的那个字符。
1.2 代码实现
class Solution {public String modifyString(String s) {char[] arr = s.toCharArray();int len = arr.length;for(int i = 0; i < len; i++) {if(arr[i] == '?') {for(char c = 'a'; c <= 'z'; c++) {if((i == 0 || c != arr[i-1]) && (i == len-1 || c != arr[i+1])) {arr[i] = c;break;}}}}return new String(arr);}
}
2. 提莫攻击
题目链接
2.1 解题思路

这道题给给我们一个数组,里面是从第几秒开始掉血,和一个掉血持续时间d秒,如果两个时间间隔小于d 就会重新计时,让我们计算该数组一共要掉血多少秒。

我们可以画个数组发现,两个数之间小于d,就会重新计时,此时前面的数只能执行两数之差秒,如果>=d,才会执行完整的时间d。
2.2 代码实现
class Solution {public int findPoisonedDuration(int[] timeSeries, int d) {int len = timeSeries.length;if(len == 1) {return d;}int sum = 0;for(int i = 1; i < len; i++) {int tmp = timeSeries[i] - timeSeries[i-1];if(tmp >= d) {sum += d;}else {sum += tmp;}}return sum + d;}
}
3. Z字形变换
题目链接
3.1 解题思路

这道题给我们一个字符串s和一个行数n,让我们返回字符串按照上面排序后的新字符串。
方法一:
我们可以将字符串放到一个二维数组里面,然后遍历这个二维数组,返回字符串:

方法二:
我们可以找规律,将字符串对应的第几个字符填到二维数组中,找规律打印对应的字符串的第几个字符:

3.2 代码实现
普通解法代码:
class Solution {public String convert(String s, int n) {int len = s.length();//当二维数组只有一行或者一列if (n == 1 || len <= n) {return s;}char[] c = s.toCharArray();char[][] arr = new char[n][len];int x = 0, y = 0;//周期:每个周期填2*n-2个字符int t = 2*n-2;for(int i = 0; i < len; i++) {arr[x][y] = c[i];if(i % t < n-1) {x++;//向下移动}else {//向右上移动x--;y++;}}StringBuilder ss = new StringBuilder();for (int k = 0; k < n; k++) {for (int j = 0; j < len; j++) {if (arr[k][j] != 0) {ss.append(arr[k][j]);}}}return ss.toString();}
}
找到规律实现的代码:
class Solution {public String convert(String s, int n) {int len = s.length();if(n == 1 || len <= n) {return s;}char[] c = s.toCharArray();StringBuilder ss = new StringBuilder();int d = 2 * n -2;for(int i = 0; i < n; i++) {if(i == 0 || i == n-1) {//打印第一行和最后一行for(int j = i; j < len; j += d) {ss.append(c[j]);}}else {//打印中间行int tmp = 2*n - 2 - i;for(int j = i; j < len; j += d) {ss.append(c[j]);if(tmp < len) {ss.append(c[tmp]);}tmp += d;}}}return ss.toString();}
}
4. 外观数列
题目链接
4.1 解题思路

这道题给我们一个数字n,让我们求该数字的行程长度编码,n的行程长度编码=(n-1)的行程长度编码进行运算,这个运算指的是对这个字符串进行解析,例如:"111133355566",这个字符串有4个1,3个3,3个5,2个6 运算后为41 33 35 26。返回这个值就行。
我们直接进行解题:

利用模拟+双指针的算法解决,如果给的数是n,我们一共要进行n-1次运算。
4.2 代码实现
class Solution {public String countAndSay(int n) {if(n == 1) {return "1";}String start = "1";for(int j = 1 ; j < n; j++) {int left = 0;int right = 0;StringBuilder newStart = new StringBuilder();for(right = 0; right < start.length();) {while(right < start.length() && start.charAt(left) == start.charAt(right)) {right++;}newStart.append(Integer.toString(right-left));newStart.append(start.charAt(left));left = right;}start = newStart.toString();}return start;}
}
5. 数青蛙
题目链接
5.1 解题思路

这道题给你一个字符串cro,里面包含多个青蛙的叫声,青蛙的叫声是“croak”,字符串cro可能包含多个青蛙的叫声,返回这个字符串最少需要几个青蛙完成叫。
比如croakcroak,这表示一个青蛙就能发出,
比如crcoakroak,表示至少两个青蛙才能发出,
比如croakcrook,这种就不满足情况,返回-1,
比如croakcroa,这种也不满足情况,返回-1.
我们可以分析下:

我们可以遍历字符串,设置一个哈希表来表示青蛙叫声的每个字符以及其对应的数量,然后遍历字符串,分情况讨论:
方法一:
我们使用哈希表表示青蛙叫声字符串,然后使用if语句分情况讨论不同前驱字符的情况。
方法二:
我们使用数组表示哈希表表示青蛙叫声字符串。
使用哈希表表示青蛙每个叫声对应的字符以及该字符对应的下标,更方便找到前驱节点。
5.2 代码实现
方法一:
class Solution {public int minNumberOfFrogs(String croakOfFrogs) {Map<Character,Integer> hash = new HashMap<Character,Integer>();char[] s = croakOfFrogs.toCharArray();int len = s.length;hash.put('c',0);hash.put('r',0);hash.put('o',0);hash.put('a',0);hash.put('k',0);for(int i = 0; i < len; i++) {if(s[i] == 'c') {//不存在if(hash.get('k') == 0) {hash.put('c',hash.get('c')+1);}else {hash.put('k',hash.get('k')-1);hash.put('c',hash.get('c')+1);}}else if(s[i] == 'r') {//存在if(hash.get('c') >= 1) {hash.put('r',hash.get('r')+1);hash.put('c',hash.get('c')-1);}else {return -1;}}else if(s[i] == 'o') {//存在if(hash.get('r') >= 1) {hash.put('o',hash.get('o')+1);hash.put('r',hash.get('r')-1);}else {return -1;}}else if(s[i] == 'a') {//存在if(hash.get('o') >= 1) {hash.put('a',hash.get('a')+1);hash.put('o',hash.get('o')-1);}else {return -1;}}else {//存在if(hash.get('a') >= 1) {hash.put('k',hash.get('k')+1);hash.put('a',hash.get('a')-1);}else {return -1;}}}if(hash.get('c') != 0 || hash.get('r') != 0 || hash.get('o') != 0 || hash.get('a') != 0) {return -1;}return hash.get('k');}
}
方法二:
class Solution {public int minNumberOfFrogs(String croakOfFrogs) {char[] s = croakOfFrogs.toCharArray();String ss = "croak";int len = ss.length();//使用数组表示哈希表int[] hash = new int[len];//使用哈希表来表示蛙声对应字符的下标Map<Character,Integer> Index = new HashMap<>();for(int i = 0; i < len; i++) {Index.put(ss.charAt(i),i);}//计算最少青蛙for(char ch : s) {//遇到第一个字符if(ch == ss.charAt(0)) {//最后一个字符存在if(hash[len-1] != 0) {hash[len-1]--;hash[0]++;}else {hash[0]++;}}else {//获取当前字符下标int i = Index.get(ch);//前驱字符存在if(hash[i-1] != 0) {hash[i-1]--;hash[i]++;}else {return -1;}}}//判断除最后一个字符的其他字符是否还存在for(int i = 0; i < len-1; i++) {if(hash[i] != 0) {return -1;}}return hash[len-1];}
}