modify code

master
algorithmzuo 3 years ago
parent 1a20fedcb6
commit 4c8cafa760

@ -0,0 +1,36 @@
package class_2023_02_1_week;
import java.util.TreeSet;
// 给你一个由 n 个正整数组成的数组 nums
// 你可以对数组的任意元素执行任意次数的两类操作
// 如果元素是 偶数 ,除以 2
// 例如,如果数组是 [1,2,3,4]
// 那么你可以对最后一个元素执行此操作使其变成 [1,2,3,2]
// 如果元素是 奇数 ,乘上 2
// 例如,如果数组是 [1,2,3,4] ,那么你可以对第一个元素执行此操作,使其变成 [2,2,3,4]
// 数组的 偏移量 是数组中任意两个元素之间的 最大差值
// 返回数组在执行某些操作之后可以拥有的 最小偏移量
// 测试链接 : https://leetcode.cn/problems/minimize-deviation-in-array/
public class Code01_MinimizeDeviationInArray {
public int minimumDeviation(int[] nums) {
// 有序表,小 -> 大 组织
// 最大 set.last()
TreeSet<Integer> set = new TreeSet<>();
for (int num : nums) {
set.add(num % 2 == 0 ? num : num * 2);
}
// 答案
int ans = set.last() - set.first();
while (ans > 0 && set.last() % 2 == 0) {
// 最大值
int max = set.last();
set.remove(max);
set.add(max / 2);
ans = Math.min(ans, set.last() - set.first());
}
return ans;
}
}

@ -0,0 +1,61 @@
package class_2023_02_1_week;
import java.util.TreeMap;
// 给定一个整数数组 A你可以从某一起始索引出发跳跃一定次数
// 在你跳跃的过程中,第 1、3、5... 次跳跃称为奇数跳跃
// 而第 2、4、6... 次跳跃称为偶数跳跃
// 你可以按以下方式从索引 i 向后跳转到索引 j其中 i < j
// 在进行奇数跳跃时(如,第 135... 次跳跃),你将会跳到索引 j
// 使得 A[i] <= A[j]A[j] 是可能的最小值。如果存在多个这样的索引 j
// 你只能跳到满足要求的最小索引 j 上。
// 在进行偶数跳跃时(如,第 246... 次跳跃)
// 你将会跳到索引 j使得 A[i] >= A[j]A[j] 是可能的最大值
// 如果存在多个这样的索引 j你只能跳到满足要求的最小索引 j 上。
//(对于某些索引 i可能无法进行合乎要求的跳跃。
// 如果从某一索引开始跳跃一定次数(可能是 0 次或多次)
// 就可以到达数组的末尾(索引 A.length - 1
// 那么该索引就会被认为是好的起始索引
// 返回好的起始索引的数量
// 测试链接 : https://leetcode.cn/problems/odd-even-jump/
public class Code02_OddEvenJump {
public static int oddEvenJumps(int[] arr) {
int n = arr.length;
// 来到了i位置如果要遵循奇数规则应该去哪odd[i]
int[] odd = new int[n];
// 来到了i位置如果要遵循偶数规则应该去哪even[i]
int[] even = new int[n];
// 有序表,
// key : 某个值
// value : key这个值出现的最左位置
// >= key 且最小
// <= key 且最大
TreeMap<Integer, Integer> orderMap = new TreeMap<>();
for (int i = n - 1; i >= 0; i--) {
// i位置arr[i],奇数规则,>= arr[i]且最小的!
Integer to = orderMap.ceilingKey(arr[i]);
odd[i] = to == null ? -1 : orderMap.get(to);
// i位置arr[i],偶数规则,<= arr[i]且最大的!
to = orderMap.floorKey(arr[i]);
even[i] = to == null ? -1 : orderMap.get(to);
orderMap.put(arr[i], i);
}
// dp[i][0] : 当来到i位置且在奇数规则下最终能不能到结尾
// dp[i][1] : 当来到i位置且在偶数规则下最终能不能到结尾
boolean[][] dp = new boolean[n][2];
dp[n - 1][0] = true;
dp[n - 1][1] = true;
int ans = 1;
for (int i = n - 2; i >= 0; i--) {
// dp[i][0] : 当来到i位置且在奇数规则下最终能不能到结尾
// odd[i] -> 右走! -1
dp[i][0] = odd[i] != -1 && dp[odd[i]][1];
// dp[i][1] : 当来到i位置且在偶数规则下最终能不能到结尾
dp[i][1] = even[i] != -1 && dp[even[i]][0];
ans += dp[i][0] ? 1 : 0;
}
return ans;
}
}

