Add solution 1668、1669、1670、1672、1673

This commit is contained in:
YDZ
2020-12-16 03:08:19 +08:00
parent 2e796fe70e
commit e85f3236f4
30 changed files with 1266 additions and 428 deletions

View File

@ -5,48 +5,48 @@ import (
"testing"
)
type question1665 struct {
para1665
ans1665
type question1668 struct {
para1668
ans1668
}
// para 是参数
// one 代表第一个参数
type para1665 struct {
type para1668 struct {
sequence string
word string
}
// ans 是答案
// one 代表第一个答案
type ans1665 struct {
type ans1668 struct {
one int
}
func Test_Problem1665(t *testing.T) {
func Test_Problem1668(t *testing.T) {
qs := []question1665{
qs := []question1668{
{
para1665{"ababc", "ab"},
ans1665{2},
para1668{"ababc", "ab"},
ans1668{2},
},
{
para1665{"ababc", "ba"},
ans1665{1},
para1668{"ababc", "ba"},
ans1668{1},
},
{
para1665{"ababc", "ac"},
ans1665{0},
para1668{"ababc", "ac"},
ans1668{0},
},
}
fmt.Printf("------------------------Leetcode Problem 1665------------------------\n")
fmt.Printf("------------------------Leetcode Problem 1668------------------------\n")
for _, q := range qs {
_, p := q.ans1665, q.para1665
_, p := q.ans1668, q.para1668
fmt.Printf("【input】:%v 【output】:%v \n", p, maxRepeating(p.sequence, p.word))
}
fmt.Printf("\n\n\n")

View File

@ -0,0 +1,69 @@
# [1668. Maximum Repeating Substring](https://leetcode.com/problems/maximum-repeating-substring/)
## 题目
For a string `sequence`, a string `word` is **`k`-repeating** if `word` concatenated `k` times is a substring of `sequence`. The `word`'s **maximum `k`-repeating value** is the highest value `k` where `word` is `k`-repeating in `sequence`. If `word` is not a substring of `sequence`, `word`'s maximum `k`-repeating value is `0`.
Given strings `sequence` and `word`, return *the **maximum `k`-repeating value** of `word` in `sequence`*.
**Example 1:**
```
Input: sequence = "ababc", word = "ab"
Output: 2
Explanation: "abab" is a substring in "ababc".
```
**Example 2:**
```
Input: sequence = "ababc", word = "ba"
Output: 1
Explanation: "ba" is a substring in "ababc". "baba" is not a substring in "ababc".
```
**Example 3:**
```
Input: sequence = "ababc", word = "ac"
Output: 0
Explanation: "ac" is not a substring in "ababc".
```
**Constraints:**
- `1 <= sequence.length <= 100`
- `1 <= word.length <= 100`
- `sequence` and `word` contains only lowercase English letters.
## 题目大意
给你一个字符串 sequence 如果字符串 word 连续重复 k 次形成的字符串是 sequence 的一个子字符串那么单词 word 的 重复值为 k 。单词 word 的 最大重复值 是单词 word  sequence 中最大的重复值。如果 word 不是 sequence 的子串那么重复值 k 为 0 。给你一个字符串 sequence 和 word 请你返回 最大重复值 k 。
## 解题思路
- 循环叠加构造 `word`,每次构造出新的 `word` 都在 `sequence` 查找一次,如果找到就输出叠加次数,否则继续叠加构造,直到字符串长度和 `sequence` 一样长,最终都没有找到则输出 0 。
## 代码
```go
package leetcode
import (
"strings"
)
func maxRepeating(sequence string, word string) int {
for i := len(sequence) / len(word); i >= 0; i-- {
tmp := ""
for j := 0; j < i; j++ {
tmp += word
}
if strings.Contains(sequence, tmp) {
return i
}
}
return 0
}
```

View File

@ -0,0 +1,37 @@
package leetcode
import (
"github.com/halfrost/LeetCode-Go/structures"
)
// ListNode define
type ListNode = structures.ListNode
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func mergeInBetween(list1 *ListNode, a int, b int, list2 *ListNode) *ListNode {
n := list1
var startRef, endRef *ListNode
for i := 0; i <= b; i++ {
if i == a-1 {
startRef = n
}
if i == b {
endRef = n
}
n = n.Next
}
startRef.Next = list2
n = list2
for n.Next != nil {
n = n.Next
}
n.Next = endRef.Next
return list1
}

View File

@ -0,0 +1,62 @@
package leetcode
import (
"fmt"
"testing"
"github.com/halfrost/LeetCode-Go/structures"
)
type question1669 struct {
para1669
ans1669
}
// para 是参数
// one 代表第一个参数
type para1669 struct {
one []int
a int
b int
another []int
}
// ans 是答案
// one 代表第一个答案
type ans1669 struct {
one []int
}
func Test_Problem1669(t *testing.T) {
qs := []question1669{
{
para1669{[]int{0, 1, 2, 3, 4, 5}, 3, 4, []int{1000000, 1000001, 1000002}},
ans1669{[]int{0, 1, 2, 1000000, 1000001, 1000002, 5}},
},
{
para1669{[]int{0, 1, 2, 3, 4, 5, 6}, 2, 5, []int{1000000, 1000001, 1000002, 1000003, 1000004}},
ans1669{[]int{0, 1, 1000000, 1000001, 1000002, 1000003, 1000004, 6}},
},
{
para1669{[]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, 3, 5, []int{1000000, 1000001, 1000002, 1000003, 1000004, 1000005, 1000006}},
ans1669{[]int{0, 1, 2, 1000000, 1000001, 1000002, 1000003, 1000004, 1000005, 1000006, 6, 7, 8, 9}},
},
{
para1669{[]int{0, 1, 2}, 1, 1, []int{1000000, 1000001, 1000002, 1000003}},
ans1669{[]int{0, 1000000, 1000001, 1000002, 1000003, 2}},
},
}
fmt.Printf("------------------------Leetcode Problem 1669------------------------\n")
for _, q := range qs {
_, p := q.ans1669, q.para1669
fmt.Printf("【input】:%v 【output】:%v\n", p, structures.List2Ints(mergeInBetween(structures.Ints2List(p.one), p.a, p.b, structures.Ints2List(p.another))))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,75 @@
# [1669. Merge In Between Linked Lists](https://leetcode.com/problems/merge-in-between-linked-lists/)
## 题目
You are given two linked lists: `list1` and `list2` of sizes `n` and `m` respectively.
Remove `list1`'s nodes from the `ath` node to the `bth` node, and put `list2` in their place.
The blue edges and nodes in the following figure incidate the result:
![https://assets.leetcode.com/uploads/2020/11/05/fig1.png](https://assets.leetcode.com/uploads/2020/11/05/fig1.png)
*Build the result list and return its head.*
**Example 1:**
![https://assets.leetcode.com/uploads/2020/11/05/merge_linked_list_ex1.png](https://assets.leetcode.com/uploads/2020/11/05/merge_linked_list_ex1.png)
```
Input: list1 = [0,1,2,3,4,5], a = 3, b = 4, list2 = [1000000,1000001,1000002]
Output: [0,1,2,1000000,1000001,1000002,5]
Explanation: We remove the nodes 3 and 4 and put the entire list2 in their place. The blue edges and nodes in the above figure indicate the result.
```
**Example 2:**
![https://assets.leetcode.com/uploads/2020/11/05/merge_linked_list_ex2.png](https://assets.leetcode.com/uploads/2020/11/05/merge_linked_list_ex2.png)
```
Input: list1 = [0,1,2,3,4,5,6], a = 2, b = 5, list2 = [1000000,1000001,1000002,1000003,1000004]
Output: [0,1,1000000,1000001,1000002,1000003,1000004,6]
Explanation: The blue edges and nodes in the above figure indicate the result.
```
**Constraints:**
- `3 <= list1.length <= 104`
- `1 <= a <= b < list1.length - 1`
- `1 <= list2.length <= 104`
## 题目大意
给你两个链表 list1 和 list2 它们包含的元素分别为 n 个和 m 个。请你将 list1 中第 a 个节点到第 b 个节点删除并将list2 接在被删除节点的位置。
## 解题思路
- 简单题,考查链表的基本操作。此题注意 a == b 的情况。
## 代码
```go
func mergeInBetween(list1 *ListNode, a int, b int, list2 *ListNode) *ListNode {
n := list1
var startRef, endRef *ListNode
for i := 0; i <= b; i++ {
if i == a-1 {
startRef = n
}
if i == b {
endRef = n
}
n = n.Next
}
startRef.Next = list2
n = list2
for n.Next != nil {
n = n.Next
}
n.Next = endRef.Next
return list1
}
```

View File

@ -0,0 +1,94 @@
package leetcode
import (
"container/list"
)
type FrontMiddleBackQueue struct {
list *list.List
middle *list.Element
}
func Constructor() FrontMiddleBackQueue {
return FrontMiddleBackQueue{list: list.New()}
}
func (this *FrontMiddleBackQueue) PushFront(val int) {
e := this.list.PushFront(val)
if this.middle == nil {
this.middle = e
} else if this.list.Len()%2 == 0 && this.middle.Prev() != nil {
this.middle = this.middle.Prev()
}
}
func (this *FrontMiddleBackQueue) PushMiddle(val int) {
if this.middle == nil {
this.PushFront(val)
} else {
if this.list.Len()%2 != 0 {
this.middle = this.list.InsertBefore(val, this.middle)
} else {
this.middle = this.list.InsertAfter(val, this.middle)
}
}
}
func (this *FrontMiddleBackQueue) PushBack(val int) {
e := this.list.PushBack(val)
if this.middle == nil {
this.middle = e
} else if this.list.Len()%2 != 0 && this.middle.Next() != nil {
this.middle = this.middle.Next()
}
}
func (this *FrontMiddleBackQueue) PopFront() int {
if this.list.Len() == 0 {
return -1
}
e := this.list.Front()
if this.list.Len() == 1 {
this.middle = nil
} else if this.list.Len()%2 == 0 && this.middle.Next() != nil {
this.middle = this.middle.Next()
}
return this.list.Remove(e).(int)
}
func (this *FrontMiddleBackQueue) PopMiddle() int {
if this.middle == nil {
return -1
}
e := this.middle
if this.list.Len()%2 != 0 {
this.middle = e.Prev()
} else {
this.middle = e.Next()
}
return this.list.Remove(e).(int)
}
func (this *FrontMiddleBackQueue) PopBack() int {
if this.list.Len() == 0 {
return -1
}
e := this.list.Back()
if this.list.Len() == 1 {
this.middle = nil
} else if this.list.Len()%2 != 0 && this.middle.Prev() != nil {
this.middle = this.middle.Prev()
}
return this.list.Remove(e).(int)
}
/**
* Your FrontMiddleBackQueue object will be instantiated and called as such:
* obj := Constructor();
* obj.PushFront(val);
* obj.PushMiddle(val);
* obj.PushBack(val);
* param_4 := obj.PopFront();
* param_5 := obj.PopMiddle();
* param_6 := obj.PopBack();
*/

View File

@ -5,7 +5,7 @@ import (
"testing"
)
func Test_Problem707(t *testing.T) {
func Test_Problem1670(t *testing.T) {
obj := Constructor()
fmt.Printf("obj = %v %v\n", MList2Ints(&obj), obj)
obj.PushFront(1)
@ -102,6 +102,11 @@ func Test_Problem707(t *testing.T) {
// [[],[],[3],[6],[6],[3],[],[7],[],[8]]
}
func MList2Ints(head *FrontMiddleBackQueue) []int {
return head.Queue
func MList2Ints(this *FrontMiddleBackQueue) []int {
array := []int{}
for e := this.list.Front(); e != nil; e = e.Next() {
value, _ := e.Value.(int)
array = append(array, value)
}
return array
}

View File

@ -0,0 +1,172 @@
# [1670. Design Front Middle Back Queue](https://leetcode.com/problems/design-front-middle-back-queue/)
## 题目
Design a queue that supports `push` and `pop` operations in the front, middle, and back.
Implement the `FrontMiddleBack` class:
- `FrontMiddleBack()` Initializes the queue.
- `void pushFront(int val)` Adds `val` to the **front** of the queue.
- `void pushMiddle(int val)` Adds `val` to the **middle** of the queue.
- `void pushBack(int val)` Adds `val` to the **back** of the queue.
- `int popFront()` Removes the **front** element of the queue and returns it. If the queue is empty, return `1`.
- `int popMiddle()` Removes the **middle** element of the queue and returns it. If the queue is empty, return `1`.
- `int popBack()` Removes the **back** element of the queue and returns it. If the queue is empty, return `1`.
**Notice** that when there are **two** middle position choices, the operation is performed on the **frontmost** middle position choice. For example:
- Pushing `6` into the middle of `[1, 2, 3, 4, 5]` results in `[1, 2, 6, 3, 4, 5]`.
- Popping the middle from `[1, 2, 3, 4, 5, 6]` returns `3` and results in `[1, 2, 4, 5, 6]`.
**Example 1:**
```
Input:
["FrontMiddleBackQueue", "pushFront", "pushBack", "pushMiddle", "pushMiddle", "popFront", "popMiddle", "popMiddle", "popBack", "popFront"]
[[], [1], [2], [3], [4], [], [], [], [], []]
Output:
[null, null, null, null, null, 1, 3, 4, 2, -1]
Explanation:
FrontMiddleBackQueue q = new FrontMiddleBackQueue();
q.pushFront(1); // [1]
q.pushBack(2); // [1, 2]
q.pushMiddle(3); // [1, 3, 2]
q.pushMiddle(4); // [1, 4, 3, 2]
q.popFront(); // return 1 -> [4, 3, 2]
q.popMiddle(); // return 3 -> [4, 2]
q.popMiddle(); // return 4 -> [2]
q.popBack(); // return 2 -> []
q.popFront(); // return -1 -> [] (The queue is empty)
```
**Constraints:**
- `1 <= val <= 109`
- At most `1000` calls will be made to `pushFront`, `pushMiddle`, `pushBack`, `popFront`, `popMiddle`, and `popBack`.
## 题目大意
请你设计一个队列,支持在前,中,后三个位置的 push 和 pop 操作。
请你完成 FrontMiddleBack 
- FrontMiddleBack() 初始化队列。
- void pushFront(int val) 将 val 添加到队列的 最前面 。
- void pushMiddle(int val) 将 val 添加到队列的 正中间 。
- void pushBack(int val)  val 添加到队里的 最后面 。
- int popFront() 将 最前面 的元素从队列中删除并返回值,如果删除之前队列为空,那么返回 -1 
- int popMiddle() 将 正中间 的元素从队列中删除并返回值,如果删除之前队列为空,那么返回 -1 
- int popBack() 将 最后面 的元素从队列中删除并返回值,如果删除之前队列为空,那么返回 -1 
请注意当有 两个 中间位置的时候,选择靠前面的位置进行操作。比方说:
- 将 6 添加到 [1, 2, 3, 4, 5] 的中间位置,结果数组为 [1, 2, 6, 3, 4, 5] 。
- 从 [1, 2, 3, 4, 5, 6] 的中间位置弹出元素返回 3 数组变为 [1, 2, 4, 5, 6] 。
## 解题思路
- 简单题,利用 go 原生的双向队列 list 的实现,可以轻松实现这个“前中后队列”。
- 具体实现见代码,几组特殊测试用例见测试文件。
## 代码
```go
package leetcode
import (
"container/list"
)
type FrontMiddleBackQueue struct {
list *list.List
middle *list.Element
}
func Constructor() FrontMiddleBackQueue {
return FrontMiddleBackQueue{list: list.New()}
}
func (this *FrontMiddleBackQueue) PushFront(val int) {
e := this.list.PushFront(val)
if this.middle == nil {
this.middle = e
} else if this.list.Len()%2 == 0 && this.middle.Prev() != nil {
this.middle = this.middle.Prev()
}
}
func (this *FrontMiddleBackQueue) PushMiddle(val int) {
if this.middle == nil {
this.PushFront(val)
} else {
if this.list.Len()%2 != 0 {
this.middle = this.list.InsertBefore(val, this.middle)
} else {
this.middle = this.list.InsertAfter(val, this.middle)
}
}
}
func (this *FrontMiddleBackQueue) PushBack(val int) {
e := this.list.PushBack(val)
if this.middle == nil {
this.middle = e
} else if this.list.Len()%2 != 0 && this.middle.Next() != nil {
this.middle = this.middle.Next()
}
}
func (this *FrontMiddleBackQueue) PopFront() int {
if this.list.Len() == 0 {
return -1
}
e := this.list.Front()
if this.list.Len() == 1 {
this.middle = nil
} else if this.list.Len()%2 == 0 && this.middle.Next() != nil {
this.middle = this.middle.Next()
}
return this.list.Remove(e).(int)
}
func (this *FrontMiddleBackQueue) PopMiddle() int {
if this.middle == nil {
return -1
}
e := this.middle
if this.list.Len()%2 != 0 {
this.middle = e.Prev()
} else {
this.middle = e.Next()
}
return this.list.Remove(e).(int)
}
func (this *FrontMiddleBackQueue) PopBack() int {
if this.list.Len() == 0 {
return -1
}
e := this.list.Back()
if this.list.Len() == 1 {
this.middle = nil
} else if this.list.Len()%2 != 0 && this.middle.Prev() != nil {
this.middle = this.middle.Prev()
}
return this.list.Remove(e).(int)
}
/**
* Your FrontMiddleBackQueue object will be instantiated and called as such:
* obj := Constructor();
* obj.PushFront(val);
* obj.PushMiddle(val);
* obj.PushBack(val);
* param_4 := obj.PopFront();
* param_5 := obj.PopMiddle();
* param_6 := obj.PopBack();
*/
```

View File

@ -0,0 +1,15 @@
package leetcode
func maximumWealth(accounts [][]int) int {
res := 0
for _, banks := range accounts {
sAmount := 0
for _, amount := range banks {
sAmount += amount
}
if sAmount > res {
res = sAmount
}
}
return res
}

View File

@ -0,0 +1,52 @@
package leetcode
import (
"fmt"
"testing"
)
type question1672 struct {
para1672
ans1672
}
// para 是参数
// one 代表第一个参数
type para1672 struct {
accounts [][]int
}
// ans 是答案
// one 代表第一个答案
type ans1672 struct {
one int
}
func Test_Problem1672(t *testing.T) {
qs := []question1672{
{
para1672{[][]int{{1, 2, 3}, {3, 2, 1}}},
ans1672{6},
},
{
para1672{[][]int{{1, 5}, {7, 3}, {3, 5}}},
ans1672{10},
},
{
para1672{[][]int{{2, 8, 7}, {7, 1, 3}, {1, 9, 5}}},
ans1672{17},
},
}
fmt.Printf("------------------------Leetcode Problem 1672------------------------\n")
for _, q := range qs {
_, p := q.ans1672, q.para1672
fmt.Printf("【input】:%v 【output】:%v\n", p, maximumWealth(p.accounts))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,72 @@
# [1672. Richest Customer Wealth](https://leetcode.com/problems/richest-customer-wealth/)
## 题目
You are given an `m x n` integer grid `accounts` where `accounts[i][j]` is the amount of money the `ith` customer has in the `jth` bank. Return *the **wealth** that the richest customer has.*
A customer's **wealth** is the amount of money they have in all their bank accounts. The richest customer is the customer that has the maximum **wealth**.
**Example 1:**
```
Input: accounts = [[1,2,3],[3,2,1]]
Output: 6
Explanation:1st customer has wealth = 1 + 2 + 3 = 6
2nd customer has wealth = 3 + 2 + 1 = 6
Both customers are considered the richest with a wealth of 6 each, so return 6.
```
**Example 2:**
```
Input: accounts = [[1,5],[7,3],[3,5]]
Output: 10
Explanation:
1st customer has wealth = 6
2nd customer has wealth = 10
3rd customer has wealth = 8
The 2nd customer is the richest with a wealth of 10.
```
**Example 3:**
```
Input: accounts = [[2,8,7],[7,1,3],[1,9,5]]
Output: 17
```
**Constraints:**
- `m == accounts.length`
- `n == accounts[i].length`
- `1 <= m, n <= 50`
- `1 <= accounts[i][j] <= 100`
## 题目大意
给你一个 m x n 的整数网格 accounts ,其中 accounts[i][j] 是第 i 位客户在第 j 家银行托管的资产数量。返回最富有客户所拥有的 资产总量 。客户的 资产总量 就是他们在各家银行托管的资产数量之和。最富有客户就是 资产总量 最大的客户。
## 解题思路
- 简单题。计算二维数组中每个一位数组的元素总和,然后动态维护这些一位数组和的最大值即可。
## 代码
```go
package leetcode
func maximumWealth(accounts [][]int) int {
res := 0
for _, banks := range accounts {
sAmount := 0
for _, amount := range banks {
sAmount += amount
}
if sAmount > res {
res = sAmount
}
}
return res
}
```

View File

@ -0,0 +1,13 @@
package leetcode
// 单调栈
func mostCompetitive(nums []int, k int) []int {
stack := make([]int, 0, len(nums))
for i := 0; i < len(nums); i++ {
for len(stack)+len(nums)-i > k && len(stack) > 0 && nums[i] < stack[len(stack)-1] {
stack = stack[:len(stack)-1]
}
stack = append(stack, nums[i])
}
return stack[:k]
}

View File

@ -0,0 +1,63 @@
package leetcode
import (
"fmt"
"testing"
)
type question1673 struct {
para1673
ans1673
}
// para 是参数
// one 代表第一个参数
type para1673 struct {
nums []int
k int
}
// ans 是答案
// one 代表第一个答案
type ans1673 struct {
one []int
}
func Test_Problem1673(t *testing.T) {
qs := []question1673{
{
para1673{[]int{3, 5, 2, 6}, 2},
ans1673{[]int{2, 6}},
},
{
para1673{[]int{2, 4, 3, 3, 5, 4, 9, 6}, 4},
ans1673{[]int{2, 3, 3, 4}},
},
{
para1673{[]int{2, 4, 3, 3, 5, 4, 9, 6}, 4},
ans1673{[]int{2, 3, 3, 4}},
},
{
para1673{[]int{71, 18, 52, 29, 55, 73, 24, 42, 66, 8, 80, 2}, 3},
ans1673{[]int{8, 80, 2}},
},
{
para1673{[]int{84, 10, 71, 23, 66, 61, 62, 64, 34, 41, 80, 25, 91, 43, 4, 75, 65, 13, 37, 41, 46, 90, 55, 8, 85, 61, 95, 71}, 24},
ans1673{[]int{10, 23, 61, 62, 34, 41, 80, 25, 91, 43, 4, 75, 65, 13, 37, 41, 46, 90, 55, 8, 85, 61, 95, 71}},
},
}
fmt.Printf("------------------------Leetcode Problem 1673------------------------\n")
for _, q := range qs {
_, p := q.ans1673, q.para1673
fmt.Printf("【input】:%v 【output】:%v\n", p, mostCompetitive(p.nums, p.k))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,62 @@
# [1673. Find the Most Competitive Subsequence](https://leetcode.com/problems/find-the-most-competitive-subsequence/)
## 题目
Given an integer array `nums` and a positive integer `k`, return *the most **competitive** subsequence of* `nums` *of size* `k`.
An array's subsequence is a resulting sequence obtained by erasing some (possibly zero) elements from the array.
We define that a subsequence `a` is more **competitive** than a subsequence `b` (of the same length) if in the first position where `a` and `b` differ, subsequence `a` has a number **less** than the corresponding number in `b`. For example, `[1,3,4]` is more competitive than `[1,3,5]` because the first position they differ is at the final number, and `4` is less than `5`.
**Example 1:**
```
Input: nums = [3,5,2,6], k = 2
Output: [2,6]
Explanation: Among the set of every possible subsequence: {[3,5], [3,2], [3,6], [5,2], [5,6], [2,6]}, [2,6] is the most competitive.
```
**Example 2:**
```
Input: nums = [2,4,3,3,5,4,9,6], k = 4
Output: [2,3,3,4]
```
**Constraints:**
- `1 <= nums.length <= 105`
- `0 <= nums[i] <= 109`
- `1 <= k <= nums.length`
## 题目大意
给你一个整数数组 nums 和一个正整数 k ,返回长度为 k 且最具 竞争力 的 nums 子序列。数组的子序列是从数组中删除一些元素(可能不删除元素)得到的序列。
在子序列 a 和子序列 b 第一个不相同的位置上如果 a 中的数字小于 b 中对应的数字,那么我们称子序列 a 比子序列 b相同长度下更具 竞争力 。 例如,[1,3,4] 比 [1,3,5] 更具竞争力在第一个不相同的位置也就是最后一个位置上 4 小于 5 。
## 解题思路
- 这一题是单调栈的典型题型。利用单调栈,可以保证原数组中元素相对位置不变,这满足题意中删除元素但不移动元素的要求。单调栈又能保证每次进栈,元素是最小的。
- 类似的题目还有第 42 题,第 84 题,第 496 题,第 503 题,第 856 题,第 901 题,第 907 题,第 1130 题,第 1425 题,第 1673 题。
## 代码
```go
package leetcode
// 单调栈
func mostCompetitive(nums []int, k int) []int {
stack := make([]int, 0, len(nums))
for i := 0; i < len(nums); i++ {
for len(stack)+len(nums)-i > k && len(stack) > 0 && nums[i] < stack[len(stack)-1] {
stack = stack[:len(stack)-1]
}
stack = append(stack, nums[i])
}
return stack[:k]
}
```

View File

@ -56,7 +56,7 @@ Explanation: It is impossible to distribute nums into 3 subsets where no two ele
- 读完题最直白的思路就是 DFS。做法类似第 77 题。这里就不赘述了。可以见第 77 题题解。
- 这一题还需要用到贪心的思想。每次取数都取最小的数。这样可以不会让最大数和最小数在一个集合中。由于每次取数都是取最小的,那么能保证不兼容性每次都尽量最小。于是在 order 数组中定义取数的顺序。然后再把数组从小到大排列。这样每次按照 order 顺序取数,都是取的最小值。
- 正常的 DFS 写完提交,耗时是很长的。大概是 1532ms。如何优化到极致呢这里需要加上 2 个剪枝条件。第一个剪枝条件比较简单,如果累计 sum 比之前存储的 res 大,那么直接 return不需要继续递归了。第二个剪枝条件就非常重要了可以一下子减少很多次递归。每次取数产生新的集合的时候要从第一个最小数开始取一旦取了后面就不需要再循环递归了。举个例子[1,2,3,4],第一个数如果取 2集合可以是 [[2,3],[1,4]] 或 [[2,4], [1,3]], 这个集合和[[1,3],[2,4]]、[[1,4], [2,3]] 情况一样。可以看到如果取出第一个最小值以后,后面的循环是不必要的了。所以在取下标为 0 的数的时候,递归到底层以后,返回就可以直接 break不用接下去的循环了接下去的循环和递归是不必要的。加了这 2 个剪枝条件以后,耗时就变成了 0ms 了。beats 100%
- 正常的 DFS 写完提交,耗时是很长的。大概是 1532ms。如何优化到极致呢这里需要加上 2 个剪枝条件。第一个剪枝条件比较简单,如果累计 sum 比之前存储的 res 大,那么直接 return不需要继续递归了。第二个剪枝条件就非常重要了可以一下子减少很多次递归。每次取数产生新的集合的时候要从第一个最小数开始取一旦取了后面就不需要再循环递归了。举个例子[1,2,3,4],第一个数如果取 2集合可以是 [[2,3],[1,4]] 或 [[2,4], [1,3]], 这个集合和[[1,3],[2,4]]、[[1,4], [2,3]] 情况一样。可以看到如果取出第一个最小值以后,后面的循环是不必要的了。所以在取下标为 0 的数的时候,递归到底层以后,返回就可以直接 break不用接下去的循环了接下去的循环和递归是不必要的。每组组内的顺序我们并不关心,只要最大值和最小值在分组内即可。另外组间顺序我们也不关心。所以可以把排列问题 O(n!) 时间复杂度降低到组合问题 O(2^n)。加了这 2 个剪枝条件以后,耗时就变成了 0ms 了。beats 100%
## 代码

View File

@ -1,46 +0,0 @@
package leetcode
import (
"github.com/halfrost/LeetCode-Go/structures"
)
// ListNode define
type ListNode = structures.ListNode
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func mergeInBetween(list1 *ListNode, a int, b int, list2 *ListNode) *ListNode {
pre, cur, list2Cur := list1, list1.Next, list2
for cur.Next != nil {
if cur.Val == a {
pre.Next = list2
pre = cur
break
}
pre = cur
cur = cur.Next
}
cur = cur.Next
for list2Cur.Next != nil {
list2Cur = list2Cur.Next
}
if a == b {
list2Cur.Next = cur
return list1
}
for cur.Next != nil {
if cur.Val == b {
list2Cur.Next = cur.Next
break
}
pre = cur
cur = cur.Next
}
return list1
}

View File

@ -1,62 +0,0 @@
package leetcode
import (
"fmt"
"testing"
"github.com/halfrost/LeetCode-Go/structures"
)
type question2 struct {
para2
ans2
}
// para 是参数
// one 代表第一个参数
type para2 struct {
one []int
a int
b int
another []int
}
// ans 是答案
// one 代表第一个答案
type ans2 struct {
one []int
}
func Test_Problem2(t *testing.T) {
qs := []question2{
{
para2{[]int{0, 1, 2, 3, 4, 5}, 3, 4, []int{1000000, 1000001, 1000002}},
ans2{[]int{0, 1, 2, 1000000, 1000001, 1000002, 5}},
},
{
para2{[]int{0, 1, 2, 3, 4, 5, 6}, 2, 5, []int{1000000, 1000001, 1000002, 1000003, 1000004}},
ans2{[]int{0, 1, 1000000, 1000001, 1000002, 1000003, 1000004, 6}},
},
{
para2{[]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, 3, 5, []int{1000000, 1000001, 1000002, 1000003, 1000004, 1000005, 1000006}},
ans2{[]int{0, 1, 2, 1000000, 1000001, 1000002, 1000003, 1000004, 1000005, 1000006, 6, 7, 8, 9}},
},
{
para2{[]int{0, 1, 2}, 1, 1, []int{1000000, 1000001, 1000002, 1000003}},
ans2{[]int{0, 1000000, 1000001, 1000002, 1000003, 2}},
},
}
fmt.Printf("------------------------Leetcode Problem 2------------------------\n")
for _, q := range qs {
_, p := q.ans2, q.para2
fmt.Printf("【input】:%v 【output】:%v\n", p, structures.List2Ints(mergeInBetween(structures.Ints2List(p.one), p.a, p.b, structures.Ints2List(p.another))))
}
fmt.Printf("\n\n\n")
}

View File

@ -1,78 +0,0 @@
package leetcode
type FrontMiddleBackQueue struct {
Queue []int
Length int
}
func Constructor() FrontMiddleBackQueue {
return FrontMiddleBackQueue{Queue: make([]int, 0), Length: 0}
}
func (this *FrontMiddleBackQueue) PushFront(val int) {
tmp := make([]int, this.Length+1)
copy(tmp[1:], this.Queue)
tmp[0] = val
this.Queue = tmp
this.Length++
}
func (this *FrontMiddleBackQueue) PushMiddle(val int) {
tmp := make([]int, this.Length+1)
idx := this.Length / 2
copy(tmp[:idx], this.Queue[:idx])
tmp[idx] = val
copy(tmp[idx+1:], this.Queue[idx:])
this.Queue = tmp
this.Length++
}
func (this *FrontMiddleBackQueue) PushBack(val int) {
this.Queue = append(this.Queue, val)
this.Length++
}
func (this *FrontMiddleBackQueue) PopFront() int {
if this.Length == 0 {
return -1
}
res := this.Queue[0]
this.Queue = this.Queue[1:]
this.Length--
return res
}
func (this *FrontMiddleBackQueue) PopMiddle() int {
if this.Length == 0 {
return -1
}
mid := (this.Length - 1) / 2
res := this.Queue[mid]
tmp := make([]int, len(this.Queue)-1)
copy(tmp[:mid], this.Queue[:mid])
copy(tmp[mid:], this.Queue[mid+1:])
this.Queue = tmp
this.Length--
return res
}
func (this *FrontMiddleBackQueue) PopBack() int {
if this.Length == 0 {
return -1
}
res := this.Queue[this.Length-1]
this.Queue = this.Queue[:this.Length-1]
this.Length--
return res
}
/**
* Your FrontMiddleBackQueue object will be instantiated and called as such:
* obj := Constructor();
* obj.PushFront(val);
* obj.PushMiddle(val);
* obj.PushBack(val);
* param_4 := obj.PopFront();
* param_5 := obj.PopMiddle();
* param_6 := obj.PopBack();
*/

View File

@ -1,20 +0,0 @@
package leetcode
func maximumWealth(accounts [][]int) int {
res := 0
for i := 0; i < len(accounts); i++ {
sum := 0
for j := 0; j < len(accounts[i]); j++ {
sum += accounts[i][j]
}
res = max(res, sum)
}
return res
}
func max(a int, b int) int {
if a > b {
return a
}
return b
}

View File

@ -1,52 +0,0 @@
package leetcode
import (
"fmt"
"testing"
)
type question491 struct {
para491
ans491
}
// para 是参数
// one 代表第一个参数
type para491 struct {
accounts [][]int
}
// ans 是答案
// one 代表第一个答案
type ans491 struct {
one int
}
func Test_Problem491(t *testing.T) {
qs := []question491{
{
para491{[][]int{{1, 2, 3}, {3, 2, 1}}},
ans491{6},
},
{
para491{[][]int{{1, 5}, {7, 3}, {3, 5}}},
ans491{10},
},
{
para491{[][]int{{2, 8, 7}, {7, 1, 3}, {1, 9, 5}}},
ans491{17},
},
}
fmt.Printf("------------------------Leetcode Problem 491------------------------\n")
for _, q := range qs {
_, p := q.ans491, q.para491
fmt.Printf("【input】:%v 【output】:%v\n", p, maximumWealth(p.accounts))
}
fmt.Printf("\n\n\n")
}

View File

@ -1,87 +0,0 @@
package leetcode
import (
"fmt"
)
// 解法一 单调栈
func mostCompetitive(nums []int, k int) []int {
stack := make([]int, 0, len(nums))
for i := 0; i < len(nums); i++ {
for len(stack)+len(nums)-i > k && len(stack) > 0 && nums[i] < stack[len(stack)-1] {
stack = stack[:len(stack)-1]
}
stack = append(stack, nums[i])
}
return stack[:k]
}
// 解法二 DFS 超时
func mostCompetitive1(nums []int, k int) []int {
c, visited, res := []int{}, map[int]bool{}, []int{}
for i := 0; i < len(nums)-1; i++ {
if _, ok := visited[nums[i]]; ok {
continue
} else {
visited[nums[i]] = true
generateIncSubsets(nums, i, k, c, &res)
}
}
return res
}
func generateIncSubsets(nums []int, current, k int, c []int, res *[]int) {
c = append(c, nums[current])
fmt.Printf("c = %v res = %v\n", c, *res)
if len(c) > k {
return
}
if len(c) < k && len(*res) != 0 {
b, flag := make([]int, len(c)), false
copy(b, c)
for i := 0; i < len(b); i++ {
if b[i] < (*res)[i] {
flag = true
break
}
}
if !flag {
return
}
}
// if len(*res) != 0 && len(c) <= len(*res) && c[len(c)-1] > (*res)[len(c)-1] {
// return
// }
if len(c) == k {
//fmt.Printf("c = %v\n", c)
b, flag := make([]int, len(c)), false
copy(b, c)
if len(*res) == 0 {
*res = b
} else {
for i := 0; i < len(b); i++ {
if b[i] < (*res)[i] {
flag = true
break
}
}
if flag {
*res = b
}
}
fmt.Printf("tmp = %v min = %v\n", b, *res)
}
visited := map[int]bool{}
for i := current + 1; i < len(nums); i++ {
// if nums[current] <= nums[i] {
if _, ok := visited[nums[i]]; ok {
continue
} else {
visited[nums[i]] = true
generateIncSubsets(nums, i, k, c, res)
}
//}
}
c = c[:len(c)-1]
return
}

View File

@ -1,63 +0,0 @@
package leetcode
import (
"fmt"
"testing"
)
type question491 struct {
para491
ans491
}
// para 是参数
// one 代表第一个参数
type para491 struct {
nums []int
k int
}
// ans 是答案
// one 代表第一个答案
type ans491 struct {
one []int
}
func Test_Problem491(t *testing.T) {
qs := []question491{
{
para491{[]int{3, 5, 2, 6}, 2},
ans491{[]int{2, 6}},
},
{
para491{[]int{2, 4, 3, 3, 5, 4, 9, 6}, 4},
ans491{[]int{2, 3, 3, 4}},
},
{
para491{[]int{2, 4, 3, 3, 5, 4, 9, 6}, 4},
ans491{[]int{2, 3, 3, 4}},
},
{
para491{[]int{71, 18, 52, 29, 55, 73, 24, 42, 66, 8, 80, 2}, 3},
ans491{[]int{8, 80, 2}},
},
{
para491{[]int{84, 10, 71, 23, 66, 61, 62, 64, 34, 41, 80, 25, 91, 43, 4, 75, 65, 13, 37, 41, 46, 90, 55, 8, 85, 61, 95, 71}, 24},
ans491{[]int{10, 23, 61, 62, 34, 41, 80, 25, 91, 43, 4, 75, 65, 13, 37, 41, 46, 90, 55, 8, 85, 61, 95, 71}},
},
}
fmt.Printf("------------------------Leetcode Problem 491------------------------\n")
for _, q := range qs {
_, p := q.ans491, q.para491
fmt.Printf("【input】:%v 【output】:%v\n", p, mostCompetitive(p.nums, p.k))
}
fmt.Printf("\n\n\n")
}