Add solution 0583、1482

This commit is contained in:
YDZ
2021-05-09 18:24:45 +08:00
parent 09c6e478e1
commit 9a30c0094e
24 changed files with 750 additions and 182 deletions

View File

@ -0,0 +1,31 @@
package leetcode
func minDistance(word1 string, word2 string) int {
dp := make([][]int, len(word1)+1)
for i := 0; i < len(word1)+1; i++ {
dp[i] = make([]int, len(word2)+1)
}
for i := 0; i < len(word1)+1; i++ {
dp[i][0] = i
}
for i := 0; i < len(word2)+1; i++ {
dp[0][i] = i
}
for i := 1; i < len(word1)+1; i++ {
for j := 1; j < len(word2)+1; j++ {
if word1[i-1] == word2[j-1] {
dp[i][j] = dp[i-1][j-1]
} else {
dp[i][j] = 1 + min(dp[i][j-1], dp[i-1][j])
}
}
}
return dp[len(word1)][len(word2)]
}
func min(x, y int) int {
if x < y {
return x
}
return y
}

View File

@ -0,0 +1,48 @@
package leetcode
import (
"fmt"
"testing"
)
type question583 struct {
para583
ans583
}
// para 是参数
// one 代表第一个参数
type para583 struct {
word1 string
word2 string
}
// ans 是答案
// one 代表第一个答案
type ans583 struct {
one int
}
func Test_Problem583(t *testing.T) {
qs := []question583{
{
para583{"sea", "eat"},
ans583{2},
},
{
para583{"leetcode", "etco"},
ans583{4},
},
}
fmt.Printf("------------------------Leetcode Problem 583------------------------\n")
for _, q := range qs {
_, p := q.ans583, q.para583
fmt.Printf("【input】:%v 【output】:%v\n", p, minDistance(p.word1, p.word2))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,76 @@
# [583. Delete Operation for Two Strings](https://leetcode.com/problems/delete-operation-for-two-strings/)
## 题目
Given two strings `word1` and `word2`, return *the minimum number of **steps** required to make* `word1` *and* `word2` *the same*.
In one **step**, you can delete exactly one character in either string.
**Example 1:**
```
Input: word1 = "sea", word2 = "eat"
Output: 2
Explanation: You need one step to make "sea" to "ea" and another step to make "eat" to "ea".
```
**Example 2:**
```
Input: word1 = "leetcode", word2 = "etco"
Output: 4
```
**Constraints:**
- `1 <= word1.length, word2.length <= 500`
- `word1` and `word2` consist of only lowercase English letters.
## 题目大意
给定两个单词 word1 和 word2找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符。
## 解题思路
- 从题目数据量级判断,此题一定是 O(n^2) 动态规划题。定义 `dp[i][j]` 表示 `word1[:i]``word2[:j]` 匹配所删除的最少步数。如果 `word1[:i-1]``word2[:j-1]` 匹配,那么 `dp[i][j] = dp[i-1][j-1]`。如果 `word1[:i-1]``word2[:j-1]` 不匹配,那么需要考虑删除一次,所以 `dp[i][j] = 1 + min(dp[i][j-1], dp[i-1][j])`。所以动态转移方程是:
$$dp[i][j] = \left\{\begin{matrix}dp[i-1][j-1]&, word1[i-1] == word2[j-1]\\ 1 + min(dp[i][j-1], dp[i-1][j])&, word1[i-1] \neq word2[j-1]\\\end{matrix}\right.$$
最终答案存储在 `dp[len(word1)][len(word2)]` 中。
## 代码
```go
package leetcode
func minDistance(word1 string, word2 string) int {
dp := make([][]int, len(word1)+1)
for i := 0; i < len(word1)+1; i++ {
dp[i] = make([]int, len(word2)+1)
}
for i := 0; i < len(word1)+1; i++ {
dp[i][0] = i
}
for i := 0; i < len(word2)+1; i++ {
dp[0][i] = i
}
for i := 1; i < len(word1)+1; i++ {
for j := 1; j < len(word2)+1; j++ {
if word1[i-1] == word2[j-1] {
dp[i][j] = dp[i-1][j-1]
} else {
dp[i][j] = 1 + min(dp[i][j-1], dp[i-1][j])
}
}
}
return dp[len(word1)][len(word2)]
}
func min(x, y int) int {
if x < y {
return x
}
return y
}
```

View File

@ -0,0 +1,30 @@
package leetcode
import "sort"
func minDays(bloomDay []int, m int, k int) int {
if m*k > len(bloomDay) {
return -1
}
maxDay := 0
for _, day := range bloomDay {
if day > maxDay {
maxDay = day
}
}
return sort.Search(maxDay, func(days int) bool {
flowers, bouquets := 0, 0
for _, d := range bloomDay {
if d > days {
flowers = 0
} else {
flowers++
if flowers == k {
bouquets++
flowers = 0
}
}
}
return bouquets >= m
})
}

View File

@ -0,0 +1,64 @@
package leetcode
import (
"fmt"
"testing"
)
type question1482 struct {
para1482
ans1482
}
// para 是参数
// one 代表第一个参数
type para1482 struct {
bloomDay []int
m int
k int
}
// ans 是答案
// one 代表第一个答案
type ans1482 struct {
one int
}
func Test_Problem1482(t *testing.T) {
qs := []question1482{
{
para1482{[]int{1, 10, 3, 10, 2}, 3, 1},
ans1482{3},
},
{
para1482{[]int{1, 10, 3, 10, 2}, 3, 2},
ans1482{-1},
},
{
para1482{[]int{7, 7, 7, 7, 12, 7, 7}, 2, 3},
ans1482{12},
},
{
para1482{[]int{1000000000, 1000000000}, 1, 1},
ans1482{1000000000},
},
{
para1482{[]int{1, 10, 2, 9, 3, 8, 4, 7, 5, 6}, 4, 2},
ans1482{9},
},
}
fmt.Printf("------------------------Leetcode Problem 1482------------------------\n")
for _, q := range qs {
_, p := q.ans1482, q.para1482
fmt.Printf("【input】:%v 【output】:%v \n", p, minDays(p.bloomDay, p.m, p.k))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,110 @@
# [1482. Minimum Number of Days to Make m Bouquets](https://leetcode.com/problems/minimum-number-of-days-to-make-m-bouquets/)
## 题目
Given an integer array `bloomDay`, an integer `m` and an integer `k`.
We need to make `m` bouquets. To make a bouquet, you need to use `k` **adjacent flowers** from the garden.
The garden consists of `n` flowers, the `ith` flower will bloom in the `bloomDay[i]` and then can be used in **exactly one** bouquet.
Return *the minimum number of days* you need to wait to be able to make `m` bouquets from the garden. If it is impossible to make `m` bouquets return **-1**.
**Example 1:**
```
Input: bloomDay = [1,10,3,10,2], m = 3, k = 1
Output: 3
Explanation: Let's see what happened in the first three days. x means flower bloomed and _ means flower didn't bloom in the garden.
We need 3 bouquets each should contain 1 flower.
After day 1: [x, _, _, _, _] // we can only make one bouquet.
After day 2: [x, _, _, _, x] // we can only make two bouquets.
After day 3: [x, _, x, _, x] // we can make 3 bouquets. The answer is 3.
```
**Example 2:**
```
Input: bloomDay = [1,10,3,10,2], m = 3, k = 2
Output: -1
Explanation: We need 3 bouquets each has 2 flowers, that means we need 6 flowers. We only have 5 flowers so it is impossible to get the needed bouquets and we return -1.
```
**Example 3:**
```
Input: bloomDay = [7,7,7,7,12,7,7], m = 2, k = 3
Output: 12
Explanation: We need 2 bouquets each should have 3 flowers.
Here's the garden after the 7 and 12 days:
After day 7: [x, x, x, x, _, x, x]
We can make one bouquet of the first three flowers that bloomed. We cannot make another bouquet from the last three flowers that bloomed because they are not adjacent.
After day 12: [x, x, x, x, x, x, x]
It is obvious that we can make two bouquets in different ways.
```
**Example 4:**
```
Input: bloomDay = [1000000000,1000000000], m = 1, k = 1
Output: 1000000000
Explanation: You need to wait 1000000000 days to have a flower ready for a bouquet.
```
**Example 5:**
```
Input: bloomDay = [1,10,2,9,3,8,4,7,5,6], m = 4, k = 2
Output: 9
```
**Constraints:**
- `bloomDay.length == n`
- `1 <= n <= 10^5`
- `1 <= bloomDay[i] <= 10^9`
- `1 <= m <= 10^6`
- `1 <= k <= n`
## 题目大意
给你一个整数数组 bloomDay以及两个整数 m 和 k 。现需要制作 m 束花。制作花束时,需要使用花园中 相邻的 k 朵花 。花园中有 n 朵花,第 i 朵花会在 bloomDay[i] 时盛开,恰好 可以用于 一束 花中。请你返回从花园中摘 m 束花需要等待的最少的天数。如果不能摘到 m 束花则返回 -1 。
## 解题思路
- 本题是二分搜索提醒。题目解空间固定,答案区间一定在 [0, maxDay] 中。这是单调增且有序区间,所以可以在这个解空间内使用二分搜索。在区间 [0, maxDay] 中找到第一个能满足 m 束花的解。二分搜索判断是否为 true 的条件为:从左往右遍历数组,依次统计当前日期下,花是否开了,如果连续开花 k 朵,便为 1 束,数组遍历结束如果花束总数 ≥ k 即为答案。二分搜索会返回最小的下标,即对应满足题意的最少天数。
## 代码
```go
package leetcode
import "sort"
func minDays(bloomDay []int, m int, k int) int {
if m*k > len(bloomDay) {
return -1
}
maxDay := 0
for _, day := range bloomDay {
if day > maxDay {
maxDay = day
}
}
return sort.Search(maxDay, func(days int) bool {
flowers, bouquets := 0, 0
for _, d := range bloomDay {
if d > days {
flowers = 0
} else {
flowers++
if flowers == k {
bouquets++
flowers = 0
}
}
}
return bouquets >= m
})
}
```