modify code

master
algorithmzuo 1 year ago
parent c209807121
commit 5d36b275ca

@ -0,0 +1,193 @@
package class_2023_05_2_week;
import java.util.Arrays;
// 来自华为OD学员问题
// 一个图像有n个像素点存储在一个长度为n的数组arr里
// 每个像素点的取值范围[0,s]的整数
// 请你给图像每个像素点值加上一个整数k可以是负数
// 像素值会自动截取到[0,s]范围,
// 当像素值<0会更改为0当新像素值>s会更改为s
// 这样就可以得到新的arr想让所有像素点的平均值最接近中位值s/2, 向下取整
// 请输出这个整数k, 如有多个整数k都满足, 输出小的那个
// 1 <= n <= 10^6
// 1 <= s <= 10^18
public class Code01_ImageArrayAverageGotoHalf {
// 暴力方法
// 为了测试
public static int best1(int[] arr, int s) {
int half = s / 2;
int average = -100000;
int ans = -s;
for (int k = -s; k <= s; k++) {
int curAverage = average1(arr, k, s);
if (Math.abs(half - curAverage) < Math.abs(half - average)) {
average = curAverage;
ans = k;
}
}
return ans;
}
// 暴力方法
// 为了测试
// arr[100, k = 200 , s
// s
public static int average1(int[] arr, int k, int s) {
int sum = 0;
for (int num : arr) {
int value = num + k;
if (value < 0) {
sum += 0;
} else if (value > s) {
sum += s;
} else {
sum += value;
}
}
return sum / arr.length;
}
// 优化了一下,但不是最优解
public static int best2(int[] arr, int s) {
int l = -s;
int r = s;
int m = 0;
int half = s / 2;
int average = -s;
int ans = 0;
while (l <= r) {
m = (l + r) / 2;
int curAverage = average1(arr, m, s);
if ((Math.abs(half - curAverage) < Math.abs(half - average))
|| ((Math.abs(half - curAverage) == Math.abs(half - average)) && m < ans)) {
average = curAverage;
ans = m;
}
if (curAverage >= half) {
r = m - 1;
} else {
l = m + 1;
}
}
return ans;
}
// 正式方法
// 最优解
// O(N * logN) + O(logS * logN)
public static int best3(int[] arr, int s) {
Arrays.sort(arr);
int[] sum = new int[arr.length];
sum[0] = arr[0];
for (int i = 1; i < arr.length; i++) {
sum[i] = sum[i - 1] + arr[i];
}
int l = -s;
int r = s;
int m = 0;
int half = s / 2;
int average = -s;
int ans = 0;
while (l <= r) {
m = (l + r) / 2;
int curAverage = average3(arr, sum, m, s);
if ((Math.abs(half - curAverage) < Math.abs(half - average))
|| ((Math.abs(half - curAverage) == Math.abs(half - average)) && m < ans)) {
average = curAverage;
ans = m;
}
if (curAverage >= half) {
r = m - 1;
} else {
l = m + 1;
}
}
return ans;
}
public static int average3(int[] arr, int[] pre, int k, int s) {
int n = arr.length;
if (k < 0) {
int l = bsZero(arr, k);
int sum = rangeSum(pre, l + 1, n - 1);
return (sum + (k * (n - l - 1))) / n;
} else {
int r = bsS(arr, k, s);
int sum = rangeSum(pre, 0, r - 1);
return (sum + (k * r) + (s * (n - r))) / n;
}
}
public static int bsZero(int[] arr, int k) {
int ans = -1;
int l = 0;
int r = arr.length - 1;
int m;
while (l <= r) {
m = (l + r) / 2;
if (arr[m] + k <= 0) {
ans = m;
l = m + 1;
} else {
r = m - 1;
}
}
return ans;
}
public static int bsS(int[] arr, int k, int s) {
int ans = arr.length;
int l = 0;
int r = arr.length - 1;
int m;
while (l <= r) {
m = (l + r) / 2;
if (arr[m] + k >= s) {
ans = m;
r = m - 1;
} else {
l = m + 1;
}
}
return ans;
}
public static int rangeSum(int[] pre, int l, int r) {
if (l > r) {
return 0;
}
return l == 0 ? pre[r] : (pre[r] - pre[l - 1]);
}
// 为了测试
public static int[] randomArray(int n, int s) {
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = (int) (Math.random() * (s + 1));
}
return arr;
}
// 为了测试
public static void main(String[] args) {
int N = 50;
int S = 500;
int testTimes = 10000;
System.out.println("测试开始");
for (int i = 0; i < testTimes; i++) {
int n = (int) (Math.random() * N) + 1;
int s = (int) (Math.random() * S) + 1;
int[] arr = randomArray(n, s);
int ans1 = best1(arr, s);
int ans2 = best2(arr, s);
int ans3 = best3(arr, s);
if (ans1 != ans2 || ans1 != ans3) {
System.out.println("出错了!");
}
}
System.out.println("测试结束");
}
}

