专栏:50多种数据结构彻底征服
专栏:50多种经典图论算法全部掌握
一前阿里巴巴的员工最近发文称:自己35岁,年薪百万,还是技术专家,被一个空降的95后嫡系领导逼到离职。说他代码水平不如应届生,不想干可以走。
都技术专家了,代码水平肯定不会差的,即便代码水平差,也应该是由经验更足的人来评价。假如一个 5 年工作经验的对一个 1 年工作经验的说你的代码水平差,能理解。但一个 1 年工作经验的对一个 5 工作经验的说你的代码水平很差,就感觉有点找茬了,但也不排除个别 5 年工作经验的确实比较水。
但发文的作者都已经是技术专家了,水平不会差的,所以空降的95后领导很可能是来搞事的。
--------------下面是今天的算法题--------------
来看下今天的算法题,这题是LeetCode的第1477题:找两个和为目标值且不重叠的子数组,难度是中等。
给你一个整数数组 arr 和一个整数值 target 。
请你在 arr 中找两个互不重叠的子数组且它们的和都等于 target 。可能会有多种方案,请你返回满足要求的两个子数组长度和的最小值 。
请返回满足要求的最小长度和,如果无法找到这样的两个子数组,请返回 -1 。
示例1:
输入:arr = [7,3,4,7], target = 7 输出:2 解释:尽管我们有 3 个互不重叠的子数组和为 7 ([7], [3,4] 和 [7]),但我们会选择第一个和第三个子数组,因为它们的长度和 2 是最小值。
示例2:
输入:arr = [4,3,2,6,2,3,4], target = 6 输出:-1 解释:我们只有一个和为 6 的子数组。
1 <= arr.length <= 10^5
1 <= arr[i] <= 1000
1 <= target <= 10^8
问题分析
这题说的是找出两个子数组,他们的和都等于target,并且这两个子数组还不能重叠,如果有多个这样的子数组,返回长度和的最小值。
如果只是计算子数组之和等于target,我们可以使用滑动窗口,但这题即要保证两个子数组之和等于target,又要保证这两个子数组不能重叠。这里我们可以使用滑动窗口加动态规划来解决。
我们定义dp[i]表示子数组[0,i-1]中满足和为target的最小子数组长度,如果某个子数组[m,n]的和为target,我们只需要在子数组[0,m-1]中找个一个满足条件的最小长度即可,这个最小长度就是dp[m],最后还需要保存最小长度。
JAVA:
public int minSumOfLengths(int[] arr, int target) { int left = 0, right = 0, n = arr.length; // dp[i+1]表示子数组[0,i]中满足和为target的数组最小长度。 int[] dp = new int[n + 1]; dp[0] = n; int ans = Integer.MAX_VALUE; int sum = 0;// 窗口中元素的和。 while (right < n) { sum += arr[right]; while (sum > target)// 窗口中的元素之和不能大于target。 sum -= arr[left++]; if (sum == target) {// 窗口中的元素之和等于target。 int len = right - left + 1;// 窗口长度 ans = Math.min(ans, dp[left] + len); dp[right + 1] = Math.min(dp[right], len); } else {// 窗口中的元素之后小于target。 dp[right + 1] = dp[right]; } right++;// 滑动窗口右边界。 } return ans > n ? -1 : ans; }C++:
public: int minSumOfLengths(vector
&arr, int target) { int left = 0, right = 0, n = arr.size(); // dp[i+1]表示子数组[0,i]中满足和为target的数组最小长度。 vector
dp(n + 1, 0); dp[0] = n; int ans = INT_MAX; int sum = 0;// 窗口中元素的和。 while (right < n) { sum += arr[right]; while (sum > target)// 窗口中的元素之和不能大于target。 sum -= arr[left++]; if (sum == target) {// 窗口中的元素之和等于target。 int len = right - left + 1;// 窗口长度 ans = min(ans, dp[left] + len); dp[right + 1] = min(dp[right], len); } else {// 窗口中的元素之后小于target。 dp[right + 1] = dp[right]; } right++;// 滑动窗口右边界。 } return ans > n ? -1 : ans; }
笔者简介
博哥,真名:王一博,毕业十多年, 作者,专注于 数据结构和算法 的讲解,在全球30多个算法网站中累计做题2000多道,在公众号中写算法题解800多题,对算法题有自己独特的解题思路和解题技巧,喜欢的可以给个关注,也可以 下载我整理的1000多页的PDF算法文档 。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.