100262. Find the Sum of Encrypted Integers
给你一个整数数组 nums ,数组中的元素都是 正 整数。定义一个加密函数 encrypt ,encrypt(x) 将一个整数 x 中 每一个 数位都用 x 中的 最大 数位替换。比方说 encrypt(523) = 555 且 encrypt(213) = 333 。
请你返回数组中所有元素加密后的 和 。
测试样例:
输入:nums = [1,2,3]
输出:6
解释:加密后的元素位 [1,2,3] 。加密元素的和为 1 + 2 + 3 == 6 。
解答:按照题意,变化每个数字并累加。
class Solution {
public int sumOfEncryptedInt(int[] nums) {
int res = 0;
for (int n : nums) {
res += max(n);
}
return res;
}
private int max(int num) {
String tmp = String.valueOf(num);
int max = 0;
for (int i = 0; i < tmp.length(); ++i) {
max = Math.max(max, tmp.charAt(i) - '0');
}
StringBuilder res = new StringBuilder();
for (int i = 0; i < tmp.length(); ++i) {
res.append(max);
}
return Integer.parseInt(res.toString());
}
}
100209. Mark Elements on Array by Performing Queries
给你一个长度为 n 下标从 0 开始的正整数数组 nums 。
同时给你一个长度为 m 的二维操作数组 queries ,其中 queries[i] = [indexi, ki] 。
一开始,数组中的所有元素都 未标记 。
你需要依次对数组执行 m 次操作,第 i 次操作中,你需要执行:
- 如果下标 indexi 对应的元素还没标记,那么标记这个元素。
- 然后标记 ki 个数组中还没有标记的 最小 元素。如果有元素的值相等,那么优先标记它们中下标较小的。如果少于 ki 个未标记元素存在,那么将它们全部标记。
请你返回一个长度为 m 的数组 answer ,其中 answer[i]是第 i 次操作后数组中还没标记元素的 和 。
测试样例:
输入:nums = [1,2,2,1,2,3,1], queries = [[1,2],[3,3],[4,2]]
输出:[8,3,0]
解释:我们依次对数组做以下操作:
- 标记下标为 1 的元素,同时标记 2 个未标记的最小元素。标记完后数组为 nums = [1,2,2,1,2,3,1] 。未标记元素的和为 2 + 2 + 3 + 1 = 8 。
- 标记下标为 3 的元素,由于它已经被标记过了,所以我们忽略这次标记,同时标记最靠前的 3 个未标记的最小元素。标记完后数组为 nums = [1,2,2,1,2,3,1] 。未标记元素的和为 3 。
- 标记下标为 4 的元素,由于它已经被标记过了,所以我们忽略这次标记,同时标记最靠前的 2 个未标记的最小元素。标记完后数组为 nums = [1,2,2,1,2,3,1] 。未标记元素的和为 0 。
解答:利用优先队列将当前数组进行排序,然后引入一个标记数组,最后完成当前数组累和。遍历所有query元素,按照题意完成第index位标记,并寻找最小的k个未标记的数,所有未标记数从累和中扣除。
class Solution {
public long[] unmarkedSumArray(int[] nums, int[][] queries) {
long sum = 0;
PriorityQueue<Integer> queue = new PriorityQueue<>((a, b) -> (Integer.compare(nums[a], nums[b]) == 0
? Integer.compare(a, b) : Integer.compare(nums[a], nums[b])));
for (int i = 0; i < nums.length; ++i) {
queue.add(i);
sum += nums[i];
}
long[] res = new long[queries.length];
boolean[] isMark = new boolean[nums.length];
for (int i = 0; i < res.length; ++i) {
if (!isMark[queries[i][0]]) {
sum -= nums[queries[i][0]];
isMark[queries[i][0]] = true;
}
int remain = queries[i][1];
while (!queue.isEmpty() && remain > 0) {
int tmp = queue.poll();
if (!isMark[tmp]) {
isMark[tmp] = true;
sum -= nums[tmp];
--remain;
}
}
res[i] = sum;
}
return res;
}
}
100249. Replace Question Marks in String to Minimize Its Value
给你一个字符串 s 。s[i] 要么是小写英文字母,要么是问号 '?' 。
对于长度为 m 且 只 含有小写英文字母的字符串 t ,我们定义函数 cost(i) 为下标 i 之前(也就是范围 [0, i - 1] 中)出现过与 t[i] 相同 字符出现的次数。
字符串 t 的 分数 为所有下标 i 的 cost(i) 之 和 。
比方说,字符串 t = "aab" :
- cost(0) = 0
- cost(1) = 1
- cost(2) = 0
- 所以,字符串 "aab" 的分数为 0 + 1 + 0 = 1 。
你的任务是用小写英文字母 替换 s 中 所有 问号,使 s 的 分数最小 。
请你返回替换所有问号 '?' 之后且分数最小的字符串。如果有多个字符串的 分数最小 ,那么返回字典序最小的一个。
测试样例:
输入:s = "???"
输出:"abc"
解释:这个例子中,我们将 s 中的问号 '?' 替换得到 "abc" 。对于字符串 "abc" ,cost(0) = 0 ,cost(1) = 0 和 cost(2) = 0 。"abc" 的分数为 0 。其他修改 s 得到分数 0 的字符串为 "cba" ,"abz" 和 "hey" 。这些字符串中,我们返回字典序最小的。
解答:这周个人认为最难的一题,是一道脑筋急转弯题。对于每个?字符,可以认为它是对当前所有已经确认的某个字符的累和。那么每个?都是寻找当前哪个字符出现最少的过程。?的替换顺序其实不重要,获取字符串之后,排序插入即可。
class Solution {
public String minimizeStringValue(String s) {
int[] count = new int[26];
for (int i = 0; i < s.length(); ++i) {
if (s.charAt(i) != '?') {
count[s.charAt(i) - 'a'] += 1;
}
}
List<Character> list = new ArrayList<>();
for (int i = 0; i < s.length(); ++i) {
if (s.charAt(i) == '?') {
int min = Integer.MAX_VALUE, pos = 0;
for (int j = 0; j < 26; ++j) {
if (min > count[j]) {
min = count[j];
pos = j;
}
}
list.add((char)(pos + 'a'));
count[pos] += 1;
}
}
Collections.sort(list);
StringBuilder res = new StringBuilder();
int pos = 0;
for (int i = 0; i < s.length(); ++i) {
if (s.charAt(i) != '?') {
res.append(s.charAt(i));
} else {
res.append(list.get(pos++));
}
}
return res.toString();
}
}
100216. Maximum Strength of K Disjoint Subarrays
给你一个长度为 n 的整数数组 nums 和一个 正 整数 k 。
一个整数数组的 能量 定义为和 等于 k 的子序列的数目。
请你返回 nums 中所有子序列的 能量和 。
由于答案可能很大,请你将它对 10^9 + 7 取余 后返回。
测试样例:
输入:nums = [1,2,3], k = 3
输出:6
解释:总共有 5 个能量不为 0 的子序列:
- 子序列 [1,2,3] 有 2 个和为 3 的子序列:[1,2,3] 和 [1,2,3] 。
- 子序列 [1,2,3] 有 1 个和为 3 的子序列:[1,2,3] 。
- 子序列 [1,2,3] 有 1 个和为 3 的子序列:[1,2,3] 。
- 子序列 [1,2,3] 有 1 个和为 3 的子序列:[1,2,3] 。
- 子序列 [1,2,3] 有 1 个和为 3 的子序列:[1,2,3] 。
所以答案为 2 + 1 + 1 + 1 + 1 = 6 。
解答:k的范围不大,其实可以遍历并搜索所有小于等于k的数字,属于的子序列数。逻辑比较简单,遍历数字。如果当前数字选择不加入,那么当前累和子序列次数*2(加入,不加入两种情况)。选择加入,那么对当前累和+n进行更新。
class Solution {
private static final int mod = 1_000_000_007;
public int sumOfPower(int[] nums, int k) {
int[] mem = new int[k + 1];
mem[0] = 1;
for (int n : nums) {
int[] nextMem = new int[k + 1];
for (int j = k; j >= 0; --j) {
nextMem[j] = (2 * mem[j]) % mod;
if (j - n >= 0) {
nextMem[j] = (nextMem[j] + mem[j - n]) % mod;
}
}
mem = nextMem;
}
return mem[k];
}
}