@ -0,0 +1,180 @@
package class_2023_05_2_week;
// 来自学员问题,来自真实笔试
// 塔子哥最近在处理一些字符串相关的任务
// 他喜欢 R 字符,因为在某些任务中,这个字符通常表示“正确”的结果
// 另一方面,他不喜欢 B 字符,因为在某些任务中,这个字符通常表示“错误”的结果
// 为了解决他的任务,塔子哥定义了字符串的权值为字符串中 R 字符的出现次数
// 例如,对于字符串 BBRBRB它的权值为 2因为其中有 2 个 R 字符
// 现在,塔子哥面临一个问题,他有一个长度为 n 的字符串 s它仅由 R 和 B 组成
// 他想知道,长度为 n 的仅由 R 和 B组成的字符串中
// 字典序不小于 s 的字符串的权值之和是多少?
// 因此,他需要编写一个程序来解决这个问题
// 输入第一行为一个整数 n ,表示字符串的长度
// 输入第二行为一个长度为 n 的字符串 s ,字符串中元素组成仅为 R 和 B
// 输出一个整数,代表长度为 n 的、字典序不小于 s 的字符串权值之和
// 输入样例:
// 3
// RBR
// 输出:
// 7
// 解释:共有 3 个字符串字典序大于等于"RBR"RBR权值为2RRB为2RRR为3
// 1 <= n <= 100000
// 结果可能很大对1000000007取模
// 帖子链接 : https://www.mashibing.com/question/detail/67223
public class Code02_LexicographicBiggerSumOfR {
// 为了测试
// 暴力方法
public static int sum1(String str) {
return process1("", str);
}
// 为了测试
// 暴力方法
public static int process1(String path, String s) {
if (path.length() == s.length()) {
if (path.compareTo(s) >= 0) {
int ans = 0;
for (int i = 0; i < path.length(); i++) {
if (path.charAt(i) == 'R') {
ans++;
}
}
return ans;
} else {
return 0;
}
} else {
return process1(path + "R", s) + process1(path + "B", s);
}
}
// 以下为正式方法
public static int MAXN = 100001;
// pow2[i] : 长度为i的所有RB串一共有多少字符串%mod的余数
// 一定要求余数!
public static int[] pow2 = new int[MAXN];
// f[i] : 长度为i的所有RB串一共有多少权值和%mod的余数
// 一定要求余数!
public static int[] f = new int[MAXN];
public static int mod = 1000000007;
static {
pow2[0] = 1;
for (int i = 1; i < MAXN; i++) {
pow2[i] = (pow2[i - 1] * 2) % mod;
}
f[1] = 1;
for (int i = 2; i < MAXN; i++) {
// 2^i-1 + 2*f[i-1]
f[i] = (pow2[i - 1] + f[i - 1]) % mod;
f[i] = (f[i] + f[i - 1]) % mod;
}
}
// 普通递归版
// 不是最优解,但是展示了大过程
public static int sum2(String str) {
int n = str.length();
char[] s = str.toCharArray();
int[] rnumber = new int[n];
rnumber[0] = s[0] == 'R' ? 1 : 0;
for (int i = 1; i < n; i++) {
rnumber[i] = rnumber[i - 1] + (s[i] == 'R' ? 1 : 0);
}
return process2(s, rnumber, n, 0);
}
// 你依次填写字符串
// 0...i-1范围上你填写的东西和s完全一样
// 当前来到i位置一共的长度是n
// rnumber[i] : s[0...i]范围上有几个R
// 返回 : 在[0...i-1]和s完全一样的情况下后续所有字典序不小于s的字符串整体的权值和是多少?
public static int process2(char[] s, int[] rnumber, int n, int i) {
int ans = 0;
if (i == n) {
ans = rnumber[n - 1];
} else {
if (s[i] == 'B') {
// s当前位置是'B'你可以填写R也可以是B
// 如果你当前填R现在的情况是
// 0...i-1位置上你填写的和s一样
// i位置上s是'B',你填写的是'R'
// i之后的剩余长度是 : n-i-1你可以随便填了
// n-i-1可以随便填那么字符串个数为 : 2^(n-i-1)个
// 这2^(n-i-1)个字符串,都是:
// [0...i-1]和s一样i位置比s多一个R
// 权值和 = 1) + 2)
// 1) 是这2^(n-i-1)个字符串,前缀上的权值和
// 2) 是这2^(n-i-1)个字符串,后缀上的权值和
// 具体来说 :
// 1) (s的[0...i]范围上R的数量 + 1) * 2^(n-i-1)
// 2) 在[i+1....]范围上的权值和 : f[n-i-1]
int p1 = (int) (((long) (rnumber[i] + 1) * pow2[n - i - 1]) % mod);
p1 = (p1 + f[n - i - 1]) % mod;
// 如果你当前填B那么继续递归
int p2 = process2(s, rnumber, n, i + 1);
ans = (p1 + p2) % mod;
} else {
// s当前位置是'R'你只能填写R然后继续递归
ans = process2(s, rnumber, n, i + 1);
}
}
return ans;
}
// 彻底动态规划版
// 正式版时间复杂度O(N)
public static int sum3(String str) {
int n = str.length();
char[] s = str.toCharArray();
int[] rnumber = new int[n];
rnumber[0] = s[0] == 'R' ? 1 : 0;
for (int i = 1; i < n; i++) {
rnumber[i] = rnumber[i - 1] + (s[i] == 'R' ? 1 : 0);
}
int[] dp = new int[n + 1];
dp[n] = rnumber[n - 1];
for (int i = n - 1; i >= 0; i--) {
if (s[i] == 'B') {
int p1 = (int) (((long) (rnumber[i] + 1) * pow2[n - i - 1]) % mod);
p1 = (p1 + f[n - i - 1]) % mod;
int p2 = dp[i + 1];
dp[i] = (p1 + p2) % mod;
} else {
dp[i] = dp[i + 1];
}
}
return dp[0];
}
// 为了测试
public static String randomString(int n) {
char[] s = new char[n];
for (int i = 0; i < n; i++) {
s[i] = Math.random() < 0.5 ? 'B' : 'R';
}
return String.valueOf(s);
}
public static void main(String[] args) {
int N = 15;
int testTimes = 10000;
System.out.println("测试开始");
for (int i = 0; i < testTimes; i++) {
int n = (int) (Math.random() * N) + 1;
String s = randomString(n);
int ans1 = sum1(s);
int ans3 = sum3(s);
if (ans1 != ans3) {
System.out.println("出错了!");
}
}
System.out.println("测试结束");
}
}

