问题描述
小R有一个特殊的随机播放规则。他首先播放歌单中的第一首歌,播放后将其从歌单中移除。如果歌单中还有歌曲,则会将当前第一首歌移到最后一首。这个过程会一直重复,直到歌单中没有任何歌曲。
例如,给定歌单 [5, 3, 2, 1, 4],真实的播放顺序是 [5, 2, 4, 1, 3]。
保证歌曲中的id两两不同。
测试样例
样例1:
输入:n = 5 ,a = [5, 3, 2, 1, 4]
输出:[5, 2, 4, 1, 3]
样例2:
输入:n = 4 ,a = [4, 1, 3, 2]
输出:[4, 3, 1, 2]
样例3:
输入:n = 6 ,a = [1, 2, 3, 4, 5, 6]
输出:[1, 3, 5, 2, 6, 4]
这题的实现思路非常的简单,只需要将歌单数组全部存进一个双向队列中,再每次取出最前面的歌,然后再取出一首歌存放进队尾,这样一直循环直到队列中没有歌曲了。完整逻辑是:
- 初始化双向队列:将整个歌单数组中的歌曲全部存入一个双向队列中。由于双向队列允许我们从两端进行操作,这为我们实现题目中的特殊播放规则提供了便利。
- 处理播放逻辑:
- 每次从队列的最前端取出第一首歌进行播放,这代表了播放当前的第一首歌。
- 然后紧接着从队列的最前端取出下一首歌,并将其放置到队列的最末尾。这个操作模拟了将当前第一首歌移到歌单的最后一位。
- 循环操作:重复上述步骤,每次操作后队列的长度都会减少一个,直到队列为空,此时所有的歌曲都已经按照特定的顺序播放完毕。
- 记录播放顺序:在每次从队列中取出歌曲进行播放时,我们将这首歌记录到一个新的数组中,这个数组最终将包含所有歌曲的真实播放顺序。
import java.util.*;
public class Main {
public static int[] solution(int n, int[] a) {
// write code here
int[] b = new int[n];
b[0] = a[0];
Deque<Integer> deque = new ArrayDeque<>();
for (int i = 1; i < n; i++) {
deque.add(a[i]);
}
int k = 1;
while (!deque.isEmpty()) {
Integer pollFirst = deque.pollFirst();
deque.addLast(pollFirst);
System.out.println(pollFirst);
b[k] = deque.pollFirst();
k++;
}
return b;
}
public static void main(String[] args) {
System.out.println(Arrays.equals(solution(5, new int[] { 5, 3, 2, 1, 4 }), new int[] { 5, 2, 4, 1, 3 }));
System.out.println(Arrays.equals(solution(4, new int[] { 4, 1, 3, 2 }), new int[] { 4, 3, 1, 2 }));
System.out.println(Arrays.equals(solution(6, new int[] { 1, 2, 3, 4, 5, 6 }), new int[] { 1, 3, 5, 2, 6, 4 }));
}
}
最少字符串操作次数
问题描述
小U得到一个只包含小写字母的字符串 S。她可以执行如下操作:每次选择字符串中两个相同的字符删除,然后在字符串末尾添加一个任意的小写字母。小U想知道,最少需要多少次操作才能使得字符串中的所有字母都不相同?
测试样例
样例1:
输入:S = "abab"
输出:2
样例2:
输入:S = "aaaa"
输出:2
样例3:
输入:S = "abcabc"
输出:3
首先,我们将输入的字符串转换为其组成的字符,并将它们存储在一个HashMap集合中,其中键是字符串中的每个字符,而值则是对应字符出现的次数。接着,我们引入一个变量<font style="color:rgb(26, 32, 41);">excessCharacters</font>,用以追踪不同字母种类的总数。我们遍历这个HashMap,针对那些出现次数超过一次的字符执行减少操作。每执行一次减少操作,<font style="color:rgb(26, 32, 41);">excessCharacters</font>的值便增加一。值得注意的是,当某个字符的出现次数为偶数时,经过操作后,该字符将被完全移除,因此我们需要在<font style="color:rgb(26, 32, 41);">excessCharacters</font>中减去一个计数。在遍历结束后,如果剩余的不同字符种类超过了26个英文字母的总数,那么每个超出部分的字符都需要额外进行一次删除操作。因此,最终的所需操作次数需要加上<font style="color:rgb(26, 32, 41);">excessCharacters</font>与26的差值。
import java.util.*;
public class Main {
public static int solution(String s) {
// write code here
Map<Character, Integer> character = new HashMap<Character, Integer>();
for (int i = 0; i < s.length(); i++) {
char key = s.charAt(i);
character.put(key, character.getOrDefault(key, 0) + 1);
}
int operations = 0;
int excessCharacters = character.size(); // 用于记录超出26个字母的字符总数
for (int count : character.values()) {
if (count > 1) {
// 每次操作可以减少两个相同的字符
operations += count / 2;
// 如果字符数量是奇数,则会有一个字符剩余
excessCharacters += count / 2;
if (count % 2 == 0) {
excessCharacters--;
}
}
}
// 小写字符总共26个,每次删除两个相同的就会增加1个小写字符
// 如果超出26个字母的字符总数大于0,则需要额外的操作
// 因为每次操作可以添加一个新的字符,所以需要额外的操作次数
if (excessCharacters > 26) {
operations += excessCharacters - 26;
}
return operations;
}
public static void main(String[] args) {
System.out.println(solution("abab") == 2);
System.out.println(solution("aaaa") == 2);
System.out.println(solution("abcabc") == 3);
}
}