和至少为K的最短子数组

返回 A 的最短的非空连续子数组的长度,该子数组的和至少为 K

如果没有和至少为 K 的非空子数组,返回 -1 。

示例 1:

输入:A = [1], K = 1
输出:1

示例 2:

输入:A = [1,2], K = 4
输出:-1

示例 3:

输入:A = [2,-1,2], K = 3
输出:3

1 <= A.length <=
50000
-10 ^ 5 <= A[i] <= 10 ^ 5
1 <= K <= 10 ^ 9

这道题的关键在于我们要知道各个区间的和。从而来判断哪个区间的和是满足要求的。用暴利解法逐个判断是可行的,但是耗费的时间太多。因为暴力解法其实做了很多重复的工作。那么为了节省重复的计算,有个方法就是保存数组的前缀和数组。也就是用一个数组sum来记录各个区间的和。也就是

sum[i]=arr[0]+arr[1]+……+arr[i-1]。这里为了计算方便,增加了以为sum[0]=0。有了这个数组,就可以很方便的求解任意区间的和。

比如要求区间[4,6]的和,就可以用sum[6]-sum[4]。

那么接下来的工作就是要将sum数组中的各个求和值入队列。

(1) 当区间[0,i]的值比[0,i-1]的值要大的时候,就直接进队列。

(2) 当区间[0…i]的值比区间[0….i-1]还要小的时候,那么对于后面的位置,其实可以忽略掉i-1,因为sum[n]-sum[i] > sum[n]-sum[n-1]。也就是[i,n]区间的值比[i-1,n]的值要大,而且更短。因此i-1这个位置就可以被踢出队列。

比如队列里面的数值如下:0,1,3,5,4。由于4比5小,此时应该将5剔除出队列,为什么呢,如果保留5在队列里面,当后面一个数组比如7进队列的时候,队列数组变成0,1,3,5,4,7。 这个时候计算区间和7-5明显比7-4要小。而且[5,7]的区间长度为2,[4,7]的区间长度为1。因此5没有必要存在于队列中。队里中的值变为0,1,3,4,7

每次完成队列插入的操作后,就要开始对队列里面的区间进行计算了。

当队列为0,1的时候,1-0<4 不满足条件

当队列为0,1,3的时候,3-1<4 不满足条件

当队列为0,1,3,5的时候,5-0>4 满足条件,最小长度为3。0出队列,队列变为1,3,5
继续比较5-1>4,最小长度为2,1出队列,队列变为3,5。

当队列为3,4的时候(由于5比4小,因此出队列), 4-3<4不满足条件

当队列为3,4,7的时候,7-3>=4,满足条件,最小长度为2

代码如下:

没有采用队列或者栈的结构,就用数组来存储dquue,用dq_begin, dq_end, dq_size来分别表示数组的第一个,最后一个元素以及数组长度。

int shortestSubarray(int a[], int k, int len)

{

int *dqueue;

int *sum;

int
i,dq_begin,dq_end,dq_size,min_length,lengh;

dqueue = (int *)malloc((len + 1) * sizeof(int));

sum = (int *)malloc(len * sizeof(int));

memset(sum, 0,len * sizeof(int));

memset(dqueue, 0, (len + 1) * sizeof(int));

dq_begin = 0;

dq_end = -1;

dq_size = 0;

min_length = len+1;

for (i = 1; i
<= len; i++)

{

*(sum + i) = *(sum+i-1)+a[i-1];

}

for (i = 0; i
<= len; i++)

{

if (i != 0)

{

while (dq_size > 0 && sum[dq_end] >= sum[i])

{

dq_end -= 1;

dq_size -= 1;

}

while (dq_size > 0 && sum[i] - sum[dq_begin] >= k)

{

lengh = i - dq_begin;

min_length = min_length >=
lengh ? lengh : min_length;

dq_begin += 1;

dq_size -= 1;

}

}

dq_end += 1;

dqueue[dq_end] = i;

dq_size += 1;

}

return min_length;

}

原文地址:https://www.cnblogs.com/zhanghongfeng/p/11621746.html

时间: 2024-10-12 08:57:32

和至少为K的最短子数组的相关文章