@ -0,0 +1,140 @@
package class_2023_05_2_week;
import java.util.Arrays;
import java.util.List;
// 作为项目经理,你规划了一份需求的技能清单 req_skills
// 并打算从备选人员名单 people 中选出些人组成一个「必要团队」
// 编号为 i 的备选人员 people[i] 含有一份该备选人员掌握的技能列表)。
// 所谓「必要团队」,就是在这个团队中,
// 对于所需求的技能列表 req_skills 中列出的每项技能,
// 团队中至少有一名成员已经掌握。可以用每个人的编号来表示团队中的成员:
// 例如,团队 team = [0, 1, 3] 表示掌握技能分别为
// people[0]people[1],和 people[3] 的备选人员。
// 请你返回 任一 规模最小的必要团队,团队成员用人员编号表示。
// 你可以按 任意顺序 返回答案,题目数据保证答案存在。
// 测试链接 : https://leetcode.cn/problems/smallest-sufficient-team/
public class Code03_SmallestSufficientTeam {
// 需要的技能有 : "ABC" 、 "FG" 、 "ET"
// 人 "ABC" "ET" "BB"
// "ABC" 、 "FG" 、 "ET" -> "ABC" "ET" "FG"
// 0 1 2
// x : "ABC" "ET" "BB" : 2 1 0
// 0 1 1
public static int[] smallestSufficientTeam(String[] skills, List<List<String>> people) {
Arrays.sort(skills);
int n = skills.length;
int m = people.size();
int[] statuses = new int[m];
for (int i = 0; i < m; i++) {
int skillStatus = 0; // 00000000000000
List<String> skill = people.get(i);
skill.sort((a, b) -> a.compareTo(b));
int p1 = 0;
int p2 = 0;
while (p1 < n && p2 < skill.size()) {
int compare = skills[p1].compareTo(skill.get(p2));
if (compare < 0) {
p1++;
} else if (compare > 0) {
p2++;
} else {
skillStatus |= 1 << p1;
p1++;
p2++;
}
}
statuses[i] = skillStatus;
}
// 上面的过程,其实是把技能变成状态信息
// 比如:
// skills = { f,a,e,c}
// 排个序为 : a c e f
// 认为a是0技能
// 认为c是1技能
// 认为e是2技能
// 认为f是3技能
// 然后就可以把每个人的技能变成状态信息了
// 比如A会的技能 : e f t x c
// feca
// 认为A会的技能状态为 : 1110
// 解释一下 :
// 第0位是0说明A不会a技能
// 第1位是1说明A会c技能
// 第2位是1说明A会e技能
// 第3位是1说明A会f技能
// 至于t、x技能忽略因为没用
// 上面的过程,就是把技能编号
// 然后把每个人的技能变成位信息
// 比如skills一共8个技能
// 那么就是为了这个状态 : 00..0011111111
// 也就是什么时候凑齐8个1什么时候就可以结束了
int[][] dp = new int[m][1 << n];
for (int i = 0; i < m; i++) {
Arrays.fill(dp[i], -1);
}
// process函数去跑动态规划
// 目的是算出至少几人
// 以及填好动态规划表
int size = process(statuses, n, 0, 0, dp);
int[] ans = new int[size];
int ansi = 0;
int i = 0;
int status = 0;
// 大厂刷题班章节11
// 看一下,是根据动态规划表生成答案的路径
// 这就是为什么需要动态规划表,因为答案的路径可以用动态规划表生成
// 一定要看一下这个课
while (status != (1 << n) - 1) {
// 3人 3人
if (i + 1 == m || dp[i][status] != dp[i + 1][status]) {
ans[ansi++] = i;
status |= statuses[i];
}
i++;
}
return ans;
}
// 第i个人的技能列表是位信息就是people[i]people数组是固定参数
// 一定要凑齐n个技能n是固定参数
// 当前来到第i个人了可以要这个人也可以不要这个人i是可变信息
// 之前的技能哪个技能凑到了哪个技能还没凑到就是status你的目的是把它凑齐也就是凑齐n个1stauts是可变参数
// 返回值的含义 :
// 当前在people[i....]范围上选择人之前凑齐的技能状态是status请问所有技能都凑齐还需要至少几个人
// dp就是动态规划表记录返回值的
public static int process(int[] people, int n, int i, int status, int[][] dp) {
// n = 8
// 0000...0000 1111 1111
if (status == (1 << n) - 1) {
// 技能已经凑齐了
// 还需要0个人
return 0;
}
// 还没凑齐!
if (i == people.length) {
// 技能还没凑齐
// 但是人已经没了
// 怎么都凑不齐了
return Integer.MAX_VALUE;
}
if (dp[i][status] != -1) {
// 缓存命中,直接返回
return dp[i][status];
}
// 不要第i个人后续要几个人能凑齐
int p1 = process(people, n, i + 1, status, dp);
// 要第i个人后续要几个人能凑齐
int p2 = Integer.MAX_VALUE;
int next2 = process(people, n, i + 1, status | people[i], dp);
if (next2 != Integer.MAX_VALUE) {
p2 = 1 + next2;
}
// 选择人数最少的方案
int ans = Math.min(p1, p2);
dp[i][status] = ans;
return ans;
}
}

