目录
6362. 最长平衡子字符串
给你一个仅由 0
和 1
组成的二进制字符串 s
。 如果子字符串中 所有的 0
都在 1
之前 且其中 0
的数量等于 1
的数量,则认为 s
的这个子字符串是平衡子字符串。请注意,空子字符串也视作平衡子字符串。 返回 s
中最长的平衡子字符串长度。子字符串是字符串中的一个连续字符序列。
示例 1:
输入:s = "01000111" 输出:6 解释:最长的平衡子字符串是 "000111" ,长度为 6 。
示例 2:
输入:s = "00111" 输出:4 解释:最长的平衡子字符串是 "0011" ,长度为 4 。
示例 3:
输入:s = "111" 输出:0 解释:除了空子字符串之外不存在其他平衡子字符串,所以答案为 0 。
提示:
1 <= s.length <= 50
'0' <= s[i] <= '1'
class Solution {
public int findTheLongestBalancedSubstring(String s) {
int n = s.length();
if(n < 2) return 0;
int res = 0;
for(int i = 0; i < n - 1; i++){
if(s.charAt(i) == '0' && s.charAt(i + 1) == '1'){
int j = i, k = i + 1;
while(j >= 0 && k < n && s.charAt(j) == '0' && s.charAt(k) == '1'){
--j;
++k;
}
res = Math.max(res, k - j - 1);
}
}
return res;
}
}
6363. 转换二维数组
给你一个整数数组 nums
。请你创建一个满足以下条件的二维数组:
- 二维数组应该 只 包含数组
nums
中的元素。 - 二维数组中的每一行都包含 不同 的整数。
- 二维数组的行数应尽可能 少 。
返回结果数组。如果存在多种答案,则返回其中任何一种。请注意,二维数组的每一行上可以存在不同数量的元素。
示例 1:
输入:nums = [1,3,4,1,2,3,1] 输出:[[1,3,4,2],[1,3],[1]] 解释:根据题目要求可以创建包含以下几行元素的二维数组: - 1,3,4,2 - 1,3 - 1 nums 中的所有元素都有用到,并且每一行都由不同的整数组成,所以这是一个符合题目要求的答案。 可以证明无法创建少于三行且符合题目要求的二维数组。
示例 2:
输入:nums = [1,2,3,4] 输出:[[4,3,2,1]] 解释:nums 中的所有元素都不同,所以我们可以将其全部保存在二维数组中的第一行。
提示:
1 <= nums.length <= 200
1 <= nums[i] <= nums.length
class Solution {
public List<List<Integer>> findMatrix(int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
int m = 0;
for(int i = 0; i < nums.length; ++i){
map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
m = Math.max(map.get(nums[i]), m);
}
List<List<Integer>> res = new ArrayList<>();
for(int i = 0 ; i < m; i++) res.add(new ArrayList<Integer>());
int index = 0;
while(index < m){
for(Integer key: map.keySet()) {
if(map.get(key) > 0) res.get(index).add(key);
map.put(key, map.get(key) - 1);
}
index++;
}
return res;
}
}
6364. 老鼠和奶酪
有两只老鼠和 n
块不同类型的奶酪,每块奶酪都只能被其中一只老鼠吃掉。
下标为 i
处的奶酪被吃掉的得分为:
- 如果第一只老鼠吃掉,则得分为
reward1[i]
。 - 如果第二只老鼠吃掉,则得分为
reward2[i]
。
给你一个正整数数组 reward1
,一个正整数数组 reward2
,和一个非负整数 k
。
请你返回第一只老鼠恰好吃掉 k
块奶酪的情况下,最大 得分为多少。
示例 1:
输入:reward1 = [1,1,3,4], reward2 = [4,4,1,1], k = 2 输出:15 解释:这个例子中,第一只老鼠吃掉第 2 和 3 块奶酪(下标从 0 开始),第二只老鼠吃掉第 0 和 1 块奶酪。 总得分为 4 + 4 + 3 + 4 = 15 。 15 是最高得分。
示例 2:
输入:reward1 = [1,1], reward2 = [1,1], k = 2 输出:2 解释:这个例子中,第一只老鼠吃掉第 0 和 1 块奶酪(下标从 0 开始),第二只老鼠不吃任何奶酪。 总得分为 1 + 1 = 2 。 2 是最高得分。
提示:
1 <= n == reward1.length == reward2.length <= 105
1 <= reward1[i], reward2[i] <= 1000
0 <= k <= n
java回溯(会超时):
//回溯
class Solution {
int res = Integer.MIN_VALUE;
public int miceAndCheese(int[] reward1, int[] reward2, int k) {
int n = reward1.length;
boolean[] record = new boolean[n];
Arrays.fill(record, false);
backtrack(reward1, reward2, k, 0, record);
return res;
}
private void backtrack(int[] reward1, int[] reward2, int k, int start, boolean[] record){
int count = 0;
for(boolean r : record){
if(r) ++count;
}
if(count == k){
int sum = 0;
for(int i = 0; i < reward1.length; ++i){
if(record[i]) sum += reward1[i];
else sum += reward2[i];
}
res = Math.max(res, sum);
return;
}
for(int i = start; i < reward1.length; ++i){
record[i] = true;
backtrack(reward1, reward2, k, i + 1, record);
record[i] = false;
}
}
}
啊啊啊啊,怎么又超时了
//超时 547 / 564 个通过测试用例
class Solution {
public int miceAndCheese(int[] reward1, int[] reward2, int k) {
int n = reward1.length;
int[] diff = new int[n];
for(int i = 0; i < n; ++i){
diff[i] = reward1[i] - reward2[i];
}
// 寻找diff最大的前k个值
List<Integer> pre_k = new ArrayList<>();
for(int i = 0; i < k; ++i){
int m = Integer.MIN_VALUE;
int index = -1, j = 0;
for(; j < n; ++j){
if(pre_k.contains(j)) continue;
if(diff[j] > m){
index = j;
m = diff[j];
}
}
pre_k.add(index);
}
int res = 0;
for(int i = 0; i < n; ++i){
if(pre_k.contains(i)) res += reward1[i];
else res += reward2[i];
}
return res;
}
}
利用优先队列寻找最大的前k个值还是超时了,麻木了
//552 / 564 个通过测试用例
class Solution {
public int miceAndCheese(int[] reward1, int[] reward2, int k) {
int n = reward1.length;
// 寻找diff最大的前k个值
List<Integer> pre_k = findTopKIndex(reward1, reward2, k);
int res = 0;
for(int i = 0; i < n; ++i){
if(pre_k.contains(i)) res += reward1[i];
else res += reward2[i];
}
return res;
}
private List<Integer> findTopKIndex(int[] reward1, int[] reward2, int k) {
List<Integer> result = new ArrayList<>();
if(k == 0) return result;
PriorityQueue<Integer> pq = new PriorityQueue<>(k, Comparator.comparingInt(i -> (reward1[i] - reward2[i])));
for (int i = 0; i < reward1.length; i++) {
if (pq.size() < k) {
pq.offer(i);
} else if (reward1[i] - reward2[i] > reward1[pq.peek()] - reward2[pq.peek()]) {
pq.poll();
pq.offer(i);
}
}
while (!pq.isEmpty()) {
result.add(pq.poll());
}
Collections.reverse(result);
return result;
}
}
然后换动态规划,又超内存了,我服了
class Solution {
public int miceAndCheese(int[] reward1, int[] reward2, int k) {
int n = reward1.length;
if(k >= n){
int sum = 0;
for(int x: reward1) sum+= x;
return sum;
}
if(k > n/2){
return miceAndCheese(reward2, reward1, n - k);
}
// dp[i][j]表示索引[0,i],第一只老鼠恰好吃掉 j 块奶酪的情况下的最大得分
int[][] dp = new int[n][k + 1];
dp[0][0] = reward2[0];
if(k > 0) dp[0][1] = reward1[0];
for(int i = 1; i < n; ++i){
dp[i][0] = dp[i - 1][0] + reward2[i];
}
for(int i = 1; i < n && i < k; ++i){
dp[i][i + 1] = dp[i - 1][i] + reward1[i];
}
for(int i = 1; i < n; ++i){
for(int j = 1; j <= i && j<= k; ++j){
dp[i][j] = Math.max(dp[i - 1][j - 1] + reward1[i], dp[i - 1][j] + reward2[i]);
}
}
return dp[n - 1][k];
}
}
原来还可以先全部吃reward2,再把没吃到的补上,我终于通过看题解过了这道题,不容易
class Solution {
public int miceAndCheese(int[] reward1, int[] reward2, int k) {
int ans = 0, n = reward1.length;
for(int i = 0; i < n; ++i){
ans += reward2[i];
reward1[i] -= reward2[i];
}
Arrays.sort(reward1);
for(int i = n - k; i < n; ++i){
ans += reward1[i];
}
return ans;
}
}