[Swift]LeetCode862. 和至少为 K 的最短子数组 | Shortest Subarray with Sum at Least K

Return the length of the shortest, non-empty, contiguous subarray of A with sum at least K. If there is no non-empty subarray with sum at least K, return -1. Example 1: Input: A = [1], K = 1 Output: 1 Example 2: Input: A = [1,2], K = 4 Output: -1 Exa

排序练习题(五):最短子数组

对于一个数组,请设计一个高效算法计算需要排序的最短子数组的长度. 给定一个int数组A和数组的大小n,请返回一个二元组,代表所求序列的长度.(原序列位置从0开始标号,若原序列有序,返回0).保证A中元素均为正整数. 测试样例: [1,4,6,5,9,10],6 返回:2 public class Subsequence { public int shortestSubsequence(int[] A, int n) { // write code here int max = A[0],min

算法笔记 --- 最短子数组

对于一个数组,请设计一个高效算法计算需要排序的最短子数组的长度. 给定一个int数组A和数组的大小n,请返回一个二元组,代表所求序列的长度.(原序列位置从0开始标号,若原序列有序,返回0).保证A中元素均为正整数. #include <iostream> #include <vector> using namespace std; class Subsequence { public: int shortestSubsequence(vector<int> A, int

leetcode 974. 和可被 K 整除的子数组

目录 题目描述: 示例: 解法: 题目描述: 给定一个整数数组 A,返回其中元素之和可被 K?整除的(连续.非空)子数组的数目. 示例: 输入:A = [4,5,0,-2,-3,1], K = 5 输出:7 解释: 有 7 个子数组满足其元素之和可被 K = 5 整除: [4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3] 提示: 1 <= A.length <= 30000 -10000 &

hihocoder-1796-完美K倍子数组

hihocoder-1796-完美K倍子数组  #1796 : 完美K倍子数组 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 如果一个数组满足长度至少是2,并且其中任意两个不同的元素Ai和Aj (i ≠ j)其和Ai+Aj都是K的倍数,我们就称该数组是 完美K倍数组. 现在给定一个包含N个整数的数组A = [A1, A2, ... AN]以及一个整数K,请你找出A的最长的完美子数组B,输出B的长度. 如果这样的子数组不存在,输出-1. 输入 第一行包含两个整数N和

转:最小区间:k个有序的数组,找到最小区间使k个数组中每个数组至少有一个数在区间中

转:http://www.itmian4.com/thread-6504-1-1.html 最小区间原题 k个有序的数组,找到最小的区间范围使得这k个数组中,每个数组至少有一个数字在这个区间范围内.比如: 数组1:[4, 10, 15, 24, 26] 数组2:[0, 9, 12, 20] 数组3:[5, 18, 22, 30] 最小的区间是[20, 24],这个区间包含了数组1中的24,数组2中的20,数组3中的22 思考时间~~~ 分析 该题看起来还算比较简单,大家通常都会想到:为每一个数组

[LeetCode] Shortest Unsorted Continuous Subarray 最短无序连续子数组

Given an integer array, you need to find one continuous subarray that if you only sort this subarray in ascending order, then the whole array will be sorted in ascending order, too. You need to find the shortest such subarray and output its length. E

后缀数组(至少重复k次的可重叠的最长重复子串)—— POJ 3882

对应POJ 题目:点击打开链接 Stammering Aliens Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Description Dr. Ellie Arroway has established contact with an extraterrestrial civilization. However, all efforts to decode their m

【算法30】从数组中选择k组长度为m的子数组,要求其和最小

原题链接:codeforce 267 Div2 C 问题描述: 给定长度为n的数组a[],从中选择k个长度为m的子数组,要求和最大. 形式描述为:选择$k$个子数组[$l_1$, $r_1$], [$l_2$, $r_2$], ..., [$l_k$l1, $r_k$] (1 ≤ $l_1$ ≤$r_1$ ≤$l_2$ ≤ $r_2$ ≤... ≤$l_k$ ≤ $r_k$ ≤ n; $r_i-r_i+1$), 使得$\sum_{i=1}^{k}\sum_{j=l_i}^{r_i}p_j$ 问题