@ -0,0 +1,94 @@
package class_2023_05_2_week;
import java.util.Arrays;
// 给定一个整数数组 nums 和一个正整数 k
// 找出是否有可能把这个数组分成 k 个非空子集,其总和都相等。
// 测试链接 : https://leetcode.cn/problems/partition-to-k-equal-sum-subsets/
public class Code04_PartitionToKEqualSumSubsets {
// 状态压缩的方法,正统,处理不了大长度
// 其实任何方法都处理不了
public static boolean canPartitionKSubsets1(int[] nums, int k) {
int sum = 0;
for (int num : nums) {
sum += num;
}
if (sum % k != 0) {
return false;
}
return process1(nums, 0, 0, 0, sum / k, k, new int[1 << nums.length]) == 1;
}
public static int process1(int[] nums, int status, int sum, int sets, int limit, int k, int[] dp) {
if (dp[status] != 0) {
return dp[status];
}
int ans = -1;
if (sets == k) {
ans = 1;
} else {
for (int i = 0; i < nums.length; i++) {
if ((status & (1 << i)) == 0 && sum + nums[i] <= limit) {
if (sum + nums[i] == limit) {
ans = process1(nums, status | (1 << i), 0, sets + 1, limit, k, dp);
} else {
ans = process1(nums, status | (1 << i), sum + nums[i], sets, limit, k, dp);
}
if (ans == 1) {
break;
}
}
}
}
dp[status] = ans;
return ans;
}
public static boolean canPartitionKSubsets2(int[] nums, int k) {
int sum = 0;
for (int num : nums) {
sum += num;
}
if (sum % k != 0) {
return false;
}
Arrays.sort(nums);
return partitionK(new int[k], sum / k, nums, nums.length - 1);
}
// 100 10 -> 10
// 100 2 -> 50
// 100 4 -> 25
// 当前的数字nums[index]
// nums[n-1] 给哪个桶
// nums[n-2] 给哪个桶
// ...
// nums[0] 给哪个桶
public static boolean partitionK(int[] group, int target, int[] nums, int index) {
if (index < 0) {
return true;
}
int num = nums[index];
// len是桶的数量! 就是k
int len = group.length;
for (int i = 0; i < len; i++) {
if (group[i] + num <= target) {
// 放入后,不超
group[i] += num;
if (partitionK(group, target, nums, index - 1)) {
return true;
}
group[i] -= num;
// if (group[i] == 0) {
// return false;
// }
while (i + 1 < group.length && group[i] == group[i + 1]) {
i++;
}
}
}
return false;
}
}

