From 1a4b3862a2b384b88fcddfea8de5f1c6a179e53e Mon Sep 17 00:00:00 2001 From: algorithmzuo Date: Fri, 21 Apr 2023 17:02:10 +0800 Subject: [PATCH] modify code --- ..._ReplaceTheSubstringForBalancedString.java | 67 ++++++++++ .../Code02_NumberOfSubsetGcdEqualK.java | 65 ++++++++++ ...de03_LongestNoDecreaseModifyKSubarray.java | 117 ++++++++++++++++++ ...养的大厂算法面试题(正在直播) | 34 ++++- 4 files changed, 279 insertions(+), 4 deletions(-) create mode 100644 算法周更班/class_2023_04_3_week/Code01_ReplaceTheSubstringForBalancedString.java create mode 100644 算法周更班/class_2023_04_3_week/Code02_NumberOfSubsetGcdEqualK.java create mode 100644 算法周更班/class_2023_04_3_week/Code03_LongestNoDecreaseModifyKSubarray.java diff --git a/算法周更班/class_2023_04_3_week/Code01_ReplaceTheSubstringForBalancedString.java b/算法周更班/class_2023_04_3_week/Code01_ReplaceTheSubstringForBalancedString.java new file mode 100644 index 0000000..9bec192 --- /dev/null +++ b/算法周更班/class_2023_04_3_week/Code01_ReplaceTheSubstringForBalancedString.java @@ -0,0 +1,67 @@ +package class_2023_04_3_week; + +// 来自华为OD +// 完美走位问题 +// 给定一个由'W'、'A'、'S'、'D'四种字符组成的字符串,长度一定是4的倍数 +// 你可以把任意连续的一段子串,变成'W'、'A'、'S'、'D'组成的随意状态 +// 目的是让4种字符词频一样 +// 返回需要修改的最短子串长度 +// 找到了出处,是leetcode原题 +// 测试链接 : https://leetcode.cn/problems/replace-the-substring-for-balanced-string/ +public class Code01_ReplaceTheSubstringForBalancedString { + + // Q W E R + // 0 1 2 3 + public static int balancedString(String str) { + int n = str.length(); + int[] arr = new int[n]; + int[] cnts = new int[4]; + for (int i = 0; i < n; i++) { + char c = str.charAt(i); + arr[i] = c == 'W' ? 1 : (c == 'E' ? 2 : (c == 'R' ? 3 : 0)); + cnts[arr[i]]++; + } + int ans = n; + // L = 0...... + // 1..... + // 2....r + // 3...... + for (int l = 0, r = 0; l < n; l++) { + // !ok(cnts, l, r) , 当前窗口[l....r),如果不能让四种字符一样多! + // && r < n,虽然没达标,但是还有努力空间 + while (!ok(cnts, l, r) && r < n) { + cnts[arr[r++]]--; + } + // 1) ok了 + // 2) 依然不ok,而且也没努力空间了 + if (ok(cnts, l, r)) { + ans = Math.min(ans, r - l); + } else { + break; + } + cnts[arr[l]]++; + } + return ans; + } + + // 窗口,str[l.....r),你可以自由变化,但是窗口外的不能变化 + // l = 3, r = 10 + // [3....9] + // 窗口长度 = r - l + // cnts,窗口之外每一种字符的词频统计,不能算窗口内的统计的! + // w : cnts[0] + // a : cnts[1] + // s : cnts[2] + // d : cnts[3] + // cnts只有4长度 + public static boolean ok(int[] cnts, int l, int r) { + // 窗口外最大词频是多少 + int maxCnt = Math.max(Math.max(cnts[0], cnts[1]), Math.max(cnts[2], cnts[3])); + // 需要多少空间,拉平?changes + // maxCnt - cnts[0] + maxCnt - cnts[1] maxCnt - cnts[2] maxCnt - cnts[3] + int changes = maxCnt * 4 - cnts[0] - cnts[1] - cnts[2] - cnts[3]; + int rest = r - l - changes; + return rest >= 0 && rest % 4 == 0; + } + +} diff --git a/算法周更班/class_2023_04_3_week/Code02_NumberOfSubsetGcdEqualK.java b/算法周更班/class_2023_04_3_week/Code02_NumberOfSubsetGcdEqualK.java new file mode 100644 index 0000000..730a2e6 --- /dev/null +++ b/算法周更班/class_2023_04_3_week/Code02_NumberOfSubsetGcdEqualK.java @@ -0,0 +1,65 @@ +package class_2023_04_3_week; + +// 来自腾讯笔试 +// 给定一个长度为N的正数数组,还有一个正数K +// 返回有多少子序列的最大公约数为K +// 结果可能很大,对1000000007取模 +// 原题目简单转化就是如下的题目 +// 测试链接 : https://www.luogu.com.cn/problem/CF803F +// 所以课上会讲怎么转化,然后就是讲测试链接里的题目 +// 1 <= N <= 10^5 +// 1 <= arr[i] <= 10^5 +// 请同学们务必参考如下代码中关于输入、输出的处理 +// 这是输入输出处理效率很高的写法 +// 提交以下的所有代码,并把主类名改成"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 Code02_NumberOfSubsetGcdEqualK { + + public static int MAXN = 100001; + + public static int mod = 1000000007; + + public static long[] dp = new long[MAXN]; + + public static long[] cnt = new long[MAXN]; + + public static long[] pow2 = new long[MAXN]; + + public static int n, v; + + 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) { + n = (int) in.nval; + pow2[0] = 1; + for (int i = 1; i <= n; i++) { + in.nextToken(); + v = (int) in.nval; + cnt[v]++; + pow2[i] = (pow2[i - 1] * 2) % mod; + } + for (int i = MAXN - 1; i >= 1; i--) { + long counts = 0; + for (int j = i; j < MAXN; j += i) { + counts = (counts + cnt[j]) % mod; + } + dp[i] = (pow2[(int) counts] - 1 + mod) % mod; + for (int j = 2 * i; j < MAXN; j += i) { + dp[i] = (dp[i] - dp[j] + mod) % mod; + } + } + out.println(dp[1]); + out.flush(); + } + } + +} \ No newline at end of file diff --git a/算法周更班/class_2023_04_3_week/Code03_LongestNoDecreaseModifyKSubarray.java b/算法周更班/class_2023_04_3_week/Code03_LongestNoDecreaseModifyKSubarray.java new file mode 100644 index 0000000..ce24662 --- /dev/null +++ b/算法周更班/class_2023_04_3_week/Code03_LongestNoDecreaseModifyKSubarray.java @@ -0,0 +1,117 @@ +package class_2023_04_3_week; + +// 来自学员问题,蓝桥杯练习题 +// 给定一个长度为n的数组arr +// 现在你有一次机会, 将其中连续的K个数全修改成任意一个值 +// 请你计算如何修改可以使修改后的数 列的最长不下降子序列最长 +// 请输出这个最长的长度。 +// 最长不下降子序列:子序列中的每个数不小于在它之前的数 +// 1 <= k, n <= 10^5 +// 1 <= arr[i] <= 10^6 +// 测试链接 : https://www.luogu.com.cn/problem/P8776 +// 请同学们务必参考如下代码中关于输入、输出的处理 +// 这是输入输出处理效率很高的写法 +// 提交以下的所有代码,并把主类名改成"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 Code03_LongestNoDecreaseModifyKSubarray { + + public static int MAXN = 100001; + + public static int[] arr = new int[MAXN]; + + public static int[] right = new int[MAXN]; + + public static int[] ends = new int[MAXN]; + + public static int n, k; + + 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) { + n = (int) in.nval; + in.nextToken(); + k = (int) (in.nval); + for (int i = 1; i <= n; i++) { + in.nextToken(); + arr[i] = (int) in.nval; + } + if (k >= n) { + out.println(n); + } else { + right(); + out.println(getAns()); + } + out.flush(); + } + } + + public static void right() { + right[n] = 1; + ends[1] = arr[n]; + int len = 1; + for (int i = n - 1; i > 0; i--) { + int l = 1; + int r = len; + int m, find = len + 1; + while (l <= r) { + m = (l + r) / 2; + if (ends[m] < arr[i]) { + find = m; + r = m - 1; + } else { + l = m + 1; + } + } + ends[find] = arr[i]; + len = Math.max(len, find); + right[i] = find; + } + } + + public static int getAns() { + int ans = 0; + int len = 0; + for (int i = k + 1, j = 1; i <= n; i++, j++) { + int l = 1; + int r = len; + int m, find = len + 1; + while (l <= r) { + m = (l + r) / 2; + // 当前的arr[i], 利用之前的ends,求左边长度! + if (ends[m] > arr[i]) { + find = m; + r = m - 1; + } else { + l = m + 1; + } + } + ans = Math.max(ans, find + right[i] - 1 + k); + l = 1; + r = len; + find = len + 1; + while (l <= r) { + m = (l + r) / 2; + if (ends[m] > arr[j]) { + find = m; + r = m - 1; + } else { + l = m + 1; + } + } + len = Math.max(len, find); + ends[find] = arr[j]; + } + ans = Math.max(ans, len + k); + return ans; + } + +} \ No newline at end of file diff --git a/算法课堂笔记/课堂内容汇总/每周有营养的大厂算法面试题(正在直播) b/算法课堂笔记/课堂内容汇总/每周有营养的大厂算法面试题(正在直播) index e77c105..430b222 100644 --- a/算法课堂笔记/课堂内容汇总/每周有营养的大厂算法面试题(正在直播) +++ b/算法课堂笔记/课堂内容汇总/每周有营养的大厂算法面试题(正在直播) @@ -3439,11 +3439,37 @@ subtexti == subtextk - i + 1 表示所有 i 的有效值( 即 1 <= i <= k ) +第066节 2023年4月第3周流行算法题目解析 + +来自华为OD +完美走位问题 +给定一个由'W'、'A'、'S'、'D'四种字符组成的字符串,长度一定是4的倍数 +你可以把任意连续的一段子串,变成'W'、'A'、'S'、'D'组成的随意状态 +目的是让4种字符词频一样 +返回需要修改的最短子串长度 +找到了出处,是leetcode原题 +测试链接 : https://leetcode.cn/problems/replace-the-substring-for-balanced-string/ + +来自腾讯笔试 +给定一个长度为N的正数数组,还有一个正数K +返回有多少子序列的最大公约数为K +结果可能很大,对1000000007取模 +原题目简单转化就是如下的题目 +测试链接 : https://www.luogu.com.cn/problem/CF803F +所以课上会讲怎么转化,然后就是讲测试链接里的题目 +1 <= N <= 10^5 +1 <= arr[i] <= 10^5 - - - - +(上课时网络卡顿,将在下节课安排重讲) +来自学员问题,蓝桥杯练习题 +给定一个长度为n的数组arr +现在你有一次机会, 将其中连续的K个数全修改成任意一个值 +请你计算如何修改可以使修改后的数 列的最长不下降子序列最长 +请输出这个最长的长度。 +最长不下降子序列:子序列中的每个数不小于在它之前的数 +1 <= k, n <= 10^5 +1 <= arr[i] <= 10^6 +测试链接 : https://www.luogu.com.cn/problem/P8776