@ -0,0 +1,38 @@
package class_2023_02_1_week;
// 给定一个二进制数组 nums 和一个整数 k
// k位翻转 就是从 nums 中选择一个长度为 k 的 子数组
// 同时把子数组中的每一个 0 都改成 1 ,把子数组中的每一个 1 都改成 0
// 返回数组中不存在 0 所需的最小 k位翻转 次数。如果不可能,则返回 -1
// 子数组 是数组的 连续 部分。
// 测试链接 : https://leetcode.cn/problems/minimum-number-of-k-consecutive-bit-flips/
public class Code03_MinimumNumberOfKConsecutiveBitFlips {
public int minKBitFlips(int[] nums, int k) {
int n = nums.length;
int[] queue = new int[n];
int l = 0;
int r = 0;
int ans = 0;
for (int i = 0; i < n; i++) {
// 双端队列有东西l、r l i
if (l != r && i - queue[l] == k) {
// 意味着,双端队列大小变了!
l++;
}
// r - l 是双端队列的大小
// (r - l) & 1 == 1
// 说明队列大小是奇数(尾部状态为0)那么nums[i] == 1该加入(因为和尾部不同)
// (r - l) & 1 == 0
// 说明队列大小是偶数(尾部状态为1)那么nums[i] == 0该加入(因为和尾部不同)
// 所以综上,((r - l) & 1) == nums[i],该加入
if (((r - l) & 1) == nums[i]) {
queue[r++] = i;
ans++;
}
}
// 最后的反转点长度够k能翻转否则不能
return (l != r && queue[r - 1] + k > n) ? -1 : ans;
}
}

@ -0,0 +1,116 @@
package class_2023_02_1_week;
// 一共有 4 种硬币。面值分别为c1、c2、c3、c4
// 一开始就给定了,就是这些面值不再改变
// 某人去商店买东西,去了 n 次,
// 每次都是一次查询:
// 这个人每次代的每种硬币的数量不一样都记录在d数组中
// 1) d[i]表示他带了的i种面值的数量
// 2) 他要购买s价值的东西
// 返回每次有多少种购买方法
// 1 <= c1、c2、c3、c4、d[i]、s <= 10^5
// 1 <= n <= 1000
// 测试链接 : https://www.luogu.com.cn/problem/P1450
// 请同学们务必参考如下代码中关于输入、输出的处理
// 这是输入输出处理效率很高的写法
// 提交以下的code提交时请把类名改成"Main"
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Code04_FourKindsPaperQueryWays {
public static int limit = 100000;
// 无限制情况下的方法数得到dp
// 可以用这个dp去求解2元 交上 3元的违规方法
public static long[] dp = new long[limit + 1];
public static int[] c = new int[4];
public static int[] d = new int[4];
public static int n, s;
public static void init() {
dp[0] = 1;
for (int i = 0; i <= 3; i++) {
for (int j = c[i]; j <= limit; j++) {
dp[j] += dp[j - c[i]];
}
}
}
public static long query() {
// 违规方法数!
long minus = 0;
// d c b a
// 0 0 0 1
// 0 1 1 0
for (int status = 1; status <= 15; status++) {
// 100元2元 4张 3元 9张
// 100 - 2 * 5 - 3 * 10 => 60
// 60元无限制的情况下方法数是多少
// 就是100元在2元面值和3元面值同时违规的情况下违规方法数
long t = s;
int sign = -1;
for (int j = 0; j <= 3; j++) {
// j 0号货币有没有
// 1号货币有没有
// 2号货币有没有
// 3号货币有没有
if (((status >> j) & 1) == 1) {
t -= c[j] * (d[j] + 1);
sign = -sign;
}
}
if (t >= 0) {
minus += dp[(int) t] * sign;
}
}
return dp[s] - minus;
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer in = new StreamTokenizer(br);
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
while (in.nextToken() != StreamTokenizer.TT_EOF) {
// 先给每一种面值
// 存好,可能有多组查询,但是有哪些面值是不变的
// 面值的种数也不变4种面值
c[0] = (int) in.nval;
in.nextToken();
c[1] = (int) in.nval;
in.nextToken();
c[2] = (int) in.nval;
in.nextToken();
c[3] = (int) in.nval;
in.nextToken();
// 有多少组查询
n = (int) in.nval;
init();
for (int i = 0; i < n; i++) {
// 一组查询
// a 面值 给你多少张
// b 面值 给你多少张
// c 面值 给你多少张
// d 面值 给你多少张
in.nextToken();
d[0] = (int) in.nval;
in.nextToken();
d[1] = (int) in.nval;
in.nextToken();
d[2] = (int) in.nval;
in.nextToken();
d[3] = (int) in.nval;
in.nextToken();
// 花钱总数
// 不超过10的5次方的
s = (int) in.nval;
out.println(query());
out.flush();
}
}
}
}