@ -0,0 +1,68 @@
package class_2023_05_2_week;
import java.util.Arrays;
import java.util.TreeSet;
// 给你一个整数 n 和一个在范围 [0, n - 1] 以内的整数 p
// 它们表示一个长度为 n 且下标从 0 开始的数组 arr
// 数组中除了下标为 p 处是 1 以外,其他所有数都是 0 。
// 同时给你一个整数数组 banned ,它包含数组中的一些位置。
// banned 中第 i 个位置表示 arr[banned[i]] = 0 ,题目保证 banned[i] != p 。
// 你可以对 arr 进行 若干次 操作。一次操作中,你选择大小为 k 的一个 子数组
// 并将它 翻转 。在任何一次翻转操作后,
// 你都需要确保 arr 中唯一的 1 不会到达任何 banned 中的位置。
// 换句话说arr[banned[i]] 始终 保持 0 。
// 请你返回一个数组 ans ,对于 [0, n - 1] 之间的任意下标 i
// ans[i] 是将 1 放到位置 i 处的 最少 翻转操作次数,
// 如果无法放到位置 i 处,此数为 -1 。
// 子数组 指的是一个数组里一段连续 非空 的元素序列。
// 对于所有的 i ans[i] 相互之间独立计算。
// 将一个数组中的元素 翻转 指的是将数组中的值变成 相反顺序 。
// 测试链接 : https://leetcode.cn/problems/minimum-reverse-operations/
public class Code05_MinReverseOperations {
public static int[] minReverseOperations(int n, int p, int[] banned, int k) {
TreeSet<Integer> oddSet = new TreeSet<>();
TreeSet<Integer> evenSet = new TreeSet<>();
for (int i = 1; i < n; i += 2) {
oddSet.add(i);
}
for (int i = 0; i < n; i += 2) {
evenSet.add(i);
}
for (int ban : banned) {
oddSet.remove(ban);
evenSet.remove(ban);
}
oddSet.remove(p);
evenSet.remove(p);
int[] ans = new int[n];
Arrays.fill(ans, -1);
int[] queue = new int[n];
int l = 0;
int r = 0;
queue[r++] = p;
int level = 0;
while (l < r) {
int end = r;
for (; l < end; l++) {
int cur = queue[l];
ans[cur] = level;
// 核心的两句,举例子说明
// 纯下标变换,没什么算法
int left = Math.max(cur - k + 1, k - cur - 1);
int right = Math.min(cur + k - 1, n * 2 - k - cur - 1);
TreeSet<Integer> curSet = (left & 1) == 1 ? oddSet : evenSet;
Integer ceilling = curSet.ceiling(left);
while (ceilling != null && ceilling <= right) {
queue[r++] = ceilling;
curSet.remove(ceilling);
ceilling = curSet.ceiling(left);
}
}
level++;
}
return ans;
}
}

