添加 problem 891 和 907

This commit is contained in:
YDZ
2019-06-30 00:49:58 +08:00
parent 1325b9cf17
commit 80aedb6fc6
7 changed files with 270 additions and 7 deletions

View File

@@ -0,0 +1,15 @@
package leetcode
import (
"sort"
)
func sumSubseqWidths(A []int) int {
sort.Ints(A)
res, mod, n, p := 0, 1000000007, len(A), 1
for i := 0; i < n; i++ {
res = (res + (A[i]-A[n-1-i])*p) % mod
p = (p << 1) % mod
}
return res
}

View File

@@ -0,0 +1,47 @@
package leetcode
import (
"fmt"
"testing"
)
type question891 struct {
para891
ans891
}
// para 是参数
// one 代表第一个参数
type para891 struct {
one []int
}
// ans 是答案
// one 代表第一个答案
type ans891 struct {
one int
}
func Test_Problem891(t *testing.T) {
qs := []question891{
question891{
para891{[]int{2, 1, 3}},
ans891{6},
},
question891{
para891{[]int{3, 7, 2, 3}},
ans891{35},
},
}
fmt.Printf("------------------------Leetcode Problem 891------------------------\n")
for _, q := range qs {
_, p := q.ans891, q.para891
fmt.Printf("【input】:%v 【output】:%v\n", p, sumSubseqWidths(p.one))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,44 @@
# [891. Sum of Subsequence Widths](https://leetcode.com/problems/sum-of-subsequence-widths/)
## 题目
Given an array of integers A, consider all non-empty subsequences of A.
For any sequence S, let the width of S be the difference between the maximum and minimum element of S.
Return the sum of the widths of all subsequences of A.
As the answer may be very large, return the answer modulo 10^9 + 7.
Example 1:
```c
Input: [2,1,3]
Output: 6
Explanation:
Subsequences are [1], [2], [3], [2,1], [2,3], [1,3], [2,1,3].
The corresponding widths are 0, 0, 0, 1, 1, 2, 2.
The sum of these widths is 6.
```
Note:
- 1 <= A.length <= 20000
- 1 <= A[i] <= 20000
## 题目大意
给定一个整数数组 A ,考虑 A 的所有非空子序列。对于任意序列 S ,设 S 的宽度是 S 的最大元素和最小元素的差。返回 A 的所有子序列的宽度之和。由于答案可能非常大,请返回答案模 10^9+7。
## 解题思路
- 理解题意以后,可以发现,数组内元素的顺序并不影响最终求得的所有子序列的宽度之和。
[2,1,3]:[1],[2],[3],[2,1],[2,3],[1,3],[2,1,3]
[1,2,3]:[1],[2],[3],[1,2],[2,3],[1,3],[1,2,3]
针对每个 A[i] 而言A[i] 对最终结果的贡献是在子序列的左右两边的时候才有贡献,当 A[i] 位于区间中间的时候,不影响最终结果。先对 A[i] 进行排序,排序以后,有 i 个数 <= A[i],有 n - i - 1 个数 >= A[i]。所以 A[i] 会在 2^i 个子序列的右边界出现2^(n-i-1) 个左边界出现。那么 A[i] 对最终结果的贡献是 A[i] * 2^i - A[i] * 2^(n-i-1) 。举个例子,[1,4,5,7]A[2] = 5那么 5 作为右边界的子序列有 2^2 = 4 个,即 [5],[1,5],[4,5],[1,4,5]5 作为左边界的子序列有 2^(4-2-1) = 2 个,即 [5],[5,7]。A[2] = 5 对最终结果的影响是 5 * 2^2 - 5 * 2^(4-2-1) = 10 。
- 题目要求所有子序列的宽度之和,也就是求每个区间最大值减去最小值的总和。那么 `Ans = SUM{ A[i]*2^i - A[n-i-1] * 2^(n-i-1) }`,其中 `0 <= i < n`。需要注意的是 2^i 可能非常大,所以在计算中就需要去 mod 了,而不是最后计算完了再 mod。注意取模的结合律`(a * b) % c = (a % c) * (b % c) % c`

View File

@@ -0,0 +1,70 @@
package leetcode
// 解法一 最快的解是 DP + 单调栈
func sumSubarrayMins(A []int) int {
stack, dp, res, mod := []int{}, make([]int, len(A)+1), 0, 1000000007
stack = append(stack, -1)
for i := 0; i < len(A); i++ {
for stack[len(stack)-1] != -1 && A[i] <= A[stack[len(stack)-1]] {
stack = stack[:len(stack)-1]
}
dp[i+1] = (dp[stack[len(stack)-1]+1] + (i-stack[len(stack)-1])*A[i]) % mod
stack = append(stack, i)
res += dp[i+1]
res %= mod
}
return res
}
type pair struct {
val int
count int
}
// 解法二 用两个单调栈
func sumSubarrayMins_(A []int) int {
res, n, mod := 0, len(A), 1000000007
lefts, rights, leftStack, rightStack := make([]int, n), make([]int, n), []*pair{}, []*pair{}
for i := 0; i < n; i++ {
count := 1
for len(leftStack) != 0 && leftStack[len(leftStack)-1].val > A[i] {
count += leftStack[len(leftStack)-1].count
leftStack = leftStack[:len(leftStack)-1]
}
leftStack = append(leftStack, &pair{val: A[i], count: count})
lefts[i] = count
}
for i := n - 1; i >= 0; i-- {
count := 1
for len(rightStack) != 0 && rightStack[len(rightStack)-1].val >= A[i] {
count += rightStack[len(rightStack)-1].count
rightStack = rightStack[:len(rightStack)-1]
}
rightStack = append(rightStack, &pair{val: A[i], count: count})
rights[i] = count
}
for i := 0; i < n; i++ {
res = (res + A[i]*lefts[i]*rights[i]) % mod
}
return res
}
// 解法三 暴力解法,中间很多重复判断子数组的情况
func sumSubarrayMins__(A []int) int {
res, mod := 0, 1000000007
for i := 0; i < len(A); i++ {
stack := []int{}
stack = append(stack, A[i])
for j := i; j < len(A); j++ {
if stack[len(stack)-1] >= A[j] {
stack = stack[:len(stack)-1]
stack = append(stack, A[j])
}
res += stack[len(stack)-1]
}
}
return res % mod
}

View File

@@ -0,0 +1,42 @@
package leetcode
import (
"fmt"
"testing"
)
type question907 struct {
para907
ans907
}
// para 是参数
// one 代表第一个参数
type para907 struct {
one []int
}
// ans 是答案
// one 代表第一个答案
type ans907 struct {
one int
}
func Test_Problem907(t *testing.T) {
qs := []question907{
question907{
para907{[]int{3, 1, 2, 4}},
ans907{17},
},
}
fmt.Printf("------------------------Leetcode Problem 907------------------------\n")
for _, q := range qs {
_, p := q.ans907, q.para907
fmt.Printf("【input】:%v 【output】:%v\n", p, sumSubarrayMins(p.one))
}
fmt.Printf("\n\n\n")
}

View File

@@ -0,0 +1,45 @@
# [907. Sum of Subarray Minimums](https://leetcode.com/problems/sum-of-subarray-minimums/)
## 题目
Given an array of integers A, find the sum of min(B), where B ranges over every (contiguous) subarray of A.
Since the answer may be large, return the answer modulo 10^9 + 7.
Example 1:
```c
Input: [3,1,2,4]
Output: 17
Explanation: Subarrays are [3], [1], [2], [4], [3,1], [1,2], [2,4], [3,1,2], [1,2,4], [3,1,2,4].
Minimums are 3, 1, 2, 4, 1, 1, 2, 1, 1, 1. Sum is 17.
```
Note:
1. 1 <= A.length <= 30000
2. 1 <= A[i] <= 30000
## 题目大意
给定一个整数数组 A找到 min(B) 的总和,其中 B 的范围为 A 的每个(连续)子数组。
由于答案可能很大,因此返回答案模 10^9 + 7。
## 解题思路
- 首先想到的是暴力解法,用两层循环,分别枚举每个连续的子区间,区间内用一个元素记录区间内最小值。每当区间起点发生变化的时候,最终结果都加上上次遍历区间找出的最小值。当整个数组都扫完一遍以后,最终结果模上 10^9+7。
- 上面暴力解法时间复杂度特别大,因为某个区间的最小值可能是很多区间的最小值,但是我们暴力枚举所有区间,导致要遍历的区间特别多。优化点就在如何减少遍历的区间。第二种思路是用 2 个单调栈。想得到思路是 `res = sum(A[i] * f(i))`,其中 f(i) 是子区间的数A[i] 是这个子区间内的最小值。为了得到 f(i) 我们需要找到 left[i] 和 right[i]left[i] 是 A[i] 左边严格大于 A[i](>关系)的区间长度。right[i] 是 A[i] 右边非严格大于(>=关系)的区间长度。left[i] + 1 等于以 A[i] 结尾的子数组数目A[i] 是唯一的最小值right[i] + 1 等于以 A[i] 开始的子数组数目A[i] 是第一个最小值。于是有 `f(i) = (left[i] + 1) * (right[i] + 1)`。例如对于 [3,1,4,2,5,3,3,1] 中的“2”我们找到的串就为[4,2,5,3,3]2 左边有 1 个数比 2 大且相邻2 右边有 3 个数比 2 大且相邻,所以 2 作为最小值的串有 2 * 4 = 8 种。用排列组合的思维也能分析出来2 的左边可以拿 01…… m 个,总共 (m + 1) 种,同理右边可以拿 01…… n 个,总共 (n + 1) 种,所以总共 (m + 1)(n + 1)种。只要计算出了 f(i),这个题目就好办了。以 [3,1,2,4] 为例left[i] + 1 = [1,2,1,1]right[i] + 1 = [1,3,2,1],对应 i 位的乘积是 f[i] = [1 * 12 * 31 * 21 * 1] = [1621],最终要求的最小值的总和 res = 3 * 1 + 1 * 6 + 2 * 2 + 4 * 1 = 17。
- **看到这种 mod1e9+7 的题目首先要想到的就是dp**。最终的优化解即是利用 DP + 单调栈。单调栈维护数组中的值逐渐递增的对应下标序列。定义 `dp[i + 1]` 代表以 A[i] 结尾的子区间内最小值的总和。状态转移方程是 `dp[i + 1] = dp[prev + 1] + (i - prev) * A[i]`,其中 prev 是比 A[i] 小的前一个数,由于我们维护了一个单调栈,所以 prev 就是栈顶元素。(i - prev) * A[i] 代表在还没有出现 prev 之前,这些区间内都是 A[i] 最小,那么这些区间有 i - prev 个,所以最小值总和应该是 (i - prev) * A[i]。再加上 dp[prev + 1] 就是 dp[i + 1] 的最小值总和了。以 [3, 1, 2, 4, 3] 为例,当 i = 4, 所有以 A[4] 为结尾的子区间有:
[3]
[4, 3]
[2, 4, 3]
[1, 2, 4, 3]
[3, 1, 2, 4, 3]
在这种情况下, stack.peek() = 2, A[2] = 2。前两个子区间 [3] and [4, 3], 最小值的总和 = (i - stack.peek()) * A[i] = 6。后 3 个子区间是 [2, 4, 3], [1, 2, 4, 3] 和 [3, 1, 2, 4, 3], 它们都包含 22 是比 3 小的前一个数,所以 dp[i + 1] = dp[stack.peek() + 1] = dp[2 + 1] = dp[3] = dp[2 + 1]。即需要求 i = 2 的时候 dp[i + 1] 的值。继续递推,比 2 小的前一个值是 1A[1] = 1。dp[3] = dp[1 + 1] + (2 - 1) * A[2]= dp[2] + 2。dp[2] = dp[1 + 1],当 i = 1 的时候prev = -1即没有人比 A[1] 更小了,所以 dp[2] = dp[1 + 1] = dp[-1 + 1] + (1 - (-1)) * A[1] = 0 + 2 * 1 = 2。迭代回去dp[3] = dp[2] + 2 = 2 + 2 = 4。dp[stack.peek() + 1] = dp[2 + 1] = dp[3] = 4。所以 dp[i + 1] = 4 + 6 = 10。
- 与这一题相似的解题思路的题目有第 828 题,第 891 题。

View File

@@ -950,7 +950,7 @@
| 0888 | Fair Candy Swap | | 56.80% | Easy | |
| 0889 | Construct Binary Tree from Preorder and Postorder Traversal | | 60.30% | Medium | |
| 0890 | Find and Replace Pattern | | 71.30% | Medium | |
| 0891 | Sum of Subsequence Widths | | 29.10% | Hard | |
| 0891 | Sum of Subsequence Widths |[Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0891.%20Sum%20of%20Subsequence%20Widths) | 29.10% | Hard | |
| 0892 | Surface Area of 3D Shapes | | 56.10% | Easy | |
| 0893 | Groups of Special-Equivalent Strings | | 62.80% | Easy | |
| 0894 | All Possible Full Binary Trees | | 71.00% | Medium | |
@@ -966,7 +966,7 @@
| 0904 | Fruit Into Baskets | [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0904.%20Fruit%20Into%20Baskets) | 41.60% | Medium | |
| 0905 | Sort Array By Parity | | 72.60% | Easy | |
| 0906 | Super Palindromes | | 30.40% | Hard | |
| 0907 | Sum of Subarray Minimums | | 27.60% | Medium | |
| 0907 | Sum of Subarray Minimums |[Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0907.%20Sum%20of%20Subarray%20Minimums) | 27.60% | Medium | |
| 0908 | Smallest Range I | | 64.60% | Easy | |
| 0909 | Snakes and Ladders | | 33.80% | Medium | |
| 0910 | Smallest Range II | | 23.70% | Medium | |
@@ -1247,8 +1247,8 @@
|[746. Min Cost Climbing Stairs](https://leetcode.com/problems/min-cost-climbing-stairs)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0746.%20Min%20Cost%20Climbing%20Stairs)| Easy | O(n)| O(1)||
|[766. Toeplitz Matrix](https://leetcode.com/problems/toeplitz-matrix)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0766.%20Toeplitz%20Matrix)| Easy | O(n)| O(1)||
|[867. Transpose Matrix](https://leetcode.com/problems/transpose-matrix)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0867.%20Transpose%20Matrix)| Easy | O(n)| O(1)||
|[891. Sum of Subsequence Widths](https://leetcode.com/problems/sum-of-subsequence-widths)| [Go]()| Hard | O(n)| O(1)||
|[907. Sum of Subarray Minimums](https://leetcode.com/problems/sum-of-subarray-minimums)| [Go]()| Medium | O(n)| O(1)||
|[891. Sum of Subsequence Widths](https://leetcode.com/problems/sum-of-subsequence-widths)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0891.%20Sum%20of%20Subsequence%20Widths)| Hard | O(n log n)| O(1)||
|[907. Sum of Subarray Minimums](https://leetcode.com/problems/sum-of-subarray-minimums)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0907.%20Sum%20of%20Subarray%20Minimums)| Medium | O(n)| O(n)||
|[922. Sort Array By Parity II](https://leetcode.com/problems/sum-of-subarray-minimums)| [Go]()| Medium | O(n)| O(1)||
|[969. Pancake Sorting](https://leetcode.com/problems/pancake-sorting)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0969.%20Pancake%20Sorting)| Medium | O(n)| O(1)||
|[977. Squares of a Sorted Array](https://leetcode.com/problems/squares-of-a-sorted-array)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0977.%20Squares%20of%20a%20Sorted%20Array)| Easy | O(n)| O(1)||
@@ -1367,7 +1367,7 @@
|[880. Decoded String at Index](https://leetcode.com/problems/decoded-string-at-index)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0880.%20Decoded%20String%20at%20Index)| Medium | O(n)| O(n)||
|[895. Maximum Frequency Stack](https://leetcode.com/problems/maximum-frequency-stack)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0895.%20Maximum%20Frequency%20Stack)| Hard | O(n)| O(n) ||
|[901. Online Stock Span](https://leetcode.com/problems/online-stock-span)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0901.%20Online%20Stock%20Span)| Medium | O(n)| O(n) ||
|[907. Sum of Subarray Minimums](https://leetcode.com/problems/sum-of-subarray-minimums)| [Go]()| Medium | O(n)| O(1)||
|[907. Sum of Subarray Minimums](https://leetcode.com/problems/sum-of-subarray-minimums)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0907.%20Sum%20of%20Subarray%20Minimums)| Medium | O(n)| O(n)||
|[921. Minimum Add to Make Parentheses Valid](https://leetcode.com/problems/minimum-add-to-make-parentheses-valid)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0921.%20Minimum%20Add%20to%20Make%20Parentheses%20Valid)| Medium | O(n)| O(n)||
|[946. Validate Stack Sequences](https://leetcode.com/problems/validate-stack-sequences)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0946.%20Validate%20Stack%20Sequences)| Medium | O(n)| O(n)||
|[1003. Check If Word Is Valid After Substitutions](https://leetcode.com/problems/check-if-word-is-valid-after-substitutions)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/1003.%20Check%20If%20Word%20Is%20Valid%20After%20Substitutions)| Medium | O(n)| O(1)||
@@ -1450,7 +1450,7 @@
|[746. Min Cost Climbing Stairs](https://leetcode.com/problems/min-cost-climbing-stairs)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0746.%20Min%20Cost%20Climbing%20Stairs)| Easy | O(n)| O(1)||
|[838. Push Dominoes](https://leetcode.com/problems/push-dominoes)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0838.%20Push%20Dominoes)| Medium | O(n)| O(1)||
|[1025. Divisor Game](https://leetcode.com/problems/divisor-game)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/1025.%20Divisor%20Game)| Easy | O(1)| O(1)||
|[891. Sum of Subsequence Widths](https://leetcode.com/problems/sum-of-subsequence-widths)| [Go]()| Hard | O(n)| O(1)||
|[891. Sum of Subsequence Widths](https://leetcode.com/problems/sum-of-subsequence-widths)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0891.%20Sum%20of%20Subsequence%20Widths)| Hard | O(n log n)| O(1)||
|[942. DI String Match](https://leetcode.com/problems/di-string-match)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0942.%20DI%20String%20Match)| Easy | O(n)| O(1)||
|-----------------------------------------------------------------|-------------|-------------| --------------------------| --------------------------|-------------|
@@ -1568,7 +1568,7 @@
|[357. Count Numbers with Unique Digits](https://leetcode.com/problems/count-numbers-with-unique-digits)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0357.%20Count%20Numbers%20with%20Unique%20Digits)| Medium | O(1)| O(1)||
|[628. Maximum Product of Three Numbers](https://leetcode.com/problems/maximum-product-of-three-numbers)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0628.%20Maximum%20Product%20of%20Three%20Numbers)| Easy | O(n)| O(1)||
|[885. Spiral Matrix III](https://leetcode.com/problems/spiral-matrix-iii)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0885.%20Spiral%20Matrix%20III)| Medium | O(n^2)| O(1)||
|[891. Sum of Subsequence Widths](https://leetcode.com/problems/sum-of-subsequence-widths)| [Go]()| Hard | O(n)| O(1)||
|[891. Sum of Subsequence Widths](https://leetcode.com/problems/sum-of-subsequence-widths)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0891.%20Sum%20of%20Subsequence%20Widths)| Hard | O(n log n)| O(1)||
|[942. DI String Match](https://leetcode.com/problems/di-string-match)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0942.%20DI%20String%20Match)| Easy | O(n)| O(1)||
|[976. Largest Perimeter Triangle](https://leetcode.com/problems/largest-perimeter-triangle/)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0976.%20Largest%20Perimeter%20Triangle)| Easy | O(n log n)| O(log n) ||
|[996. Number of Squareful Arrays](https://leetcode.com/problems/number-of-squareful-arrays)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0996.%20Number%20of%20Squareful%20Arrays)| Hard | O(n log n)| O(n) ||