算法设计与分析第五周作业leetccode

  1. Shortest Subarray with Sum at Least K

Difficulty:Hard
Total Accepted:4.9K
Total Submissions:25.6K
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
Example 3:

Input: A = [2,-1,2], K = 3
Output: 3

Note:

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

解决思路:
最开始的做法是两个循环,将n(n-1)/2个子序列组合遍历一遍
时间复杂度为o(n^2)

class Solution {
public:
	int shortestSubarray(vector<int>& A, int K) {
		long int result = 100000;
		int length = A.size();
		long sum = 0;
		bool isFind = false;
		for (int i = 0; i < length; i++) {
			sum = 0;
			for (int j = i; j < length; j++) {
				sum += A[j];
				if (sum >= K) {
					result = min(result, (long int)(j - i + 1));
					isFind = true;
					break;
				}
			}
		}
		if (!isFind) {
			return -1;
		}
		return result;
	}
};

很不幸,果然遇到后面的大数据,长度有三四万,处理时间超时了
在这里插入图片描述
后来参考外国网友的思路,进行改善:
Same idea, this is my thinking process to improve the O(N^2) solution to O(N).

public int shortestSubarray(int[] A, int K) {
        int[] presum = new int[A.length+1];
        int res = A.length+1;
        for(int i=1;i<presum.length;i++){
            presum[i] = presum[i-1]+A[i-1];
            for(int j=i-1;j>=0;j--){
                if(presum[i]-presum[j]>=K)
                    res = Math.min(res, i-j);
            }
        }
        return res == (A.length+1)?-1: res;
    }

This is a O(n^2) solution ( Time Limit Exceeded ).

If we have an array prefix sum array like [0,1,2,3,4,10,7,4,5,14,16,… ], K=11
The best answer is: length=2 (i=8, j=10).

For the subarray [4,10,7,4], do we need the first three elements 4,10,7? We don’t, if we have presum[j]-10>=K, presum[j]-4(later one) is also larger than K and has a shorter length. Therefore, the elements we want to use in the inner loop are actually like [0,1,2,3,**4(later one),**5,14,16, …]. When we visit later 4 in the outer loop, we can remove previous elements that are larger than 4. What we get will be a ascent array.

The first answer we found will be length=6 (i=3, j=9). After we find this answer, do we still need the elements 0,1,2? We don’t. Since the next answer must be shorter than this one, we don’t need to compare later element with these elements. Now, the array will be [3, 4, 5, 14, 16, …]

Then, when we visit 16 in the outer loop. And we will sequentially visit and remove 3,4 in the inner loop. Finally, we get the best answer (i=8, j=10).

Okay, there are two steps we need to reduce redundant calculations.

Remove previous elements that are larger than the current one ( second while loop ).
If we find an answer (i, j), remove smaller elements than presum[i]. Since we have keep elements in ascent order with the first step, we can just remove previous elements before i ( fisrt while loop ).
Since we only need to remove head or tail elements, Deque will be a great data structure.
添加两个循环,一个用来将局部和为负数的部分去掉,另一个循环用来将在同样符合条件的子序列中将更远更长的那个头下标去掉,再利用双向队列的特性,将时间复杂度从o(n^2)缩短为o(n),因为每个B[i]只需要插入一次
下面是击败了99.85%提交的代码:

class Solution {
public:
	int shortestSubarray(vector<int>& A, int K) {
		
		int length = A.size();
		int result = length + 1;
		deque<int> d;
 		vector<int> B(length+1, 0);//B[i]就是A的前i个数的和
		for (int i = 1; i <= length; i++) {
			B[i] = B[i - 1] + A[i-1];
		}
		for (int i = 0; i <= length; i++) {
			while (d.size() && (B[i] - B[d.front()]) >= K) {
				result = min(result, (i - d.front()));
				d.pop_front();
			}
			while (d.size() && B[i] <= B[d.back()]) {
				d.pop_back();
			}
			d.push_back(i);
		}
		if (result==(length+1)) {
			return -1;
		}
		return result;
	}
};

static const auto io_sync_off = []()
{
	// turn off sync
	std::ios::sync_with_stdio(false);
	// untie in/out streams
	std::cin.tie(nullptr);
	return nullptr;
}();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值