Add weekly-contest-214 solution

This commit is contained in:
YDZ
2020-11-10 07:39:47 +08:00
parent f3888ff449
commit ea38a91202
20 changed files with 1407 additions and 184 deletions

View File

@ -0,0 +1,62 @@
package leetcode
import (
"fmt"
"testing"
)
type question1646 struct {
para1646
ans1646
}
// para 是参数
// one 代表第一个参数
type para1646 struct {
n int
}
// ans 是答案
// one 代表第一个答案
type ans1646 struct {
one int
}
func Test_Problem1646(t *testing.T) {
qs := []question1646{
{
para1646{7},
ans1646{3},
},
{
para1646{2},
ans1646{1},
},
{
para1646{3},
ans1646{2},
},
{
para1646{0},
ans1646{0},
},
{
para1646{1},
ans1646{1},
},
}
fmt.Printf("------------------------Leetcode Problem 1646------------------------\n")
for _, q := range qs {
_, p := q.ans1646, q.para1646
fmt.Printf("【input】:%v 【output】:%v \n", p, getMaximumGenerated(p.n))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,96 @@
# [1646. Get Maximum in Generated Array](https://leetcode.com/problems/get-maximum-in-generated-array/)
## 题目
You are given an integer `n`. An array `nums` of length `n + 1` is generated in the following way:
- `nums[0] = 0`
- `nums[1] = 1`
- `nums[2 * i] = nums[i]` when `2 <= 2 * i <= n`
- `nums[2 * i + 1] = nums[i] + nums[i + 1]` when `2 <= 2 * i + 1 <= n`
Return *****the **maximum** integer in the array* `nums`.
**Example 1:**
```
Input: n = 7
Output: 3
Explanation: According to the given rules:
nums[0] = 0
nums[1] = 1
nums[(1 * 2) = 2] = nums[1] = 1
nums[(1 * 2) + 1 = 3] = nums[1] + nums[2] = 1 + 1 = 2
nums[(2 * 2) = 4] = nums[2] = 1
nums[(2 * 2) + 1 = 5] = nums[2] + nums[3] = 1 + 2 = 3
nums[(3 * 2) = 6] = nums[3] = 2
nums[(3 * 2) + 1 = 7] = nums[3] + nums[4] = 2 + 1 = 3
Hence, nums = [0,1,1,2,1,3,2,3], and the maximum is 3.
```
**Example 2:**
```
Input: n = 2
Output: 1
Explanation: According to the given rules, the maximum between nums[0], nums[1], and nums[2] is 1.
```
**Example 3:**
```
Input: n = 3
Output: 2
Explanation: According to the given rules, the maximum between nums[0], nums[1], nums[2], and nums[3] is 2.
```
**Constraints:**
- `0 <= n <= 100`
## 题目大意
给你一个整数 n 。按下述规则生成一个长度为 n + 1 的数组 nums
- nums[0] = 0
- nums[1] = 1
- 当 2 <= 2 * i <= n 时nums[2 * i] = nums[i]
- 当 2 <= 2 * i + 1 <= n 时nums[2 * i + 1] = nums[i] + nums[i + 1]
返回生成数组 nums 中的 最大值。
## 解题思路
- 给出一个 n + 1 的数组,并按照生成规则生成这个数组,求出这个数组中的最大值。
- 简单题,按照题意生成数组,边生成边记录和更新最大值即可。
- 注意边界条件,当 n 为 0 的时候,数组里面只有一个元素 0 。
## 代码
```go
package leetcode
func getMaximumGenerated(n int) int {
if n == 0 {
return 0
}
nums, max := make([]int, n+1), 0
nums[0], nums[1] = 0, 1
for i := 0; i <= n; i++ {
if nums[i] > max {
max = nums[i]
}
if 2*i >= 2 && 2*i <= n {
nums[2*i] = nums[i]
}
if 2*i+1 >= 2 && 2*i+1 <= n {
nums[2*i+1] = nums[i] + nums[i+1]
}
}
return max
}
```

View File

@ -1,7 +1,6 @@
package leetcode
import (
"fmt"
"sort"
)
@ -11,7 +10,6 @@ func minDeletions(s string) int {
frequency[s[i]-'a']++
}
sort.Sort(sort.Reverse(sort.IntSlice(frequency)))
fmt.Printf("%v\n", frequency)
for i := 1; i <= 25; i++ {
if frequency[i] == frequency[i-1] && frequency[i] != 0 {
res++

View File

@ -0,0 +1,62 @@
package leetcode
import (
"fmt"
"testing"
)
type question1647 struct {
para1647
ans1647
}
// para 是参数
// one 代表第一个参数
type para1647 struct {
s string
}
// ans 是答案
// one 代表第一个答案
type ans1647 struct {
one int
}
func Test_Problem1647(t *testing.T) {
qs := []question1647{
{
para1647{"aab"},
ans1647{0},
},
{
para1647{"aaabbbcc"},
ans1647{2},
},
{
para1647{"ceabaacb"},
ans1647{2},
},
{
para1647{""},
ans1647{0},
},
{
para1647{"abcabc"},
ans1647{3},
},
}
fmt.Printf("------------------------Leetcode Problem 1647------------------------\n")
for _, q := range qs {
_, p := q.ans1647, q.para1647
fmt.Printf("【input】:%v 【output】:%v \n", p, minDeletions(p.s))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,89 @@
# [1647. Minimum Deletions to Make Character Frequencies Unique](https://leetcode.com/problems/minimum-deletions-to-make-character-frequencies-unique/)
## 题目
A string `s` is called **good** if there are no two different characters in `s` that have the same **frequency**.
Given a string `s`, return *the **minimum** number of characters you need to delete to make* `s` ***good**.*
The **frequency** of a character in a string is the number of times it appears in the string. For example, in the string `"aab"`, the **frequency** of `'a'` is `2`, while the **frequency** of `'b'` is `1`.
**Example 1:**
```
Input: s = "aab"
Output: 0
Explanation: s is already good.
```
**Example 2:**
```
Input: s = "aaabbbcc"
Output: 2
Explanation: You can delete two 'b's resulting in the good string "aaabcc".
Another way it to delete one 'b' and one 'c' resulting in the good string "aaabbc".
```
**Example 3:**
```
Input: s = "ceabaacb"
Output: 2
Explanation: You can delete both 'c's resulting in the good string "eabaab".
Note that we only care about characters that are still in the string at the end (i.e. frequency of 0 is ignored).
```
**Constraints:**
- `1 <= s.length <= 105`
- `s` contains only lowercase English letters.
## 题目大意
如果字符串 s 中 不存在 两个不同字符 频次 相同的情况,就称 s 是 优质字符串 。
给你一个字符串 s返回使 s 成为优质字符串需要删除的最小字符数。
字符串中字符的 频次 是该字符在字符串中的出现次数。例如,在字符串 "aab" 中,'a' 的频次是 2而 'b' 的频次是 1 。
**提示:**
- `1 <= s.length <= 105`
- `s` 仅含小写英文字母
## 解题思路
- 给出一个字符串 s要求输出使 s 变成“优质字符串”需要删除的最小字符数。“优质字符串”的定义是:字符串 s 中不存在频次相同的两个不同字符。
- 首先将 26 个字母在字符串中的频次分别统计出来,然后把频次从大到小排列,从频次大的开始,依次调整:例如,假设前一个和后一个频次相等,就把前一个字符删除一个,频次减一,再次排序,如果频次还相等,继续调整,如果频次不同了,游标往后移,继续调整后面的频次。直到所有的频次都不同了,就可以输出最终结果了。
- 这里需要注意频次为 0 的情况,即字母都被删光了。频次为 0 以后,就不需要再比较了。
## 代码
```go
package leetcode
import (
"sort"
)
func minDeletions(s string) int {
frequency, res := make([]int, 26), 0
for i := 0; i < len(s); i++ {
frequency[s[i]-'a']++
}
sort.Sort(sort.Reverse(sort.IntSlice(frequency)))
for i := 1; i <= 25; i++ {
if frequency[i] == frequency[i-1] && frequency[i] != 0 {
res++
frequency[i]--
sort.Sort(sort.Reverse(sort.IntSlice(frequency)))
i--
}
}
return res
}
```

View File

@ -4,7 +4,55 @@ import (
"container/heap"
)
// 解法一 贪心 + 二分搜索
func maxProfit(inventory []int, orders int) int {
maxItem, thresholdValue, count, res, mod := 0, -1, 0, 0, 1000000007
for i := 0; i < len(inventory); i++ {
if inventory[i] > maxItem {
maxItem = inventory[i]
}
}
low, high := 0, maxItem
for low <= high {
mid := low + ((high - low) >> 1)
for i := 0; i < len(inventory); i++ {
count += max(inventory[i]-mid, 0)
}
if count <= orders {
thresholdValue = mid
high = mid - 1
} else {
low = mid + 1
}
count = 0
}
count = 0
for i := 0; i < len(inventory); i++ {
count += max(inventory[i]-thresholdValue, 0)
}
count = orders - count
for i := 0; i < len(inventory); i++ {
if inventory[i] >= thresholdValue {
if count > 0 {
res += (thresholdValue + inventory[i]) * (inventory[i] - thresholdValue + 1) / 2
count--
} else {
res += (thresholdValue + 1 + inventory[i]) * (inventory[i] - thresholdValue) / 2
}
}
}
return res % mod
}
func max(a int, b int) int {
if a > b {
return a
}
return b
}
// 解法二 优先队列,超时!
func maxProfit_(inventory []int, orders int) int {
res, mod := 0, 1000000007
q := PriorityQueue{}
for i := 0; i < len(inventory); i++ {

View File

@ -0,0 +1,63 @@
package leetcode
import (
"fmt"
"testing"
)
type question1648 struct {
para1648
ans1648
}
// para 是参数
// one 代表第一个参数
type para1648 struct {
inventory []int
orders int
}
// ans 是答案
// one 代表第一个答案
type ans1648 struct {
one int
}
func Test_Problem1648(t *testing.T) {
qs := []question1648{
{
para1648{[]int{2, 3, 3, 4, 5}, 4},
ans1648{16},
},
{
para1648{[]int{2, 5}, 4},
ans1648{14},
},
{
para1648{[]int{3, 5}, 6},
ans1648{19},
},
{
para1648{[]int{2, 8, 4, 10, 6}, 20},
ans1648{110},
},
{
para1648{[]int{1000000000}, 1000000000},
ans1648{21},
},
}
fmt.Printf("------------------------Leetcode Problem 1648------------------------\n")
for _, q := range qs {
_, p := q.ans1648, q.para1648
fmt.Printf("【input】:%v 【output】:%v \n", p, maxProfit(p.inventory, p.orders))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,131 @@
# [1648. Sell Diminishing-Valued Colored Balls](https://leetcode.com/problems/sell-diminishing-valued-colored-balls/)
## 题目
You have an `inventory` of different colored balls, and there is a customer that wants `orders` balls of **any** color.
The customer weirdly values the colored balls. Each colored ball's value is the number of balls **of that color** you currently have in your `inventory`. For example, if you own `6` yellow balls, the customer would pay `6` for the first yellow ball. After the transaction, there are only `5` yellow balls left, so the next yellow ball is then valued at `5` (i.e., the value of the balls decreases as you sell more to the customer).
You are given an integer array, `inventory`, where `inventory[i]` represents the number of balls of the `ith` color that you initially own. You are also given an integer `orders`, which represents the total number of balls that the customer wants. You can sell the balls **in any order**.
Return *the **maximum** total value that you can attain after selling* `orders` *colored balls*. As the answer may be too large, return it **modulo** `109 + 7`.
**Example 1:**
![https://assets.leetcode.com/uploads/2020/11/05/jj.gif](https://assets.leetcode.com/uploads/2020/11/05/jj.gif)
```
Input: inventory = [2,5], orders = 4
Output: 14
Explanation: Sell the 1st color 1 time (2) and the 2nd color 3 times (5 + 4 + 3).
The maximum total value is 2 + 5 + 4 + 3 = 14.
```
**Example 2:**
```
Input: inventory = [3,5], orders = 6
Output: 19
Explanation: Sell the 1st color 2 times (3 + 2) and the 2nd color 4 times (5 + 4 + 3 + 2).
The maximum total value is 3 + 2 + 5 + 4 + 3 + 2 = 19.
```
**Example 3:**
```
Input: inventory = [2,8,4,10,6], orders = 20
Output: 110
```
**Example 4:**
```
Input: inventory = [1000000000], orders = 1000000000
Output: 21
Explanation: Sell the 1st color 1000000000 times for a total value of 500000000500000000. 500000000500000000 modulo 109 + 7 = 21.
```
**Constraints:**
- `1 <= inventory.length <= 10^5`
- `1 <= inventory[i] <= 10^9`
- `1 <= orders <= min(sum(inventory[i]), 10^9)`
## 题目大意
你有一些球的库存 inventory 里面包含着不同颜色的球。一个顾客想要 任意颜色 总数为 orders 的球。这位顾客有一种特殊的方式衡量球的价值每个球的价值是目前剩下的 同色球 的数目。比方说还剩下 6 个黄球那么顾客买第一个黄球的时候该黄球的价值为 6 。这笔交易以后只剩下 5 个黄球了所以下一个黄球的价值为 5 也就是球的价值随着顾客购买同色球是递减的
给你整数数组 inventory 其中 inventory[i] 表示第 i 种颜色球一开始的数目。同时给你整数 orders 表示顾客总共想买的球数目。你可以按照 任意顺序 卖球。请你返回卖了 orders 个球以后 最大 总价值之和。由于答案可能会很大,请你返回答案对 109 + 7 取余数 的结果。
提示:
- 1 <= inventory.length <= 10^5
- 1 <= inventory[i] <= 10^9
- 1 <= orders <= min(sum(inventory[i]), 10^9)
## 解题思路
- 给出一个 `inventory` 数组和 `orders` 次操作,要求输出数组中前 `orders` 大个元素累加和。需要注意的是,每累加一个元素 `inventory[i]`,这个元素都会减一,下次再累加的时候,需要选取更新以后的数组的最大值。
- 拿到这个题目以后很容易想到优先队列,建立大根堆以后,`pop` 出当前最大值 `maxItem`,累加,以后把 `maxItem` 减一再 `push` 回去。循环执行 `orders` 次以后即是最终结果。题目是这个意思,但是我们不能这么写代码,因为题目条件里面给出了 `orders` 的数据大小。orders 最大为 10^9。按照优先队列的这个方法一定会超时时间复杂度为 O(orders⋅logn)。那就换一个思路。优先队列这个思路中,重复操作了 `orders` 次,其实在这些操作中,有一些是没有必要的废操作。这些大量的“废”操作导致了超时。试想,在 `orders` 次操作中,能否合并 `n``pop` 操作,一口气先 `pop``n` 个前 `n` 大的数呢?这个是可行的,因为每次 `pop` 出去,元素都只会减一,这个是非常有规律的。
- 为了接下来的描述更加清晰易懂,还需要再定义 1 个值, `thresholdValue` 为操作 `n` 次以后,当前 `inventory` 数组的最大值。关于 `thresholdValue` 的理解,这里要说明一下。 `thresholdValue` 的来源有 2 种,一种是本来数组里面就有这个值,还有一种来源是 `inventory[i]` 元素减少到了 `thresholdValue` 这个值。举个例子:原始数组是 [2,3,3,4,5]`orders` = 4取 4 次以后,剩下的数组是 [2,2,3,3,3]。3 个 3 里面其中一个 3 就来自于 `4-1=3`,或者 `5-2=3`
- 用二分搜索在 [0max(`inventory`)] 区间内找到这个 `thresholdValue` 值,能满足下列不等式的最小 `thresholdValue` 值:
$$\sum_{inventory[i]\geqslant thresholdValue}^{} \left ( inventory[i] - thresholdValue \right )\leqslant orders$$
`thresholdValue` 越小,不等式左边的值越大,随着 `thresholdValue` 的增大,不等式左边的值越来越小,直到刚刚能小于等于 `orders`。求出了 `thresholdValue` 值以后,还需要再判断有多少值等于 `thresholdValue - 1` 值了。
![https://img.halfrost.com/Leetcode/leetcode_1648.png](https://img.halfrost.com/Leetcode/leetcode_1648.png)
- 还是举上面的例子,原始数组是 [2,3,3,4,5]`orders` = 4我们可以求得 `thresholdValue` = 3 。`inventory[i]` > `thresholdValue` 的那部分 100% 的要取走,`thresholdValue` 就像一个水平面,突出水平面的那些都要拿走,每列的值按照等差数列求和公式计算即可。但是 `orders` - `thresholdValue` = 1说明水平面以下还要拿走一个`thresholdValue` 线下的虚线框里面的那 4 个球,还需要任意取走一个。最后总的结果是这 2 部分的总和,( ( 5 + 4 ) + 4 ) + 3 = 16 。
## 代码
```go
package leetcode
import (
"container/heap"
)
// 解法一 贪心 + 二分搜索
func maxProfit(inventory []int, orders int) int {
maxItem, thresholdValue, count, res, mod := 0, -1, 0, 0, 1000000007
for i := 0; i < len(inventory); i++ {
if inventory[i] > maxItem {
maxItem = inventory[i]
}
}
low, high := 0, maxItem
for low <= high {
mid := low + ((high - low) >> 1)
for i := 0; i < len(inventory); i++ {
count += max(inventory[i]-mid, 0)
}
if count <= orders {
thresholdValue = mid
high = mid - 1
} else {
low = mid + 1
}
count = 0
}
count = 0
for i := 0; i < len(inventory); i++ {
count += max(inventory[i]-thresholdValue, 0)
}
count = orders - count
for i := 0; i < len(inventory); i++ {
if inventory[i] >= thresholdValue {
if count > 0 {
res += (thresholdValue + inventory[i]) * (inventory[i] - thresholdValue + 1) / 2
count--
} else {
res += (thresholdValue + 1 + inventory[i]) * (inventory[i] - thresholdValue) / 2
}
}
}
return res % mod
}
```

View File

@ -0,0 +1,106 @@
package leetcode
import (
"github.com/halfrost/LeetCode-Go/template"
"sort"
)
// 解法一 线段树 SegmentTree
func createSortedArray(instructions []int) int {
if len(instructions) == 0 {
return 0
}
st, res, mod := template.SegmentCountTree{}, 0, 1000000007
numsMap, numsArray, tmpArray := discretization1649(instructions)
// 初始化线段树,节点内的值都赋值为 0即计数为 0
st.Init(tmpArray, func(i, j int) int {
return 0
})
for i := 0; i < len(instructions); i++ {
strictlyLessThan := st.Query(0, numsMap[instructions[i]]-1)
strictlyGreaterThan := st.Query(numsMap[instructions[i]]+1, numsArray[len(numsArray)-1])
res = (res + min(strictlyLessThan, strictlyGreaterThan)) % mod
st.UpdateCount(numsMap[instructions[i]])
}
return res
}
func discretization1649(instructions []int) (map[int]int, []int, []int) {
tmpArray, numsArray, numsMap := []int{}, []int{}, map[int]int{}
for i := 0; i < len(instructions); i++ {
numsMap[instructions[i]] = instructions[i]
}
for _, v := range numsMap {
numsArray = append(numsArray, v)
}
sort.Ints(numsArray)
for i, num := range numsArray {
numsMap[num] = i
}
for i := range numsArray {
tmpArray = append(tmpArray, i)
}
return numsMap, numsArray, tmpArray
}
func min(a int, b int) int {
if a > b {
return b
}
return a
}
// 解法二 树状数组 Binary Indexed Tree
func createSortedArray1(instructions []int) int {
b := newBIT(make([]int, 100001))
var res int
cnt := map[int]int{}
for i, n := range instructions {
less := b.get(n - 1)
greater := i - less - cnt[n]
res = (res + min(less, greater)) % (1e9 + 7)
b.update(n, 1)
cnt[n]++
}
return res % (1e9 + 7)
}
func max(x, y int) int {
if x > y {
return x
}
return y
}
type BIT struct {
data []int
}
func newBIT(nums []int) *BIT {
data := make([]int, len(nums)+1)
b := &BIT{data}
for i, n := range nums {
b.update(i, n)
}
return b
}
func (b *BIT) update(i, num int) {
i++
for i < len(b.data) {
b.data[i] += num
i += (i & -i)
}
}
func (b *BIT) get(i int) int {
i++
var sum int
for i > 0 {
sum += b.data[i]
i -= (i & -i)
}
return sum
}

View File

@ -0,0 +1,52 @@
package leetcode
import (
"fmt"
"testing"
)
type question1649 struct {
para1649
ans1649
}
// para 是参数
// one 代表第一个参数
type para1649 struct {
instructions []int
}
// ans 是答案
// one 代表第一个答案
type ans1649 struct {
one int
}
func Test_Problem1649(t *testing.T) {
qs := []question1649{
{
para1649{[]int{1, 5, 6, 2}},
ans1649{1},
},
{
para1649{[]int{1, 2, 3, 6, 5, 4}},
ans1649{3},
},
{
para1649{[]int{1, 3, 3, 3, 2, 4, 2, 1, 2}},
ans1649{4},
},
}
fmt.Printf("------------------------Leetcode Problem 1649------------------------\n")
for _, q := range qs {
_, p := q.ans1649, q.para1649
fmt.Printf("【input】:%v 【output】:%v \n", p, createSortedArray(p.instructions))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,189 @@
# [1649. Create Sorted Array through Instructions](https://leetcode.com/problems/create-sorted-array-through-instructions/)
## 题目
Given an integer array `instructions`, you are asked to create a sorted array from the elements in `instructions`. You start with an empty container `nums`. For each element from **left to right** in `instructions`, insert it into `nums`. The **cost** of each insertion is the **minimum** of the following:
- The number of elements currently in `nums` that are **strictly less than** `instructions[i]`.
- The number of elements currently in `nums` that are **strictly greater than** `instructions[i]`.
For example, if inserting element `3` into `nums = [1,2,3,5]`, the **cost** of insertion is `min(2, 1)` (elements `1` and `2` are less than `3`, element `5` is greater than `3`) and `nums` will become `[1,2,3,3,5]`.
Return *the **total cost** to insert all elements from* `instructions` *into* `nums`. Since the answer may be large, return it **modulo** `10^9 + 7`
**Example 1:**
```
Input: instructions = [1,5,6,2]
Output: 1
Explanation: Begin with nums = [].
Insert 1 with cost min(0, 0) = 0, now nums = [1].
Insert 5 with cost min(1, 0) = 0, now nums = [1,5].
Insert 6 with cost min(2, 0) = 0, now nums = [1,5,6].
Insert 2 with cost min(1, 2) = 1, now nums = [1,2,5,6].
The total cost is 0 + 0 + 0 + 1 = 1.
```
**Example 2:**
```
Input: instructions = [1,2,3,6,5,4]
Output: 3
Explanation: Begin with nums = [].
Insert 1 with cost min(0, 0) = 0, now nums = [1].
Insert 2 with cost min(1, 0) = 0, now nums = [1,2].
Insert 3 with cost min(2, 0) = 0, now nums = [1,2,3].
Insert 6 with cost min(3, 0) = 0, now nums = [1,2,3,6].
Insert 5 with cost min(3, 1) = 1, now nums = [1,2,3,5,6].
Insert 4 with cost min(3, 2) = 2, now nums = [1,2,3,4,5,6].
The total cost is 0 + 0 + 0 + 0 + 1 + 2 = 3.
```
**Example 3:**
```
Input: instructions = [1,3,3,3,2,4,2,1,2]
Output: 4
Explanation: Begin with nums = [].
Insert 1 with cost min(0, 0) = 0, now nums = [1].
Insert 3 with cost min(1, 0) = 0, now nums = [1,3].
Insert 3 with cost min(1, 0) = 0, now nums = [1,3,3].
Insert 3 with cost min(1, 0) = 0, now nums = [1,3,3,3].
Insert 2 with cost min(1, 3) = 1, now nums = [1,2,3,3,3].
Insert 4 with cost min(5, 0) = 0, now nums = [1,2,3,3,3,4].
Insert 2 with cost min(1, 4) = 1, now nums = [1,2,2,3,3,3,4].
Insert 1 with cost min(0, 6) = 0, now nums = [1,1,2,2,3,3,3,4].
Insert 2 with cost min(2, 4) = 2, now nums = [1,1,2,2,2,3,3,3,4].
The total cost is 0 + 0 + 0 + 0 + 1 + 0 + 1 + 0 + 2 = 4.
```
**Constraints:**
- `1 <= instructions.length <= 105`
- `1 <= instructions[i] <= 105`
## 题目大意
给你一个整数数组 instructions 你需要根据 instructions 中的元素创建一个有序数组。一开始你有一个空的数组 nums 你需要 从左到右 遍历 instructions 中的元素将它们依次插入 nums 数组中。每一次插入操作的 代价 是以下两者的 较小值 :
- nums 中 严格小于 instructions[i] 的数字数目。
- nums 中 严格大于 instructions[i] 的数字数目。
比方说如果要将 3 插入到 nums = [1,2,3,5] 那么插入操作的 代价  min(2, 1) (元素 1  2 小于 3 元素 5 大于 3 插入后 nums 变成 [1,2,3,3,5] 。请你返回将 instructions 中所有元素依次插入 nums 后的 总最小代价 。由于答案会很大请将它对 10^9 + 7 取余 后返回。
## 解题思路
- 给出一个数组,要求将其中的元素从头开始往另外一个空数组中插入,每次插入前,累加代价值 cost = min(**strictly less than**, **strictly greater than**)。最后输出累加值。
- 这一题虽然是 Hard 题,但是读完题以后就可以判定这是模板题了。可以用线段树和树状数组来解决。这里简单说说线段树的思路吧,先将待插入的数组排序,获得总的区间。每次循环做 4 步2 次 `query` 分别得到 `strictlyLessThan``strictlyGreaterThan` ,再比较出两者中的最小值累加,最后一步就是 `update`
- 由于题目给的数据比较大,所以建立线段树之前记得要先离散化。这一题核心代码不超过 10 行,其他的都是模板代码。具体实现见代码。
## 代码
```go
package leetcode
import (
"github.com/halfrost/LeetCode-Go/template"
"sort"
)
// 解法一 线段树 SegmentTree
func createSortedArray(instructions []int) int {
if len(instructions) == 0 {
return 0
}
st, res, mod := template.SegmentCountTree{}, 0, 1000000007
numsMap, numsArray, tmpArray := discretization1649(instructions)
// 初始化线段树,节点内的值都赋值为 0即计数为 0
st.Init(tmpArray, func(i, j int) int {
return 0
})
for i := 0; i < len(instructions); i++ {
strictlyLessThan := st.Query(0, numsMap[instructions[i]]-1)
strictlyGreaterThan := st.Query(numsMap[instructions[i]]+1, numsArray[len(numsArray)-1])
res = (res + min(strictlyLessThan, strictlyGreaterThan)) % mod
st.UpdateCount(numsMap[instructions[i]])
}
return res
}
func discretization1649(instructions []int) (map[int]int, []int, []int) {
tmpArray, numsArray, numsMap := []int{}, []int{}, map[int]int{}
for i := 0; i < len(instructions); i++ {
numsMap[instructions[i]] = instructions[i]
}
for _, v := range numsMap {
numsArray = append(numsArray, v)
}
sort.Ints(numsArray)
for i, num := range numsArray {
numsMap[num] = i
}
for i := range numsArray {
tmpArray = append(tmpArray, i)
}
return numsMap, numsArray, tmpArray
}
func min(a int, b int) int {
if a > b {
return b
}
return a
}
// 解法二 树状数组 Binary Indexed Tree
func createSortedArray1(instructions []int) int {
b := newBIT(make([]int, 100001))
var res int
cnt := map[int]int{}
for i, n := range instructions {
less := b.get(n - 1)
greater := i - less - cnt[n]
res = (res + min(less, greater)) % (1e9 + 7)
b.update(n, 1)
cnt[n]++
}
return res % (1e9 + 7)
}
func max(x, y int) int {
if x > y {
return x
}
return y
}
type BIT struct {
data []int
}
func newBIT(nums []int) *BIT {
data := make([]int, len(nums)+1)
b := &BIT{data}
for i, n := range nums {
b.update(i, n)
}
return b
}
func (b *BIT) update(i, num int) {
i++
for i < len(b.data) {
b.data[i] += num
i += (i & -i)
}
}
func (b *BIT) get(i int) int {
i++
var sum int
for i > 0 {
sum += b.data[i]
i -= (i & -i)
}
return sum
}
```

View File

@ -1,62 +0,0 @@
package leetcode
import (
"fmt"
"testing"
)
type question5561 struct {
para5561
ans5561
}
// para 是参数
// one 代表第一个参数
type para5561 struct {
n int
}
// ans 是答案
// one 代表第一个答案
type ans5561 struct {
one int
}
func Test_Problem5561(t *testing.T) {
qs := []question5561{
{
para5561{7},
ans5561{3},
},
{
para5561{2},
ans5561{1},
},
{
para5561{3},
ans5561{2},
},
{
para5561{0},
ans5561{0},
},
{
para5561{1},
ans5561{1},
},
}
fmt.Printf("------------------------Leetcode Problem 5561------------------------\n")
for _, q := range qs {
_, p := q.ans5561, q.para5561
fmt.Printf("【input】:%v 【output】:%v \n", p, getMaximumGenerated(p.n))
}
fmt.Printf("\n\n\n")
}

View File

@ -1,62 +0,0 @@
package leetcode
import (
"fmt"
"testing"
)
type question5562 struct {
para5562
ans5562
}
// para 是参数
// one 代表第一个参数
type para5562 struct {
s string
}
// ans 是答案
// one 代表第一个答案
type ans5562 struct {
one int
}
func Test_Problem5562(t *testing.T) {
qs := []question5562{
{
para5562{"aab"},
ans5562{0},
},
{
para5562{"aaabbbcc"},
ans5562{2},
},
{
para5562{"ceabaacb"},
ans5562{2},
},
{
para5562{""},
ans5562{0},
},
{
para5562{"abcabc"},
ans5562{3},
},
}
fmt.Printf("------------------------Leetcode Problem 5562------------------------\n")
for _, q := range qs {
_, p := q.ans5562, q.para5562
fmt.Printf("【input】:%v 【output】:%v \n", p, minDeletions(p.s))
}
fmt.Printf("\n\n\n")
}

View File

@ -1,58 +0,0 @@
package leetcode
import (
"fmt"
"testing"
)
type question5563 struct {
para5563
ans5563
}
// para 是参数
// one 代表第一个参数
type para5563 struct {
inventory []int
orders int
}
// ans 是答案
// one 代表第一个答案
type ans5563 struct {
one int
}
func Test_Problem5563(t *testing.T) {
qs := []question5563{
{
para5563{[]int{2, 5}, 4},
ans5563{14},
},
{
para5563{[]int{3, 5}, 6},
ans5563{19},
},
{
para5563{[]int{2, 8, 4, 10, 6}, 20},
ans5563{110},
},
{
para5563{[]int{1000000000}, 1000000000},
ans5563{21},
},
}
fmt.Printf("------------------------Leetcode Problem 5563------------------------\n")
for _, q := range qs {
_, p := q.ans5563, q.para5563
fmt.Printf("【input】:%v 【output】:%v \n", p, maxProfit(p.inventory, p.orders))
}
fmt.Printf("\n\n\n")
}