@ -3549,6 +3549,75 @@ B = { b1, b2, ... ,bn }。
第068节 2023年5月第2周流行算法题目解析
来自华为OD学员问题
一个图像有n个像素点存储在一个长度为n的数组arr里
每个像素点的取值范围[0,s]的整数
请你给图像每个像素点值加上一个整数k可以是负数
像素值会自动截取到[0,s]范围,
当像素值<0会更改为0当新像素值>s会更改为s
这样就可以得到新的arr想让所有像素点的平均值最接近中位值s/2, 向下取整
请输出这个整数k, 如有多个整数k都满足, 输出小的那个
1 <= n <= 10^6
1 <= s <= 10^18
来自学员问题,来自真实笔试
塔子哥最近在处理一些字符串相关的任务
他喜欢 R 字符,因为在某些任务中,这个字符通常表示“正确”的结果
另一方面,他不喜欢 B 字符,因为在某些任务中,这个字符通常表示“错误”的结果
为了解决他的任务,塔子哥定义了字符串的权值为字符串中 R 字符的出现次数
例如,对于字符串 BBRBRB它的权值为 2因为其中有 2 个 R 字符
现在,塔子哥面临一个问题,他有一个长度为 n 的字符串 s它仅由 R 和 B 组成
他想知道,长度为 n 的仅由 R 和 B组成的字符串中
字典序不小于 s 的字符串的权值之和是多少?
因此,他需要编写一个程序来解决这个问题
输入第一行为一个整数 n ,表示字符串的长度
输入第二行为一个长度为 n 的字符串 s ,字符串中元素组成仅为 R 和 B
输出一个整数,代表长度为 n 的、字典序不小于 s 的字符串权值之和
输入样例:
3
RBR
输出:
7
解释:共有 3 个字符串字典序大于等于"RBR"RBR权值为2RRB为2RRR为3
1 <= n <= 100000
结果可能很大对1000000007取模
帖子链接 : https://www.mashibing.com/question/detail/67223
作为项目经理,你规划了一份需求的技能清单 req_skills
并打算从备选人员名单 people 中选出些人组成一个「必要团队」
编号为 i 的备选人员 people[i] 含有一份该备选人员掌握的技能列表
所谓「必要团队」,就是在这个团队中,
对于所需求的技能列表 req_skills 中列出的每项技能,
团队中至少有一名成员已经掌握。可以用每个人的编号来表示团队中的成员:
例如,团队 team = [0, 1, 3] 表示掌握技能分别为
people[0]people[1],和 people[3] 的备选人员。
请你返回 任一 规模最小的必要团队,团队成员用人员编号表示。
你可以按 任意顺序 返回答案,题目数据保证答案存在。
测试链接 : https://leetcode.cn/problems/smallest-sufficient-team/
给定一个整数数组 nums 和一个正整数 k
找出是否有可能把这个数组分成 k 个非空子集,其总和都相等。
测试链接 : https://leetcode.cn/problems/partition-to-k-equal-sum-subsets/
给你一个整数 n 和一个在范围 [0, n - 1] 以内的整数 p
它们表示一个长度为 n 且下标从 0 开始的数组 arr
数组中除了下标为 p 处是 1 以外,其他所有数都是 0 。
同时给你一个整数数组 banned ,它包含数组中的一些位置。
banned 中第 i 个位置表示 arr[banned[i]] = 0 ,题目保证 banned[i] != p 。
你可以对 arr 进行 若干次 操作。一次操作中,你选择大小为 k 的一个 子数组
并将它 翻转 。在任何一次翻转操作后,
你都需要确保 arr 中唯一的 1 不会到达任何 banned 中的位置。
换句话说arr[banned[i]] 始终 保持 0 。
请你返回一个数组 ans ,对于 [0, n - 1] 之间的任意下标 i
ans[i] 是将 1 放到位置 i 处的 最少 翻转操作次数,
如果无法放到位置 i 处,此数为 -1 。
子数组 指的是一个数组里一段连续 非空 的元素序列。
对于所有的 i ans[i] 相互之间独立计算。
将一个数组中的元素 翻转 指的是将数组中的值变成 相反顺序 。
测试链接 : https://leetcode.cn/problems/minimum-reverse-operations/

Loading…
Cancel
Save