lc 862. Shortest Subarray with Sum at Least K

断网导致原来写的那么多答案全没了,博客园能不能实时保存草稿,醉。

https://leetcode.com/problems/shortest-subarray-with-sum-at-least-k/

给一个数组a,找和大于k的所有子数组中的最短的那个。

最近二分有点上头,因为的确很强大,两个考虑二分的情况(其实需要刻意去想想能不能使用二分才会想到,这会是个好习惯):

1.最优问题变判断问题。比如:行递增列递增的矩阵中找某个元素->行递增列递增的矩阵中找第k大元素

2.有相应的简单孪生问题。比如1中的例子,再比如:找长度大于k的最大和->找和大于k的最小长度。

本题也想用二分来做,发现不对,假如我们能判断对于大于等于L的最大和子数组是不是大于k,那么我二分将得到的是大于k的所有子数组中最“”长度是多少,而非最小。

于是乎根据问题应该用单调队列。这个也是,单独想出来不容易,但是证明有效就简单多了。下面证明单调队列有效。

目前一个维持好的单调队列[a1,a2,...an],a[i-1]和a[i]之间那些不在的点都是比a[i]大的,对于这些比a[i]大的点是不会比a[i]取得更好的结果的,因为a[i]又小又排后,和后面的某个a[x]配对会使子数组和又大而长度又短,等于是这两个指标都会比中间pop出去的这些点好,中间这些点又丑又不上进怎么行,那么我们就已经可以让他们退出历史舞台了!

单调队列的合理性可以分两步进行:

1.目前一个维持好的单调队列是对于这个新值有效的。

2.新值进来后,仍然保持单调队列特性。

那么新来一个值怎么去从单调队列中找他最好的配对对象呢?二分法找小于a[-1]-k的最大值,此处代码应该背过。

于是乎就是n*log(n)咯。

优化一个算法永远比直接想到最优解简单一些,目前我们的算法哪里可以优化?

二分找到一个中间值x后,左边的你那些小值是没用的,因为他们只能和后来的匹配形成长度更大的子数组,这是没有用的。

代码:

import collectionsclass Solution:    def shortestSubarray(self, A, K):        """        :type A: List[int]        :type K: int        :rtype: int        """        sm = [0]+[k[0] for k in [[0]] for i in A if k.append(k.pop() + i) or True]        # mi = [k[0] for k in [[sm[0]]] for i in sm if k.append(min(k.pop(), i)) or True]

        def getlen(stk,ind):            if len(stk)<=1 or stk[-1]-stk[0]<K:                return None,None            tar=stk[-1]-K            l,r=0,len(stk)-1            while r-l>1:                m=(r+l)//2                if stk[-1]-stk[m]>=K:                    l=m                else:                    r=m            ans=ind[-1]-ind[l]            for i in range(l):                ind.popleft()                stk.popleft()            return ans,l        stack=collections.deque()        ind=collections.deque()        ans=len(sm)+1        for i,s in enumerate(sm):            while len(stack)>0 and stack[-1]>=s:                stack.pop()                ind.pop()            stack.append(s)            ind.append(i)            l,pl=getlen(stack,ind)            ans=min(ans,l) if l!=None else ans        if ans>len(sm):            ans=-1        return ans

s=Solution()print(s.shortestSubarray([-11,-15,76,41,-41,68,41,12,73,-8],50))

---恢复内容结束---

lc 862. Shortest Subarray with Sum at Least K

原文地址:https://www.cnblogs.com/waldenlake/p/10666193.html

时间: 2024-07-31 05:37:24

lc 862. Shortest Subarray with Sum at Least K的相关文章

862. 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

[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

leetcode 862 shorest subarray with sum at least K

https://leetcode.com/problems/shortest-subarray-with-sum-at-least-k/ 首先回顾一下求max子数组的值的方法是:记录一个前缀min值,然后扫一遍sum数组. 1.首先这里不需要最大,因为刚好够k就好了 2.这里需要距离最短.就是数组的长度最短. 这里的思路也一样,不过保存很多个min值,就是用一个队列,保存前缀的min值,不需要最min,只不过有更小的就更好. 也就是如果sum数组的值是: ..... 60, 40.....Y..

array / matrix subarray/submatrix sum

Maximal Subarray Sum : O(n) scan-and-update dynamic programming,https://en.wikipedia.org/wiki/Maximum_subarray_problem, https://leetcode.com/problems/maximum-subarray Shortest Subarray Sum Equals K : prefix-sum + sort + hash-table: O(nlogn) time, O(n

[LC] 53. Maximum Subarray

Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum. Example: Input: [-2,1,-3,4,-1,2,1,-5,4], Output: 6 Explanation: [4,-1,2,1] has the largest sum = 6. Time:O(N)Spac

LC 416. Partition Equal Subset Sum

题目 Given a non-empty array containing only positive integers, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal. Note: Each of the array element will not exceed 100. The array size will not e

[LC] 1099. Two Sum Less Than K

Given an array A of integers and integer K, return the maximum S such that there exists i < j with A[i] + A[j] = S and S < K. If no i, j exist satisfying this equation, return -1. Example 1: Input: A = [34,23,1,24,75,33,54,8], K = 60 Output: 58 Expl

LeetCode 1099. Two Sum Less Than K

原题链接在这里:https://leetcode.com/problems/two-sum-less-than-k/ 题目: Given an array A of integers and integer K, return the maximum S such that there exists i < j with A[i] + A[j] = S and S < K. If no i, jexist satisfying this equation, return -1. Example

单调栈与单调队列

单调栈 特点 栈内的元素单调递增或者单调递减,可以在\(O(n)\)的时间内求出数列中所有数的左边或右边第一个比其大或小的元素,总时间复杂度为\(O(n)\) 例子 单调栈中一般存索引 一个单调递增栈s = [0, 10, 20 ,t]代表栈中a[1]~a[9]的元素大于a[10]的元素,索引为a[11]~a[19]的元素大于a[20]的元素... 这样我们可以发现在a[10]左边第一个比a[10]的数为a[0],在a[20]左边第一个比a[20]的数为a[10]... 如何实现呢? 每次有元素