diff --git a/README.md b/README.md index b47c19ac..7f7fa5da 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ | 9 | [Palindrome Number][0009] | Math | | 13 | [Roman to Integer][0013] | Math, String | | 14 | [Longest Common Prefix][0014] | String | +| 16.11| [跳水板(Diving Board LCCI)][16_11] | 递归、记忆化 | | 20 | [Valid Parentheses][0020] | Stack, String | | 21 | [Merge Two Sorted Lists][0021] | Linked List | | 26 | [Remove Duplicates from Sorted Array][0026] | Array, Two Pointers | @@ -85,7 +86,9 @@ | 49 | [Group Anagrams][0049] | Hash Table, String | | 50 | [Pow(x, n)][0050] | Math, Binary Search | | 56 | [Merge Intervals][0056] | Array, Sort | -| 209 | [长度最小的子数组(Minimum Size Subarray Sum)][0209] | Array, Sort | +| 63 | [不同路径 II(Unique Paths II)][0063] | 数组、动态规划 | +| 209 | [长度最小的子数组(Minimum Size Subarray Sum)][0209] | 数组、双指针、二分查找 | +| 215 | [数组中的第K个最大元素(Kth Largest Element in an Array)][0215] | 堆、分治算法 | | 554 | [Brick Wall][0554] | Hash Table | | 1014 | [最佳观光组合(Best Sightseeing Pair)][1014] | 数组 | @@ -105,9 +108,7 @@ ## 打个小广告 -欢迎加入我的知识星球「**[基你太美](https://t.zsxq.com/FmeqfYF)**」,我会在星球中分享 [AucFrame](https://blankj.com/2019/07/22/auc-frame/) 框架、大厂面经、[AndroidUtilCode](https://github.com/Blankj/AndroidUtilCode) 更详尽的说明...一切我所了解的知识,你可以通过支付进入我的星球「**[基你太美](https://t.zsxq.com/FmeqfYF)**」进行体验,加入后优先观看星球中精华的部分,如果觉得星球的内容对自身没有收益,你可以自行申请退款退出星球,也没必要加我好友;**如果你已确定要留在我的星球,可以通过扫描如下二维码(备注:基你太美+你的星球昵称)加我个人微信,方便我后续拉你进群(PS:进得越早价格越便宜)。** - -![我的二维码](https://raw.githubusercontent.com/Blankj/AndroidUtilCode/master/art/wechat.png) +欢迎加入我的小专栏「**[基你太美](https://xiaozhuanlan.com/Blankj)**」一起学习。 [src]: https://github.com/Blankj/awesome-java-leetcode/tree/master/src @@ -119,6 +120,7 @@ [0009]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/0009/README.md [0013]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/0013/README.md [0014]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/0014/README.md +[16_11]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/16_11/README.md [0020]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/0020/README.md [0021]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/0021/README.md [0026]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/0026/README.md @@ -168,15 +170,18 @@ [0049]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/0049/README.md [0050]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/0050/README.md [0056]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/0056/README.md +[0063]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/0063/README.md +[0209]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/0209/README.md +[0215]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/0215/README.md [0554]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/0554/README.md [1014]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/1014/README.md + [0004]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/0004/README.md [0010]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/0010/README.md - [0023]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/0023/README.md [0025]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/0025/README.md [0030]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/0030/README.md [0044]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/0044/README.md [0057]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/0057/README.md [0068]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/0068/README.md -[1028]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/1028/README.md \ No newline at end of file +[1028]: https://github.com/Blankj/awesome-java-leetcode/blob/master/note/1028/README.md diff --git a/note/0063/README.md b/note/0063/README.md new file mode 100644 index 00000000..2905be6f --- /dev/null +++ b/note/0063/README.md @@ -0,0 +1,86 @@ +# [不同路径 II(Unique Paths II)][title] + +## 题目描述 + +一个机器人位于一个 _m x n_ 网格的左上角 (起始点在下图中标记为“Start” )。 + +机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。 + +现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径? + +![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/10/22/robot_maze.png) + +网格中的障碍物和空位置分别用 `1` 和 `0` 来表示。 + +**说明:**_m_ 和 _n_ 的值均不超过 100。 + +**示例 1:** +``` +输入: +[ +  [0,0,0], +  [0,1,0], +  [0,0,0] +] +输出: 2 +解释: +3x3 网格的正中间有一个障碍物。 +从左上角到右下角一共有 2 条不同的路径: +1. 向右 -> 向右 -> 向下 -> 向下 +2. 向下 -> 向下 -> 向右 -> 向右 +``` + +**标签:** 数组、动态规划 + + +## 思路 + +做过爬楼梯的应该很快就能想到这是一道很典型的动态规划题目, + +我们令 `dp[i][j]` 表示走到格子 `(i, j)` 的路径数, + +那么当 `(i, j)` 没障碍物时,`dp[i][j] = 0`; + +那么当 `(i, j)` 有障碍物时,`dp[i][j] = dp[i - 1][j] + dp[i][j - 1]`; + +其初始态第 1 列(行)的格子只有从其上(左)边格子走过去这一种走法,因此初始化 `dp[i][0]`(`dp[0][j]`)值为 1,且遇到障碍物时后面值都为 0; + +有了这些条件,我相信你肯定可以写出代码来了,具体如下所示: + + +```java +class Solution { + public int uniquePathsWithObstacles(int[][] obstacleGrid) { + int m = obstacleGrid.length, n = obstacleGrid[0].length; + int[][] dp = new int[m][n]; + // 其初始态第 1 列(行)的格子只有从其上(左)边格子走过去这一种走法, + // 因此初始化 dp[i][0](dp[0][j])值为 1,且遇到障碍物时后面值都为 0; + for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) { + dp[i][0] = 1; + } + for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++) { + dp[0][j] = 1; + } + + for (int i = 1; i < m; i++) { + for (int j = 1; j < n; j++) { + if (obstacleGrid[i][j] == 0) { + // 当 (i, j) 有障碍物时,dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; + dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; + } + } + } + return dp[m - 1][n - 1]; + } +} +``` + + +## 结语 + +如果你同我一样热爱数据结构、算法、LeetCode,可以关注我 GitHub 上的 LeetCode 题解:[awesome-java-leetcode][ajl] + + + +[title]: https://leetcode-cn.com/problems/unique-paths-ii +[ajl]: https://github.com/Blankj/awesome-java-leetcode diff --git a/note/0209/README.md b/note/0209/README.md index 4c7dedcd..e0984de9 100644 --- a/note/0209/README.md +++ b/note/0209/README.md @@ -2,80 +2,106 @@ ## 题目描述 -我们从二叉树的根节点 `root` 开始进行深度优先搜索。 +给定一个含有 **n** 个正整数的数组和一个正整数 **s** ,找出该数组中满足其和 **≥ s** 的长度最小的连续子数组,并返回其长度。如果不存在符合条件的连续子数组,返回 0。 -在遍历中的每个节点处,我们输出 `D` 条短划线(其中 `D` 是该节点的深度),然后输出该节点的值。(_如果节点的深度为 `D`,则其直接子节点的深度为 `D + 1`。根节点的深度为 `0`)。_ - -如果节点只有一个子节点,那么保证该子节点为左子节点。 - -给出遍历输出 `S`,还原树并返回其根节点 `root`。 - -**示例 1:** - -**![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2019/04/12/recover-a-tree-from-preorder-traversal.png)** +**示例:** ``` -输入:"1-2--3--4-5--6--7" -输出:[1,2,5,3,4,6,7] +输入:s = 7, nums = [2,3,1,2,4,3] +输出:2 +解释:子数组 [4,3] 是该条件下的长度最小的连续子数组。 ``` -**示例 2:** +**进阶:** -**![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2019/04/12/screen-shot-2019-04-10-at-114101-pm.png)** +* 如果你已经完成了 _O_(_n_) 时间复杂度的解法, 请尝试 _O_(_n_ log _n_) 时间复杂度的解法。 -``` -输入:"1-2--3---4-5--6---7" -输出:[1,2,5,3,null,6,null,4,null,7] -``` +**标签:** 数组、双指针、二分查找 -**示例 3:** -![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2019/04/12/screen-shot-2019-04-10-at-114955-pm.png) +## 思路 0 -``` -输入:"1-401--349---90--88" -输出:[1,401,null,349,88,90] +直接暴力法,两重 for 循环,记录最小长度即可,代码很简单,如下所示: + + +```java +class Solution { + public int minSubArrayLen(int s, int[] nums) { + int ans = Integer.MAX_VALUE; + for (int i = 0; i < nums.length; i++) { + int sum = nums[i]; + if (sum >= s) { + return 1; + } + for (int j = i + 1; j < nums.length; j++) { + sum += nums[j]; + if (sum >= s) { + ans = Math.min(ans, j - i + 1); + break; + } + } + } + return ans == Integer.MAX_VALUE ? 0 : ans; + } +} ``` -**提示:** +## 思路 1 -* 原始树中的节点数介于 `1` 和 `1000` 之间。 -* 每个节点的值介于 `1` 和 `10 ^ 9` 之间。 +对上面进行优化,我们通过首位两个指针来模拟滑动窗口,如果加起来值小于 s,则向右扩大窗口直至不小于 s,然后固定窗口右侧来向左缩小窗口,同时更新符合条件的最小窗口长度即可,代码如下所示: -**标签:** 树、深度优先搜索 +```java +class Solution { + public int minSubArrayLen(int s, int[] nums) { + int left = 0, right = 0, sum = 0, ans = Integer.MAX_VALUE; + while (right < nums.length) { + sum += nums[right++]; // 向右扩大窗口 + while (sum >= s) { // 如果不小于 s,则收缩窗口左边界 + ans = Math.min(ans, right - left);// 更新结果 + sum -= nums[left++]; // 向左缩小窗口 + } + } + return ans == Integer.MAX_VALUE ? 0 : ans; + } +} +``` +## 思路 2 -## 思路 +进阶中说了,尝试使用 O(nlogn) 时间复杂度的解法,由于数组都是正整数构成,所以前缀和一定是递增的,想到的应该就是用二分查找了,可以用 sums 数组来存储 nums 数组的前缀和,sums[i] 代表 nums[0] 到 nums[i - 1] 总和,然后遍历 sums 数组,对 sums[i] + s 进行二分查找然后不断更新结果即可,具体代码如下所示: -直接暴力两层 for 循环肯定过不了关,我们把公式变化为 `(A[i] + i) + (A[j] - j)`,看到此应该就可以想到在每次遍历 `j` 时,只需要知道 `max(A[i] + i)` 即可。 ```java class Solution { - - public int maxScoreSightseeingPair(int[] A) { - int ans = 0, cur = A[0] + 0; - for (int j = 1; j < A.length; j++) { - ans = Math.max(ans, cur + A[j] - j); // 计算当前最大得分 - cur = Math.max(cur, A[j] + j); // 更新最大的 A[i] + i + public int minSubArrayLen(int s, int[] nums) { + int ans = Integer.MAX_VALUE; + int[] sums = new int[nums.length + 1]; + for (int i = 0; i < nums.length; i++) { + sums[i + 1] = sums[i] + nums[i]; } - return ans; - } - - public static void main(String[] args) { - Solution solution = new Solution(); - int[] A = new int[]{8, 1, 5, 2, 6}; - System.out.println(solution.maxScoreSightseeingPair(A)); + for (int i = 0; i < nums.length; i++) { + int target = s + sums[i]; // 确定要搜索的目标值 + // Java 二分查找 Arrays.binarySearch 如果找到就会返回该元素的索引; + // 如果没找到就会返回一个负数,这个负数取反之后再减一就是查找的值应该在数组中的位置; + // 例如 [-1, 0, 1, 5] 中二分查找 2,其返回值就是 -4,其 -(-4) - 1 = 3,所以 2 这个元素插入到数组的索引就是 3 + int bound = Arrays.binarySearch(sums, target); + if (bound < 0) { + bound = -bound - 1; + } + if (bound < sums.length) { // 当 bound 确定插入点不在 sums 数组的最后面时,说明不小于 target 的值了 + ans = Math.min(ans, bound - i); + } + } + return ans == Integer.MAX_VALUE ? 0 : ans; } } - ``` - ## 结语 如果你同我一样热爱数据结构、算法、LeetCode,可以关注我 GitHub 上的 LeetCode 题解:[awesome-java-leetcode][ajl] -[title]: https://leetcode-cn.com/problems/recover-a-tree-from-preorder-traversal +[title]: https://leetcode-cn.com/problems/minimum-size-subarray-sum [ajl]: https://github.com/Blankj/awesome-java-leetcode diff --git a/note/1014/README.md b/note/1014/README.md index 34357d6c..fe4a965e 100644 --- a/note/1014/README.md +++ b/note/1014/README.md @@ -46,7 +46,6 @@ class Solution { System.out.println(solution.maxScoreSightseeingPair(A)); } } - ``` diff --git a/note/16_11/README.md b/note/16_11/README.md new file mode 100644 index 00000000..13e6d104 --- /dev/null +++ b/note/16_11/README.md @@ -0,0 +1,68 @@ +# [跳水板(Diving Board LCCI)][title] + +## 题目描述 + +你正在使用一堆木板建造跳水板。有两种类型的木板,其中长度较短的木板长度为`shorter`,长度较长的木板长度为`longer`。你必须正好使用`k`块木板。编写一个方法,生成跳水板所有可能的长度。 + +返回的长度需要从小到大排列。 + +**示例:** + +``` +输入: +shorter = 1 +longer = 2 +k = 3 +输出: {3,4,5,6} +``` + +**提示:** + +* 0 < shorter <= longer +* 0 <= k <= 100000 + +**标签:** 递归、记忆化 + + +## 思路 + +这题乍一看,好像得用递归或动态规划来解,仔细一想,其实就是高中数学学过的等差数列知识。 + +当 `k == 0` 时,返回 `[]` 即可; + +当 `shorter == longer` 时,返回 `[k * shorter]` 即可; + +当 `shorter != longer` 时,那么其实就是一个首项为 `k * shorter`,末项为 `k * longer`,公差为 `longer - shorter` 的等差数列么; + +我们根据以上情况就可以写出如下代码了: + + +```java +public class Solution { + public int[] divingBoard(int shorter, int longer, int k) { + if (k == 0) { + return new int[0]; + } + if (shorter == longer) { + return new int[]{shorter * k}; + } + int[] ans = new int[k + 1]; + int st = k * shorter;// 等差数列的首项 + int delta = longer - shorter;// 公差 + for (int i = 0; i <= k; i++) { + ans[i] = st + i * delta; + } + return ans; + } +} +``` + + +## 结语 + +如果你同我一样热爱数据结构、算法、LeetCode,可以关注我 GitHub 上的 LeetCode 题解:[awesome-java-leetcode][ajl] + + + +[title]: https://leetcode-cn.com/problems/diving-board-lcci +[ajl]: https://github.com/Blankj/awesome-java-leetcode diff --git a/src/com/blankj/easy/_16_11/Solution.java b/src/com/blankj/easy/_16_11/Solution.java new file mode 100644 index 00000000..2e9e7906 --- /dev/null +++ b/src/com/blankj/easy/_16_11/Solution.java @@ -0,0 +1,34 @@ +package com.blankj.easy._16_11; + +import java.util.Arrays; + +/** + *
+ *     author: Blankj
+ *     blog  : http://blankj.com
+ *     time  : 2020/07/08
+ *     desc  :
+ * 
+ */ +public class Solution { + public int[] divingBoard(int shorter, int longer, int k) { + if (k == 0) { + return new int[0]; + } + if (shorter == longer) { + return new int[]{shorter * k}; + } + int[] ans = new int[k + 1]; + int st = k * shorter;// 等差数列的首项 + int delta = longer - shorter;// 公差 + for (int i = 0; i <= k; i++) { + ans[i] = st + i * delta; + } + return ans; + } + + public static void main(String[] args) { + Solution solution = new Solution(); + System.out.println(Arrays.toString(solution.divingBoard(1, 2, 3))); + } +} diff --git a/src/com/blankj/medium/_0057/Solution.java b/src/com/blankj/hard/_0057/Solution.java similarity index 97% rename from src/com/blankj/medium/_0057/Solution.java rename to src/com/blankj/hard/_0057/Solution.java index 8fde4e3a..1e5b4cea 100644 --- a/src/com/blankj/medium/_0057/Solution.java +++ b/src/com/blankj/hard/_0057/Solution.java @@ -1,4 +1,4 @@ -package com.blankj.medium._057; +package com.blankj.hard._0057; import com.blankj.structure.Interval; diff --git a/src/com/blankj/hard/_1028/Solution.java b/src/com/blankj/hard/_1028/Solution.java index 6089220f..da93396b 100644 --- a/src/com/blankj/hard/_1028/Solution.java +++ b/src/com/blankj/hard/_1028/Solution.java @@ -13,6 +13,32 @@ * */ public class Solution { +// public TreeNode recoverFromPreorder(String S) { +// char[] chars = S.toCharArray(); +// int len = chars.length; +// List levels = new LinkedList<>(); +// for (int i = 0; i < len; ) { +// int level = 0, val = 0; +// while (chars[i] == '-') { // 获取所在层级,Character.isDigit() 会比较慢 +// ++i; +// ++level; +// } +// while (i < len && chars[i] != '-') { // 获取节点的值 +// val = val * 10 + chars[i++] - '0'; +// } +// TreeNode curNode = new TreeNode(val); +// if (level > 0) { +// TreeNode parent = levels.get(level - 1); +// if (parent.left == null) { // 如果节点只有一个子节点,那么保证该子节点为左子节点。 +// parent.left = curNode; +// } else { +// parent.right = curNode; +// } +// } +// levels.add(level, curNode); // 因为是前序遍历(根-左-右),也就是右覆盖左时,此时左树已遍历完成,故无需考虑覆盖问题 +// } +// return levels.get(0); +// } public TreeNode recoverFromPreorder(String S) { char[] chars = S.toCharArray(); @@ -44,33 +70,6 @@ public TreeNode recoverFromPreorder(String S) { return stack.get(0); } -// public TreeNode recoverFromPreorder(String S) { -// char[] chars = S.toCharArray(); -// int len = chars.length; -// List levels = new LinkedList<>(); -// for (int i = 0; i < len; ) { -// int level = 0, val = 0; -// while (chars[i] == '-') { // 获取所在层级,Character.isDigit() 会比较慢 -// ++i; -// ++level; -// } -// while (i < len && chars[i] != '-') { // 获取节点的值 -// val = val * 10 + chars[i++] - '0'; -// } -// TreeNode curNode = new TreeNode(val); -// if (level > 0) { -// TreeNode parent = levels.get(level - 1); -// if (parent.left == null) { // 如果节点只有一个子节点,那么保证该子节点为左子节点。 -// parent.left = curNode; -// } else { -// parent.right = curNode; -// } -// } -// levels.add(level, curNode); // 因为是前序遍历(根-左-右),也就是右覆盖左时,此时左树已遍历完成,故无需考虑覆盖问题 -// } -// return levels.get(0); -// } - public static void main(String[] args) { Solution solution = new Solution(); TreeNode.print(solution.recoverFromPreorder("1-2--3--4-5--6--7")); diff --git a/src/com/blankj/medium/_0067/Solution.java b/src/com/blankj/medium/_0067/Solution.java new file mode 100644 index 00000000..aba07bad --- /dev/null +++ b/src/com/blankj/medium/_0067/Solution.java @@ -0,0 +1,40 @@ +package com.blankj.medium._0067; + +/** + *
+ *     author: Blankj
+ *     blog  : http://blankj.com
+ *     time  : 2020/07/07
+ *     desc  :
+ * 
+ */ +public class Solution { + public int uniquePathsWithObstacles(int[][] obstacleGrid) { + int m = obstacleGrid.length, n = obstacleGrid[0].length; + int[][] dp = new int[m][n]; + // 其初始态第 1 列(行)的格子只有从其上(左)边格子走过去这一种走法, + // 因此初始化 dp[i][0](dp[0][j])值为 1,且遇到障碍物时后面值都为 0; + for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) { + dp[i][0] = 1; + } + for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++) { + dp[0][j] = 1; + } + + for (int i = 1; i < m; i++) { + for (int j = 1; j < n; j++) { + if (obstacleGrid[i][j] == 0) { + // 当 (i, j) 有障碍物时,dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; + dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; + } + } + } + return dp[m - 1][n - 1]; + } + + public static void main(String[] args) { + Solution solution = new Solution(); + int[][] obstacleGrid = {{0, 0, 0}, {0, 1, 0}, {0, 0, 0}}; + System.out.println(solution.uniquePathsWithObstacles(obstacleGrid)); + } +} diff --git a/src/com/blankj/medium/_0209/Solution.java b/src/com/blankj/medium/_0209/Solution.java new file mode 100644 index 00000000..cdfedebc --- /dev/null +++ b/src/com/blankj/medium/_0209/Solution.java @@ -0,0 +1,70 @@ +package com.blankj.medium._0209; + +import java.util.Arrays; + +/** + *
+ *     author: Blankj
+ *     blog  : http://blankj.com
+ *     time  : 2020/06/30
+ *     desc  :
+ * 
+ */ +public class Solution { +// public int minSubArrayLen(int s, int[] nums) { +// int ans = Integer.MAX_VALUE; +// for (int i = 0; i < nums.length; i++) { +// int sum = nums[i]; +// if (sum >= s) { +// return 1; +// } +// for (int j = i + 1; j < nums.length; j++) { +// sum += nums[j]; +// if (sum >= s) { +// ans = Math.min(ans, j - i + 1); +// break; +// } +// } +// } +// return ans == Integer.MAX_VALUE ? 0 : ans; +// } + +// public int minSubArrayLen(int s, int[] nums) { +// int left = 0, right = 0, sum = 0, ans = Integer.MAX_VALUE; +// while (right < nums.length) { +// sum += nums[right++]; // 向右扩大窗口 +// while (sum >= s) { // 如果不小于 s,则收缩窗口左边界 +// ans = Math.min(ans, right - left);// 更新结果 +// sum -= nums[left++]; // 向左缩小窗口 +// } +// } +// return ans == Integer.MAX_VALUE ? 0 : ans; +// } + + public int minSubArrayLen(int s, int[] nums) { + int ans = Integer.MAX_VALUE; + int[] sums = new int[nums.length + 1]; + for (int i = 0; i < nums.length; i++) { + sums[i + 1] = sums[i] + nums[i]; + } + for (int i = 0; i < nums.length; i++) { + int target = s + sums[i]; // 确定要搜索的目标值 + // Java 二分查找 Arrays.binarySearch 如果找到就会返回该元素的索引; + // 如果没找到就会返回一个负数,这个负数取反之后再减一就是查找的值应该在数组中的位置; + // 例如 [-1, 0, 1, 5] 中二分查找 2,其返回值就是 -4,其 -(-4) - 1 = 3,所以 2 这个元素插入到数组的索引就是 3 + int bound = Arrays.binarySearch(sums, target); + if (bound < 0) { + bound = -bound - 1; + } + if (bound < sums.length) { // 当 bound 确定插入点不在 sums 数组的最后面时,说明不小于 target 的值了 + ans = Math.min(ans, bound - i); + } + } + return ans == Integer.MAX_VALUE ? 0 : ans; + } + + public static void main(String[] args) { + Solution solution = new Solution(); + System.out.println(solution.minSubArrayLen(7, new int[]{2, 3, 1, 2, 4, 3})); + } +} \ No newline at end of file