From 2cfc6687bfd066da9e1c3983fdd9f1baf6050046 Mon Sep 17 00:00:00 2001 From: whai Date: Fri, 29 Mar 2024 17:00:18 +0800 Subject: [PATCH] =?UTF-8?q?=E5=89=8D=E7=BC=80=E5=92=8C=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E9=A2=98=E7=9B=AE=202602=20462=20453=20=E6=90=BA=E7=A8=8B?= =?UTF-8?q?=E7=AC=94=E8=AF=95=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../whaifree/interview/XieChen/Xie3_13.java | 195 ++++++++++++++++++ .../cn/whaifree/interview/XieChen/xc328.java | 163 +++++++++++++++ .../whaifree/leetCode/Array/LeetCode209.java | 40 +++- .../whaifree/leetCode/Array/LeetCode2602.java | 164 +++++++++++++++ .../whaifree/leetCode/Array/LeetCode453.java | 64 ++++++ .../whaifree/leetCode/Array/LeetCode462.java | 50 +++++ .../leetCode/Dynamic/LeetCode139.java | 22 ++ .../leetCode/Dynamic/LeetCode279.java | 58 ++++++ 8 files changed, 755 insertions(+), 1 deletion(-) create mode 100644 src/main/java/cn/whaifree/interview/XieChen/Xie3_13.java create mode 100644 src/main/java/cn/whaifree/interview/XieChen/xc328.java create mode 100644 src/main/java/cn/whaifree/leetCode/Array/LeetCode2602.java create mode 100644 src/main/java/cn/whaifree/leetCode/Array/LeetCode453.java create mode 100644 src/main/java/cn/whaifree/leetCode/Array/LeetCode462.java create mode 100644 src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode139.java create mode 100644 src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode279.java diff --git a/src/main/java/cn/whaifree/interview/XieChen/Xie3_13.java b/src/main/java/cn/whaifree/interview/XieChen/Xie3_13.java new file mode 100644 index 0000000..1d8a4cc --- /dev/null +++ b/src/main/java/cn/whaifree/interview/XieChen/Xie3_13.java @@ -0,0 +1,195 @@ +package cn.whaifree.interview.XieChen; + +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/28 13:27 + * @注释 + */ +public class Xie3_13 { + + + static class Problem_1 { + + // 游游拿到了一个字符串,她想重排这个字符串后,使得该字符串包含尽可能多的"you"连续子串。你能帮帮她吗? + public static void main(String[] args) { + // 可以随意重排序 + // 输入数据 1 + // yyoouuuu + // 输出数据 1 + // uyouyouu + + Scanner scanner = new Scanner(System.in); + String s = scanner.next(); + + char[] chars = s.toCharArray(); + + int[] map = new int[26]; + + // 统计次数 + for (char aChar : chars) { + map[aChar - 'a'] += 1; + } + + int minLength = Math.min(map['y' - 'a'], Math.min(map['o' - 'a'], map['u' - 'a'])); + map['y' - 'a'] -= minLength; + map['o' - 'a'] -= minLength; + map['u' - 'a'] -= minLength; + + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < map.length; i++) { + for (int j = 0; j < map[i]; j++) { + stringBuilder.append((char)('a' + i)); + } + } + for (int i = 0; i < minLength; i++) { + stringBuilder.append("you"); + } + + System.out.println(stringBuilder.toString()); + + } + + + } + + static class Problem_2{ + + public static void main1(String[] args) { + // 游游拿到了一个数组,她每次操作可以任选一个元素加 1或者减 1。 + // 游游想知道,将所有元素都变成和ai相等需要操作最少多少次?你需要回答ie[1,n]的结果。 + + Scanner scanner = new Scanner(System.in); + int n = scanner.nextInt(); + int[] nums = new int[n]; + for (int i = 0; i < n; i++) { + nums[i] = scanner.nextInt(); + } + for (int num : nums) { + computeTime(nums, num); + } + + } + + public static void computeTime(int[] nums, int target) { + int res = 0; + for (int num : nums) { + res += Math.abs(num - target); + } + System.out.println(res); + } + + /** + * 如果 要求同时+1 -1 + * @param args + */ + public static void main(String[] args) { + // 游游拿到了一个数组,她每次操作可以任选一个元素加 1或者减 1。 + // 游游想知道,将所有元素都变成和ai相等需要操作最少多少次?你需要回答ie[1,n]的结果。 + + Scanner scanner = new Scanner(System.in); + int n = scanner.nextInt(); + int[] nums = new int[n]; + for (int i = 0; i < n; i++) { + nums[i] = scanner.nextInt(); + } + // 先排序, + Arrays.sort(nums); + // 对于nums内的元素,遍历target + // 左边 部分+1,右边部分-1,直到左边活着右边全部=target时,就能知道次数,检查还有多少个达不到target的 + for (int i = 0; i < nums.length; i++) { + change(nums, i); + } + } + + /** + * @param ints + * @param index 中间的位置 + */ + public static void change(int[] ints, int index) { + // 例如 1 2 3 4 5 选取target 为3 + + // 统计左右距离ints[index]的数量 + int leftSub = 0; + for (int i = 0; i < index; i++) { + leftSub += ints[index] - ints[i]; + } + int rightSub = 0; + for (int i = index + 1; i < ints.length; i++) { + rightSub += ints[i] - ints[index]; + } + System.out.println(rightSub + leftSub); + + } + + } + + static class Problem_3{ + + public static void main1(String[] args) { + String input = "[1(1),2(2),-3(31),3(2222222222222222),2(12)]"; + Pattern pattern = Pattern.compile("(-?\\d+)\\((-?\\d+)\\)"); + + Matcher matcher = pattern.matcher(input); + while (matcher.find()) { + String beforeBracket = matcher.group(1); + String insideBracket = matcher.group(2); + System.out.println("括号前的数字: " + beforeBracket + ", 括号内部的数字: " + insideBracket); + } + } + + + public static void main(String[] args) { + + Scanner scanner = new Scanner(System.in); + String s = scanner.next(); + List list = new ArrayList<>(); + // 正则表达式 获取s + // ()左右括号 + // -?表示可选符号,0或1此-号 + // \d 为十进制数字 + // \d+ 表示\d可以出现1次或多次 + // \\ 为\的转义 + // \\( 和 \\) 要匹配字面意义上的左括号和右括号 + Pattern pattern = Pattern.compile("(-?\\d+)\\((-?\\d+)\\)"); + Matcher matcher = pattern.matcher(s); + + while (matcher.find()) { + String beforeBracket = matcher.group(1); // 返回给定组在上一个匹配操作期间捕获的输入子序列。 + String insideBracket = matcher.group(2); + list.add(new long[]{Long.parseLong(beforeBracket),Long.parseLong(insideBracket)}); + } + compact(list); + } + + public static void compact(List list) { + for (int i = 1; i < list.size(); i++) { + if (list.get(i)[0] == list.get(i - 1)[0]) { + list.set(i, new long[]{i, list.get(i)[1] + list.get(i - 1)[1]}); + list.remove(i - 1); + } + } + + List res = new ArrayList<>(); + for (long[] ints : list) { + StringBuilder s1 = new StringBuilder(); + s1.append(ints[0]).append("(").append(ints[1]).append(")"); + res.add(s1.toString()); + } + System.out.println(res.toString()); + } + + } + + + + class Problem_4{ + + } + +} + diff --git a/src/main/java/cn/whaifree/interview/XieChen/xc328.java b/src/main/java/cn/whaifree/interview/XieChen/xc328.java new file mode 100644 index 0000000..86519f8 --- /dev/null +++ b/src/main/java/cn/whaifree/interview/XieChen/xc328.java @@ -0,0 +1,163 @@ +package cn.whaifree.interview.XieChen; + +import java.util.Arrays; +import java.util.Scanner; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/28 19:15 + * @注释 + */ +public class xc328 { + + static class p1{ + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + int n = scanner.nextInt(); + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < n; i++) { + if (i % 2 == 0) { + stringBuilder.append("you"); + }else { + stringBuilder.append("uoy"); + } + } + System.out.println(stringBuilder.toString()); + + } + } + + static class p2{ + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + int n = in.nextInt(); + int m = in.nextInt(); + int[][] ints = new int[n][m]; + for (int i = 0; i < n; i++) { + String[] split = in.next().split(""); + for (int j = 0; j < m; j++) { + ints[i][j] = Integer.parseInt(split[j]); + } + } + + // 00 变11 + // 11 不变 + // 10 向下走1 + // 01 变11 + int res = 0; + for (int i = 0; i < ints.length; i++) { + for (int j = 0; j < m - 1; j++) { + int i1 = ints[i][j]; + int i2 = ints[i][j + 1]; + if (i1 == 0 && i2 == 0) { + ints[i][j] = 1; + ints[i][j + 1] = 1; + res++; + } else if (i1 == 0 && i2 == 1) { + ints[i][j] = 1; + res++; + } else if (i1 == 1 && i2 == 0 && j == m - 2) { + ints[i][j] = 1; + res++; + } + } + } + System.out.println(res); + } + } + + + + static class p3{ + + public static void t(int[] nums) { + + + } + + // 将偶数的区间/2 让整个区间最大 + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + int n = in.nextInt(); + long[] nums = new long[n]; + for (int i = 0; i < n; i++) { + nums[i] = in.nextLong(); + } + // 获取前缀和 + long[] preSum = new long[n + 1]; + for (int i = 1; i < n + 1; i++) { + preSum[i] = preSum[i - 1] + nums[i - 1]; + } + + + long nowSum = 0; + long minSum = Integer.MAX_VALUE; + // 滑动窗口,让窗口内的值都为偶数,并且是总和最小的窗口 + + for (int i = 0; i < nums.length; i++) { + for (int j = i; j < nums.length; j++) { + if (Math.abs(nums[j] % 2) == 1) { + break; + } + nowSum += nums[j]; + minSum = Math.min(nowSum, minSum); + } + nowSum = 0; + } + +// while (right < n) { +// if (Math.abs(nums[right] % 2) == 1) { +// right++; +// left = right; +// nowSum = 0; +// continue; +// } +// nowSum += nums[right]; +// while (nowSum > minSum && left < right) { +// nowSum -= nums[left]; +// left++; +// } +// minSum = Math.min(nowSum, minSum); +// right++; +// } + + long sum = 0; + for (long num : nums) { + sum += num; + } + System.out.println(sum - minSum / 2); + } + } + + static class p4{ + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + int n = scanner.nextInt(); + int[] ints = new int[n]; + for (int i = 0; i < n; i++) { + ints[i] = i; + } + + Arrays.sort(ints); + // 1 1*2 1*2*3 1*2*3*4 + + + for (int i = 0; i < ints.length; i++) { + pro(ints[i],i); + } + + } + + // 4 6 8 + public static long pro(long n, long start) { + int res = 1; + for (long i = start; i < n; i++) { + res *= i; + } + return res; + } + } +} diff --git a/src/main/java/cn/whaifree/leetCode/Array/LeetCode209.java b/src/main/java/cn/whaifree/leetCode/Array/LeetCode209.java index 64c8b47..d0cd333 100644 --- a/src/main/java/cn/whaifree/leetCode/Array/LeetCode209.java +++ b/src/main/java/cn/whaifree/leetCode/Array/LeetCode209.java @@ -2,6 +2,8 @@ package cn.whaifree.leetCode.Array; import org.junit.Test; +import java.util.Arrays; + /** * 209. 长度最小的子数组 * 给定一个含有 n 个正整数的数组和一个正整数 target 。 @@ -82,9 +84,45 @@ public class LeetCode209 { } + + class Solution { + /** + * 前缀和做法 + * @param target + * @param nums + * @return + */ + public int minSubArrayLen(int target, int[] nums) { + // 求前缀和 + int length = nums.length; + int[] preSum = new int[length + 1]; + for (int i = 1; i < preSum.length; i++) { + preSum[i] = preSum[i - 1] + nums[i - 1]; + } + // 2,3,1,2,4,3 + // 因为每个元素都是正数,所以preSum是递增的,可以用二分查找 + int minLengthFillSolution = Integer.MAX_VALUE; + for (int i = 1; i < preSum.length; i++) { + // 从0开始查找 + int fill = target + preSum[i - 1]; + int intervalEnd = Arrays.binarySearch(preSum, fill); // 没找到就会返回负数 + if (intervalEnd < 0) { + intervalEnd = -intervalEnd - 1; // 防止查出来的是负数 + } + // 这个区间如果合理,就可能是正常的区间 + if (intervalEnd <= length) + minLengthFillSolution = Math.min(minLengthFillSolution, intervalEnd - (i - 1)); + // 注意区分下标 intervalEnd和i-1 前缀和为fill和target + } + return minLengthFillSolution == Integer.MAX_VALUE ? 0 : minLengthFillSolution; + } + } + @Test public void list() { - System.out.println(minSubArrayLen1(5, new int[]{2,3,6})); + System.out.println(new Solution().minSubArrayLen(7, new int[]{2, 3, 1, 2, 4, 3})); + +// System.out.println(minSubArrayLen1(5, new int[]{2,3,6})); } } diff --git a/src/main/java/cn/whaifree/leetCode/Array/LeetCode2602.java b/src/main/java/cn/whaifree/leetCode/Array/LeetCode2602.java new file mode 100644 index 0000000..6f863f0 --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/Array/LeetCode2602.java @@ -0,0 +1,164 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/28 16:59 + * @注释 + */ +public class LeetCode2602 { + @Test + public void test() + { + Solution solution = new Solution(); + int[] nums = {3,1,6,8}; + int[] queries = {1,5}; + List res = solution.minOperations(nums, queries); + res.forEach(System.out::println); + } + + + /** + * 超时 + */ + class Solution { + public List minOperations(int[] nums, int[] queries) { + List res = new ArrayList<>(); + for (int query : queries) { + res.add(target(nums, query)); + } + return res; + } + + public long target(int[] nums, int target) { + + long res = 0; + for (int num : nums) { + res += Math.abs(target - num); + } + return res; + } + } + + class Solution1 { + public List minOperations(int[] nums, int[] queries) { + List res = new ArrayList<>(); + Arrays.sort(nums); + // 排序后,找到对应的元素,左边小于,右边大于 + // 求前缀和 + int length = nums.length; + long[] preSum = new long[length + 1]; + for (int i = 0; i < length; i++) { + preSum[i + 1] = preSum[i] + nums[i]; + } + + for (int target : queries) { + int index = findIndex(nums, target); + long left = (long) index * target - preSum[index]; + // index 为横坐标 target为纵坐标高度 preSum为index位置前面的总和 + long right = preSum[length] - preSum[index] - (long) target * (length - index); + res.add(left + right); + } + + // 一侧的前缀和与 “平均值*一侧区间长度” 就代表这一侧的总操作数 + + return res; + } + + + public int findIndex(int[] nums, int target) { + int left = 0; + int right = nums.length - 1; + while (left <= right) { + int mid = left + (right - left) / 2; + if (nums[mid] == target) { + return mid; + } else if (nums[mid] > target) { + right = mid - 1; + } else { + left = mid + 1; + } + } + return right; + } + + } + + @Test + public void test1() + { + Solution2 solution2 = new Solution2(); + int[] nums = {3,1,6,8}; + int[] queries = {5}; + List res = solution2.minOperations(nums, queries); + res.forEach(System.out::println); + } + + + class Solution2 { + public List minOperations(int[] nums, int[] queries) { + Arrays.sort(nums); + + // 计算前缀和 + long[] preSum = new long[nums.length + 1]; + for (int i = 1; i < preSum.length; i++) { + preSum[i] = preSum[i - 1] + nums[i - 1]; + } + + List res = new ArrayList<>(); + for (int query : queries) { + res.add(getOperation(nums, query, preSum)); + } + return res; + + } + + /** + * + * + * @param nums 原数组 + * @param target 目标 + * @param preSum 前缀和 + * @return + */ + public Long getOperation(int[] nums, int target,long[] preSum) { + + int index = findIndex(nums, target); + // index左边全部比他小、右边全部比他大 + // 0 - index 为小于他的数字个数 index-length为大于他的个数 + // 小于他的数的总和 = 小于的个数 index * (target-nums[0]) - index位置的前缀和(前缀和就是一个下三角形的面积) + long leftIncr = (long) index * target - preSum[index]; + long rightIncr = + preSum[nums.length] - preSum[index] + - (long) target * (nums.length - index); + + return leftIncr + rightIncr; + } + + /** + * 二分查找 + * @param nums 有序数组 + * @param target + * @return + */ + public int findIndex(int[] nums, int target) { + int left = 0, right = nums.length - 1; + while (left <= right) { + int mid = (right + left) / 2; + if (nums[mid] < target) { + left = mid + 1; + } else { + right = mid - 1; + } + } + return left; + } + + } +} diff --git a/src/main/java/cn/whaifree/leetCode/Array/LeetCode453.java b/src/main/java/cn/whaifree/leetCode/Array/LeetCode453.java new file mode 100644 index 0000000..eeec099 --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/Array/LeetCode453.java @@ -0,0 +1,64 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/29 12:54 + * @注释 + */ +public class LeetCode453 { + @Test + public void test() + { + int[] nums = {1, 1,1}; + int res = new Solution1().minMoves(nums); + System.out.println(res); + } + + class Solution { + /** + * 让n-1个元素加1 等价于让1个元素-1,直到全部元素相等 + * @param nums + * @return + */ + public int minMoves(int[] nums) { + int min = Integer.MAX_VALUE; + for (int num : nums) { + min = Math.min(min, num); + } + int res = 0; + for (int num : nums) { + res += Math.abs(min - num); + } + return res; + } + } + + class Solution1 { + /** + * 让n-1个元素加1 等价于让1个元素-1,直到全部元素相等 + * 前缀和解法 + * @param nums + * @return + */ + public int minMoves(int[] nums) { + + // 获取前缀和 + int length = nums.length; + int[] preSum = new int[length + 1]; + // 找到最小的元素的index + int minIndex = 0; + for (int i = 1; i <= length; i++) { + if (nums[minIndex] > nums[i - 1]) { + minIndex = i - 1; + } + preSum[i] = preSum[i - 1] + nums[i - 1]; + } + + return preSum[length] - nums[minIndex] * length; + } + + } +} diff --git a/src/main/java/cn/whaifree/leetCode/Array/LeetCode462.java b/src/main/java/cn/whaifree/leetCode/Array/LeetCode462.java new file mode 100644 index 0000000..8ccbce0 --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/Array/LeetCode462.java @@ -0,0 +1,50 @@ +package cn.whaifree.leetCode.Array; + +import org.junit.Test; + +import java.util.Arrays; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/29 13:15 + * @注释 + */ +public class LeetCode462 { + + @Test + public void test() + { + Solution solution = new Solution(); + int[] nums = {1,2,3}; + int i = solution.minMoves2(nums); + System.out.println(i); + } + + class Solution { + /** + * +1 或 -1 + * @param nums + * @return + */ + public int minMoves2(int[] nums) { + // 排序后找到中位数 + Arrays.sort(nums); + // 前缀和 + int length = nums.length; + int[] preSum = new int[length + 1]; + for (int i = 1; i < preSum.length; i++) { + preSum[i] = preSum[i - 1] + nums[i - 1]; + } + // 中位数 + int middleIndex = length / 2; + int middleValue = nums[middleIndex]; + + int left = middleIndex * middleValue - preSum[middleIndex]; + int right = preSum[preSum.length - 1] - preSum[middleIndex] - (length - middleIndex) * middleValue; + return left + right; + } + } + + +} diff --git a/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode139.java b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode139.java new file mode 100644 index 0000000..54dcd46 --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode139.java @@ -0,0 +1,22 @@ +package cn.whaifree.leetCode.Dynamic; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/28 13:15 + * @注释 + */ +public class LeetCode139 { + + class Solution { + +// public boolean wordBreak(String s, List wordDict) { +// // wordDict放入s的背包 +// char[] chars = s.toCharArray(); +// +// +// } + + + } +} diff --git a/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode279.java b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode279.java new file mode 100644 index 0000000..039bc63 --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode279.java @@ -0,0 +1,58 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +import java.util.Arrays; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/3/28 11:53 + * @注释 + */ +public class LeetCode279 { + + @Test + public void test(){ + Solution solution = new Solution(); + int numSquares = solution.numSquares(12); + System.out.println(numSquares); + } + + + class Solution { + public int numSquares(int n) { + + // 完全平方数 任意取,使其满足n容量的背包的最少数量 + // 给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 。 + // dp[j] 表示容量为j的背包 最少 需要的 完全平方数 的数量 + + int[] dp = new int[n + 1]; + Arrays.fill(dp, Integer.MAX_VALUE); + + + // 求组合数就是外层for循环遍历物品,内层for遍历背包 + // 求排列数就是外层for遍历背包,内层for循环遍历物品 {1,0} {0,1} + // 本题都可以 + dp[0] = 0; +// for (int j = 0; j <= n; j++) { +// for (int i = 1; i * i <= j; j++) { +// // i-j*j 表示 之前的完全平方数 + 这个挖 +// dp[j] = Math.min(dp[j - i * i] + 1, dp[j]); +// } +// } + + for (int i = 1; i * i <= n; i++) { + for (int j = i * i; j <= n; j++) { + // i-j*j 表示 之前的完全平方数 + 这个挖 + dp[j] = Math.min(dp[j - i * i] + 1, dp[j]); + //dp[j] 可以由dp[j - i * i]推出, dp[j - i * i] + 1 便可以凑成dp[j]。 + // 或者说, dp[j-i*i]表示j-i*i的最小需要平方数,加上我们给到的i*i这一个平方数,就是+1,即dp[j - i * i] + 1 + } + } + + return dp[n]; + } + } + +}