1477 找两个和为目标值且不重叠的子数组-中等
题目:
给你一个整数数组 arr
和一个整数值 target
。
请你在 arr
中找 两个互不重叠的子数组 且它们的和都等于 target
。可能会有多种方案,请你返回满足要求的两个子数组长度和的 最小值 。
请返回满足要求的最小长度和,如果无法找到这样的两个子数组,请返回 -1 。
分析:
利用滑动窗口,找出所有满足条件的子数组【这些子数组可能重叠,也可能不重叠,需要剪枝操作】
对所有的子数组按 长度 排序,以便找到第一个答案后即可退出循环
剪枝1:判断子数组的长度,如果超过原数组的长度的一半,那么肯定无解,直接退出。
剪枝2:对有包含关系的子数组直接跳过
// date 2023/11/24
type resNum struct {
start int
length int
}
func minSumOfLengths(arr []int, target int) int {
ans := len(arr) * 2
res := make([]*resNum, 0, 16)
left, right := 0, 0
sum := 0
n := len(arr)
for right < n {
sum += arr[right]
right++
for sum >= target {
if sum == target {
// one result
// res = append(res, right-left)
res = append(res, &resNum{start: left, length: right - left})
}
sum -= arr[left]
left++
}
}
// 防止超时
// 按子数组长度排序,后面剪枝之后,只要找到答案,即可 break
sort.Slice(res, func(i, j int) bool {
return res[i].length < res[j].length
})
m := len(res)
for i := 0; i < m; i++ {
// 防止超时
// 如果单个子数组的长度已经超过一半,那么肯定无解,直接跳出
if res[i].length * 2 > n {
break
}
for j := i+1; j < m; j++ {
if res[i].start < res[j].start && res[j].start < res[i].start + res[i].length {
continue
}
if res[j].start < res[i].start && res[i].start < res[j].start + res[j].length {
continue
}
ans = min(ans, res[i].length + res[j].length)
break
}
}
if ans == len(arr) * 2 {
return -1
}
return ans
}
func min(x, y int) int {
if x < y {
return x
}
return y
}
最后更新于