470.珠子颜色去重
问题描述
小S拥有一条由n颗珠子组成的手链,每颗珠子都有一个对应的颜色编号。她希望将手链上相同颜色的珠子进行去重,只保留每种颜色最后出现的那颗珠子,同时保持珠子原来的相对顺序。
测试样例
样例1:
输入:
n = 8 ,a = [1, 2, 1, 3, 4, 2, 4, 4]输出:[1, 3, 2, 4]
样例2:
输入:
n = 5 ,a = [5, 5, 5, 5, 5]输出:[5]
样例3:
输入:
n = 6 ,a = [6, 1, 2, 6, 1, 2]输出:[6, 1, 2]
解决方案
首先遍历该数组,用哈希表记录每一个数的出现次数。然后再次遍历该数组,如果当前数的出现次数等于1,那么把它加入到答案列表中;如果当前数的出现次数大于1,那么让它的出现次数减一。最后得到的答案列表就是题目所要求的,并且保留了原来的相对顺序。
参考代码
import java.util.Arrays;
import java.util.HashMap;
public class Main {
public static int[] solution(int n, int[] a) {
// write code here
HashMap<Integer, Integer> mp = new HashMap<>();
for (int i = 0; i < n; i++) {
mp.put(a[i], mp.getOrDefault(a[i], 0) + 1);
}
int m = mp.keySet().size();
int[] res = new int[m];
int pos = 0;
for (int i = 0; i < n; i++) {
if (mp.get(a[i]) == 1) {
res[pos++] = a[i];
} else {
mp.put(a[i], mp.get(a[i]) - 1);
}
}
return res;
}
public static void main(String[] args) {
System.out.println(Arrays.equals(solution(8, new int[]{1, 2, 1, 3, 4, 2, 4, 4}), new int[]{1, 3, 2, 4}));
System.out.println(Arrays.equals(solution(5, new int[]{5, 5, 5, 5, 5}), new int[]{5}));
System.out.println(Arrays.equals(solution(6, new int[]{6, 1, 2, 6, 1, 2}), new int[]{6, 1, 2}));
}
}
483.给定字符串的字符去重问题
问题描述
给定一个字符串 s,你需要通过删除一些字符,使得每个字符在字符串中出现的次数均不相同。你需要找出最少需要删除的字符数量以达到这个目标。
测试样例
样例1:
输入:
s = "aab"输出:0
样例2:
输入:
s = "aaabbbcc"输出:2
样例3:
输入:
s = "abcdef"输出:5
解决方案
首先遍历该字符串,用哈希表记录每个字符的出现次数,然后把每个字符的出现次数存到一个列表里。因为无论删除哪个字符都会让操作次数加一,所以删除任意字符都是可以的。遍历之前得到的列表,如果在这个数字前面出现过和这个数字相同的数字,那么就让它减一,同时操作数加一,直至不相同为止。为了快速知道某个数是否出现过,可以使用HashSet。这样做得到的结果是正确的,因为假设存在一个更小的操作数,那么就会存在两个数是相同的,这就矛盾了,所以得到的结果是最小的。上述做法的时间复杂度是。
参考代码
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
public class Main {
public static int solution(String s) {
// write code here
HashMap<Character, Integer> mp = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
mp.put(s.charAt(i), mp.getOrDefault(s.charAt(i), 0) + 1);
}
ArrayList<Integer> a = new ArrayList<>();
HashSet<Integer> S = new HashSet<>();
for (Character c : mp.keySet()) {
a.add(mp.get(c));
}
S.add(a.get(0));
int res = 0;
for (int i = 1; i < a.size(); i++) {
int t = a.get(i);
while (S.contains(t)) {
t--;
res++;
}
if (t > 0) {
S.add(t);
}
}
return res;
}
public static void main(String[] args) {
System.out.println(solution("aab") == 0);
System.out.println(solution("aaabbbcc") == 2);
System.out.println(solution("abcdef") == 5);
}
}
4.数字分组求偶数和
问题描述
小M面对一组从 1 到 9 的数字,这些数字被分成多个小组,并从每个小组中选择一个数字组成一个新的数。目标是使得这个新数的各位数字之和为偶数。任务是计算出有多少种不同的分组和选择方法可以达到这一目标。
numbers: 一个由多个整数字符串组成的列表,每个字符串可以视为一个数字组。小M需要从每个数字组中选择一个数字。
例如对于[123, 456, 789],14个符合条件的数为:147 149 158 167 169 248 257 259 268 347 349 358 367 369。
测试样例
样例1:
输入:
numbers = [123, 456, 789]输出:14
样例2:
输入:
numbers = [123456789]输出:4
样例3:
输入:
numbers = [14329, 7568]输出:10
解决方案
本题可以使用回溯+剪枝解决。枚举每个小组中选哪个数字,然后判断这些数字的和是否为偶数,如果是偶数,那么答案加一。回溯的时候记得恢复现场。上述做法的时间复杂度为每个小组的数字数量之积。
参考代码
public class Main {
static int n;
static int ans;
static int[] a;
public static void dfs(int u, int sum) {
if (u == n) {
if (sum % 2 == 0) {
ans++;
}
return;
}
for (int i = 0; i <= 8; i++) {
int t = a[u] / (int)Math.pow(10, i) % 10;
if (t == 0) {
break;
}
sum += t;
dfs(u + 1, sum);
sum -= t;
}
}
public static int solution(int[] numbers) {
// Please write your code here
n = numbers.length;
a = numbers;
ans = 0;
dfs(0, 0);
return ans;
}
public static void main(String[] args) {
// You can add more test cases here
System.out.println(solution(new int[]{123, 456, 789}) == 14);
System.out.println(solution(new int[]{123456789}) == 4);
System.out.println(solution(new int[]{14329, 7568}) == 10);
}
}
10.小F的永久代币卡回本计划
问题描述
小F最近迷上了玩一款游戏,她面前有一个永久代币卡的购买机会。该卡片的价格为 a 勾玉,每天登录游戏可以返还 b 勾玉。小F想知道她至少需要登录多少天,才能让购买的永久代币卡回本。
测试样例
样例1:
输入:
a = 10, b = 1输出:10
样例2:
输入:
a = 10, b = 2输出:5
样例3:
输入:
a = 10, b = 3输出:4
解决方案
为了回本,需要登录以来获取的勾玉数量大于等于a,那么就需要登录天。上述做法的时间复杂度为。
参考代码
public class Main {
public static int solution(int a, int b) {
// write code here
return (int)Math.ceil(1.0 * a / b);
}
public static void main(String[] args) {
System.out.println(solution(10, 1) == 10);
System.out.println(solution(10, 2) == 5);
System.out.println(solution(10, 3) == 4);
}
}
14.数组元素之和最小化
问题描述
小C希望构造一个包含n个元素的数组,且满足以下条件:
- 数组中的所有元素两两不同。
- 数组所有元素的最大公约数为
k。 - 数组元素之和尽可能小。
任务是输出该数组元素之和的最小值。
测试样例
样例1:
输入:
n = 3 ,k = 1输出:6
样例2:
输入:
n = 2 ,k = 2输出:6
样例3:
输入:
n = 4 ,k = 3输出:30
解决方案
因为数组中所有元素的最大公约数为k,所以数组中所有元素都是k的倍数,又由于数组中所有元素两两不同,所以每个元素都是k的不同倍数,如果想让数组元素之和最小的话,可以让k前面的系数从小到大,也就是从1开始的公差为1的等差数列。所以该数组元素之和的最小值就是,这个可以用等差数列求和公式进行计算。上述做法的时间复杂度为。
参考代码
public class Main {
public static int solution(int n, int k) {
// write code here
return n % 2 == 0 ? n / 2 * (n + 1) * k : (n + 1) / 2 * n * k;
}
public static void main(String[] args) {
System.out.println(solution(3, 1) == 6);
System.out.println(solution(2, 2) == 6);
System.out.println(solution(4, 3) == 30);
}
}