@ -2860,13 +2860,54 @@ int pop() 删除并返回堆栈中出现频率最高的元素。
第056节 2023年2月第1周流行算法题目解析
给你一个由 n 个正整数组成的数组 nums
你可以对数组的任意元素执行任意次数的两类操作
如果元素是 偶数 ,除以 2
例如,如果数组是 [1,2,3,4]
那么你可以对最后一个元素执行此操作使其变成 [1,2,3,2]
如果元素是 奇数 ,乘上 2
例如,如果数组是 [1,2,3,4] ,那么你可以对第一个元素执行此操作,使其变成 [2,2,3,4]
数组的 偏移量 是数组中任意两个元素之间的 最大差值
返回数组在执行某些操作之后可以拥有的 最小偏移量
测试链接 : https://leetcode.cn/problems/minimize-deviation-in-array/
给定一个整数数组 A你可以从某一起始索引出发跳跃一定次数
在你跳跃的过程中,第 1、3、5... 次跳跃称为奇数跳跃
而第 2、4、6... 次跳跃称为偶数跳跃
你可以按以下方式从索引 i 向后跳转到索引 j其中 i < j
在进行奇数跳跃时(如,第 135... 次跳跃),你将会跳到索引 j
使得 A[i] <= A[j]A[j] 是可能的最小值。如果存在多个这样的索引 j
你只能跳到满足要求的最小索引 j 上。
在进行偶数跳跃时(如,第 246... 次跳跃)
你将会跳到索引 j使得 A[i] >= A[j]A[j] 是可能的最大值
如果存在多个这样的索引 j你只能跳到满足要求的最小索引 j 上。
对于某些索引 i可能无法进行合乎要求的跳跃
如果从某一索引开始跳跃一定次数(可能是 0 次或多次)
就可以到达数组的末尾(索引 A.length - 1
那么该索引就会被认为是好的起始索引
返回好的起始索引的数量
测试链接 : https://leetcode.cn/problems/odd-even-jump/
给定一个二进制数组 nums 和一个整数 k
k位翻转 就是从 nums 中选择一个长度为 k 的 子数组
同时把子数组中的每一个 0 都改成 1 ,把子数组中的每一个 1 都改成 0
返回数组中不存在 0 所需的最小 k位翻转 次数。如果不可能,则返回 -1
子数组 是数组的 连续 部分。
测试链接 : https://leetcode.cn/problems/minimum-number-of-k-consecutive-bit-flips/
一共有 4 种硬币。面值分别为c1、c2、c3、c4
一开始就给定了,就是这些面值不再改变
某人去商店买东西,去了 n 次,
每次都是一次查询:
这个人每次代的每种硬币的数量不一样都记录在d数组中
1) d[i]表示他带了的i种面值的数量
2) 他要购买s价值的东西
返回每次有多少种购买方法
1 <= c1、c2、c3、c4、d[i]、s <= 10^5
1 <= n <= 1000
测试链接 : https://www.luogu.com.cn/problem/P1450

Loading…
Cancel
Save