Add solution 1662、1663、1664、1665

This commit is contained in:
YDZ
2020-11-23 22:17:33 +08:00
parent 285f7a1c75
commit 37fde650a5
17 changed files with 1204 additions and 0 deletions

View File

@ -0,0 +1,12 @@
package leetcode
func arrayStringsAreEqual(word1 []string, word2 []string) bool {
str1, str2 := "", ""
for i := 0; i < len(word1); i++ {
str1 += word1[i]
}
for i := 0; i < len(word2); i++ {
str2 += word2[i]
}
return str1 == str2
}

View File

@ -0,0 +1,53 @@
package leetcode
import (
"fmt"
"testing"
)
type question1662 struct {
para1662
ans1662
}
// para 是参数
// one 代表第一个参数
type para1662 struct {
word1 []string
word2 []string
}
// ans 是答案
// one 代表第一个答案
type ans1662 struct {
one bool
}
func Test_Problem1662(t *testing.T) {
qs := []question1662{
{
para1662{[]string{"ab", "c"}, []string{"a", "bc"}},
ans1662{true},
},
{
para1662{[]string{"a", "cb"}, []string{"ab", "c"}},
ans1662{false},
},
{
para1662{[]string{"abc", "d", "defg"}, []string{"abcddefg"}},
ans1662{true},
},
}
fmt.Printf("------------------------Leetcode Problem 1662------------------------\n")
for _, q := range qs {
_, p := q.ans1662, q.para1662
fmt.Printf("【input】:%v 【output】:%v \n", p, arrayStringsAreEqual(p.word1, p.word2))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,65 @@
# [1662. Check If Two String Arrays are Equivalent](https://leetcode.com/problems/check-if-two-string-arrays-are-equivalent/)
## 题目
Given two string arrays `word1` and `word2`, return **`true` *if the two arrays **represent** the same string, and* `false` *otherwise.*
A string is **represented** by an array if the array elements concatenated **in order** forms the string.
**Example 1:**
```
Input: word1 = ["ab", "c"], word2 = ["a", "bc"]
Output: true
Explanation:
word1 represents string "ab" + "c" -> "abc"
word2 represents string "a" + "bc" -> "abc"
The strings are the same, so return true.
```
**Example 2:**
```
Input: word1 = ["a", "cb"], word2 = ["ab", "c"]
Output: false
```
**Example 3:**
```
Input: word1 = ["abc", "d", "defg"], word2 = ["abcddefg"]
Output: true
```
**Constraints:**
- `1 <= word1.length, word2.length <= 103`
- `1 <= word1[i].length, word2[i].length <= 103`
- `1 <= sum(word1[i].length), sum(word2[i].length) <= 103`
- `word1[i]` and `word2[i]` consist of lowercase letters.
## 题目大意
给你两个字符串数组 word1 和 word2 。如果两个数组表示的字符串相同,返回 true ;否则,返回 false 。数组表示的字符串 是由数组中的所有元素 按顺序 连接形成的字符串。
## 解题思路
- 简单题,依次拼接 2 个数组内的字符串,然后比较 str1 和 str2 是否相同即可。
## 代码
```go
package leetcode
func arrayStringsAreEqual(word1 []string, word2 []string) bool {
str1, str2 := "", ""
for i := 0; i < len(word1); i++ {
str1 += word1[i]
}
for i := 0; i < len(word2); i++ {
str2 += word2[i]
}
return str1 == str2
}
```

View File

@ -0,0 +1,55 @@
package leetcode
// 解法一 贪心
func getSmallestString(n int, k int) string {
res := make([]rune, n)
for i := n - 1; i >= 0; i-- {
diff := k - i
if diff >= 26 {
// Need to add z
res[i] = 'z'
k = k - 26
} else {
res[i] = rune('a' + diff - 1)
k = k - diff
}
}
return string(res)
}
// 解法二 DFS
func getSmallestString1(n int, k int) string {
if n == 0 {
return ""
}
res, c := "", []byte{}
findSmallestString(0, n, k, 0, c, &res)
return res
}
func findSmallestString(value int, length, k, index int, str []byte, res *string) {
if len(str) == length && value == k {
tmp := string(str)
if (*res) == "" {
*res = tmp
}
if tmp < *res && *res != "" {
*res = tmp
}
return
}
if len(str) >= index && (*res) != "" && str[index-1] > (*res)[index-1] {
return
}
for j := 0; j < 26; j++ {
if k-value > (length-len(str))*26 || value > k {
return
}
str = append(str, byte(int('a')+j))
value += j + 1
findSmallestString(value, length, k, index+1, str, res)
str = str[:len(str)-1]
value -= j + 1
}
}

View File

@ -0,0 +1,53 @@
package leetcode
import (
"fmt"
"testing"
)
type question1663 struct {
para1663
ans1663
}
// para 是参数
// one 代表第一个参数
type para1663 struct {
n int
k int
}
// ans 是答案
// one 代表第一个答案
type ans1663 struct {
one string
}
func Test_Problem1663(t *testing.T) {
qs := []question1663{
{
para1663{3, 27},
ans1663{"aay"},
},
{
para1663{5, 73},
ans1663{"aaszz"},
},
{
para1663{24, 552},
ans1663{"aaszz"},
},
}
fmt.Printf("------------------------Leetcode Problem 1663------------------------\n")
for _, q := range qs {
_, p := q.ans1663, q.para1663
fmt.Printf("【input】:%v 【output】:%v \n", p, getSmallestString(p.n, p.k))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,104 @@
# [1663. Smallest String With A Given Numeric Value](https://leetcode.com/problems/smallest-string-with-a-given-numeric-value/)
## 题目
The **numeric value** of a **lowercase character** is defined as its position `(1-indexed)` in the alphabet, so the numeric value of `a` is `1`, the numeric value of `b` is `2`, the numeric value of `c` is `3`, and so on.
The **numeric value** of a **string** consisting of lowercase characters is defined as the sum of its characters' numeric values. For example, the numeric value of the string `"abe"` is equal to `1 + 2 + 5 = 8`.
You are given two integers `n` and `k`. Return *the **lexicographically smallest string** with **length** equal to `n` and **numeric value** equal to `k`.*
Note that a string `x` is lexicographically smaller than string `y` if `x` comes before `y` in dictionary order, that is, either `x` is a prefix of `y`, or if `i` is the first position such that `x[i] != y[i]`, then `x[i]` comes before `y[i]` in alphabetic order.
**Example 1:**
```
Input: n = 3, k = 27
Output: "aay"
Explanation: The numeric value of the string is 1 + 1 + 25 = 27, and it is the smallest string with such a value and length equal to 3.
```
**Example 2:**
```
Input: n = 5, k = 73
Output: "aaszz"
```
**Constraints:**
- `1 <= n <= 105`
- `n <= k <= 26 * n`
## 题目大意
小写字符 的 数值 是它在字母表中的位置(从 1 开始),因此 a 的数值为 1 b 的数值为 2 c 的数值为 3 ,以此类推。字符串由若干小写字符组成,字符串的数值 为各字符的数值之和。例如,字符串 "abe" 的数值等于 1 + 2 + 5 = 8 。给你两个整数 n 和 k 。返回 长度 等于 n 且 数值 等于 k 的 字典序最小 的字符串。注意,如果字符串 x 在字典排序中位于 y 之前,就认为 x 字典序比 y 小,有以下两种情况:
- x 是 y 的一个前缀;
- 如果 i 是 x[i] != y[i] 的第一个位置,且 x[i] 在字母表中的位置比 y[i] 靠前。
## 解题思路
- 给出 n 和 k要求找到字符串长度为 n字母在字母表内位置总和为 k 的最小字典序字符串。
- 这一题笔者读完题,比赛的时候直接用 DFS 撸了一版。赛后看了时间复杂度马马虎虎感觉还有优化的空间。DFS 会遍历出所有的解,实际上这一题只要求最小字典序,所以 DFS 剪枝的时候要加上判断字典序的判断,如果新添加进来的字母比已经保存的字符串的相应位置上的字母字典序大,那么就直接 return这个答案一定不会是最小字典序。代码见解法二
- 想到这里,其实 DFS 不必要,直接用 for 循环就可找到最小字典序的字符串。代码见解法一。
## 代码
```go
package leetcode
// 解法一 贪心
func getSmallestString(n int, k int) string {
res := make([]rune, n)
for i := n - 1; i >= 0; i-- {
diff := k - i
if diff >= 26 {
// Need to add z
res[i] = 'z'
k = k - 26
} else {
res[i] = rune('a' + diff - 1)
k = k - diff
}
}
return string(res)
}
// 解法二 DFS
func getSmallestString1(n int, k int) string {
if n == 0 {
return ""
}
res, c := "", []byte{}
findSmallestString(0, n, k, 0, c, &res)
return res
}
func findSmallestString(value int, length, k, index int, str []byte, res *string) {
if len(str) == length && value == k {
tmp := string(str)
if (*res) == "" {
*res = tmp
}
if tmp < *res && *res != "" {
*res = tmp
}
return
}
if len(str) >= index && (*res) != "" && str[index-1] > (*res)[index-1] {
return
}
for j := 0; j < 26; j++ {
if k-value > (length-len(str))*26 || value > k {
return
}
str = append(str, byte(int('a')+j))
value += j + 1
findSmallestString(value, length, k, index+1, str, res)
str = str[:len(str)-1]
value -= j + 1
}
}
```

View File

@ -0,0 +1,45 @@
package leetcode
// 解法一 超简洁写法
func waysToMakeFair(nums []int) int {
sum, res := [2]int{}, 0
for i := 0; i < len(nums); i++ {
sum[i%2] += nums[i]
}
for i := 0; i < len(nums); i++ {
sum[i%2] -= nums[i]
if sum[i%2] == sum[1-(i%2)] {
res++
}
sum[1-(i%2)] += nums[i]
}
return res
}
// 解法二 前缀和,后缀和
func waysToMakeFair1(nums []int) int {
evenPrefix, oddPrefix, evenSuffix, oddSuffix, res := 0, 0, 0, 0, 0
for i := 0; i < len(nums); i++ {
if i%2 == 0 {
evenSuffix += nums[i]
} else {
oddSuffix += nums[i]
}
}
for i := 0; i < len(nums); i++ {
if i%2 == 0 {
evenSuffix -= nums[i]
} else {
oddSuffix -= nums[i]
}
if (evenPrefix + oddSuffix) == (oddPrefix + evenSuffix) {
res++
}
if i%2 == 0 {
evenPrefix += nums[i]
} else {
oddPrefix += nums[i]
}
}
return res
}

View File

@ -0,0 +1,57 @@
package leetcode
import (
"fmt"
"testing"
)
type question1664 struct {
para1664
ans1664
}
// para 是参数
// one 代表第一个参数
type para1664 struct {
nums []int
}
// ans 是答案
// one 代表第一个答案
type ans1664 struct {
one int
}
func Test_Problem1664(t *testing.T) {
qs := []question1664{
{
para1664{[]int{6, 1, 7, 4, 1}},
ans1664{0},
},
{
para1664{[]int{2, 1, 6, 4}},
ans1664{1},
},
{
para1664{[]int{1, 1, 1}},
ans1664{3},
},
{
para1664{[]int{1, 2, 3}},
ans1664{0},
},
}
fmt.Printf("------------------------Leetcode Problem 1664------------------------\n")
for _, q := range qs {
_, p := q.ans1664, q.para1664
fmt.Printf("【input】:%v 【output】:%v \n", p, waysToMakeFair(p.nums))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,116 @@
# [1664. Ways to Make a Fair Array](https://leetcode.com/problems/ways-to-make-a-fair-array/)
## 题目
You are given an integer array `nums`. You can choose **exactly one** index (**0-indexed**) and remove the element. Notice that the index of the elements may change after the removal.
For example, if `nums = [6,1,7,4,1]`:
- Choosing to remove index `1` results in `nums = [6,7,4,1]`.
- Choosing to remove index `2` results in `nums = [6,1,4,1]`.
- Choosing to remove index `4` results in `nums = [6,1,7,4]`.
An array is **fair** if the sum of the odd-indexed values equals the sum of the even-indexed values.
Return the ***number** of indices that you could choose such that after the removal,* `nums` *is **fair**.*
**Example 1:**
```
Input: nums = [2,1,6,4]
Output: 1
Explanation:
Remove index 0: [1,6,4] -> Even sum: 1 + 4 = 5. Odd sum: 6. Not fair.
Remove index 1: [2,6,4] -> Even sum: 2 + 4 = 6. Odd sum: 6. Fair.
Remove index 2: [2,1,4] -> Even sum: 2 + 4 = 6. Odd sum: 1. Not fair.
Remove index 3: [2,1,6] -> Even sum: 2 + 6 = 8. Odd sum: 1. Not fair.
There is 1 index that you can remove to make nums fair.
```
**Example 2:**
```
Input: nums = [1,1,1]
Output: 3
Explanation: You can remove any index and the remaining array is fair.
```
**Example 3:**
```
Input: nums = [1,2,3]
Output: 0
Explanation: You cannot make a fair array after removing any index.
```
**Constraints:**
- `1 <= nums.length <= 105`
- `1 <= nums[i] <= 104`
## 题目大意
给你一个整数数组 nums 。你需要选择 恰好 一个下标(下标从 0 开始并删除对应的元素。请注意剩下元素的下标可能会因为删除操作而发生改变。
比方说如果 nums = [6,1,7,4,1] ,那么:
- 选择删除下标 1 剩下的数组为 nums = [6,7,4,1] 。
- 选择删除下标 2 剩下的数组为 nums = [6,1,4,1] 。
- 选择删除下标 4 剩下的数组为 nums = [6,1,7,4] 。
如果一个数组满足奇数下标元素的和与偶数下标元素的和相等,该数组就是一个 平衡数组 。请你返回删除操作后剩下的数组 nums  平衡数组 的 方案数 。
## 解题思路
- 给定一个数组 nums要求输出仅删除一个元素以后能使得整个数组平衡的方案数。平衡的定义是奇数下标元素总和等于偶数下标元素总和。
- 这一题如果暴力解答,会超时。原因是每次删除元素以后,都重新计算奇偶数位总和比较耗时。应该利用前面计算过的累加和,推导出此次删除元素以后的情况。这样修改以后就不超时了。具体的,如果删除的是元素是奇数位,这个下标的前缀和不变,要变化的是后面的。删除元素后面,原来偶数位的总和变成了奇数位了,原来奇数位的总和变成偶数位了。删除元素后面这半段的总和可以用前缀和计算出来,奇数位的总和减去删除元素的前缀和,就得到了删除元素后面的后缀和。通过这个办法就可以得到删除元素后面的,奇数位总和,偶数位总和。注意这个后缀和是包含了删除元素的。所以最后需要判断删除元素是奇数位还是偶数位,如果是奇数位,那么在计算出来的偶数和上再减去这个删除元素;如果是偶数位,就在计算出来的奇数和上再减去这个删除元素。代码见解法二。
- 这一题还有一种更简洁的写法,就是解法一了。通过了解法二的思考,我们可以知道,每次变换以后的操作可以抽象出来,即三步,减去一个数,判断是否相等,再加上一个数。只不过这三步在解法二中都去判断了奇偶性。如果我们不判断奇偶性,那么代码就可以写成解法一的样子。为什么可以不用管奇偶性呢?因为每次删除一个元素以后,下次再删除,奇偶就发生颠倒了,上次的奇数和到了下次就是偶数和了。想通这一点就可以把代码写成解法一的样子。
## 代码
```go
// 解法一 超简洁写法
func waysToMakeFair(nums []int) int {
sum, res := [2]int{}, 0
for i := 0; i < len(nums); i++ {
sum[i%2] += nums[i]
}
for i := 0; i < len(nums); i++ {
sum[i%2] -= nums[i]
if sum[i%2] == sum[1-(i%2)] {
res++
}
sum[1-(i%2)] += nums[i]
}
return res
}
// 解法二 前缀和,后缀和
func waysToMakeFair1(nums []int) int {
evenPrefix, oddPrefix, evenSuffix, oddSuffix, res := 0, 0, 0, 0, 0
for i := 0; i < len(nums); i++ {
if i%2 == 0 {
evenSuffix += nums[i]
} else {
oddSuffix += nums[i]
}
}
for i := 0; i < len(nums); i++ {
if i%2 == 0 {
evenSuffix -= nums[i]
} else {
oddSuffix -= nums[i]
}
if (evenPrefix + oddSuffix) == (oddPrefix + evenSuffix) {
res++
}
if i%2 == 0 {
evenPrefix += nums[i]
} else {
oddPrefix += nums[i]
}
}
return res
}
```

View File

@ -0,0 +1,47 @@
package leetcode
import (
"sort"
)
func minimumEffort(tasks [][]int) int {
sort.Sort(Task(tasks))
res, cur := 0, 0
for _, t := range tasks {
if t[1] > cur {
res += t[1] - cur
cur = t[1] - t[0]
} else {
cur -= t[0]
}
}
return res
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
// Task define
type Task [][]int
func (task Task) Len() int {
return len(task)
}
func (task Task) Less(i, j int) bool {
t1, t2 := task[i][1]-task[i][0], task[j][1]-task[j][0]
if t1 != t2 {
return t2 < t1
}
return task[j][1] < task[i][1]
}
func (task Task) Swap(i, j int) {
t := task[i]
task[i] = task[j]
task[j] = t
}

View File

@ -0,0 +1,52 @@
package leetcode
import (
"fmt"
"testing"
)
type question1665 struct {
para1665
ans1665
}
// para 是参数
// one 代表第一个参数
type para1665 struct {
tasks [][]int
}
// ans 是答案
// one 代表第一个答案
type ans1665 struct {
one int
}
func Test_Problem1665(t *testing.T) {
qs := []question1665{
{
para1665{[][]int{{1, 2}, {2, 4}, {4, 8}}},
ans1665{8},
},
{
para1665{[][]int{{1, 3}, {2, 4}, {10, 11}, {10, 12}, {8, 9}}},
ans1665{32},
},
{
para1665{[][]int{{1, 7}, {2, 8}, {3, 9}, {4, 10}, {5, 11}, {6, 12}}},
ans1665{27},
},
}
fmt.Printf("------------------------Leetcode Problem 1665------------------------\n")
for _, q := range qs {
_, p := q.ans1665, q.para1665
fmt.Printf("【input】:%v 【output】:%v \n", p, minimumEffort(p.tasks))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,128 @@
# [1665. Minimum Initial Energy to Finish Tasks](https://leetcode.com/problems/minimum-initial-energy-to-finish-tasks/)
## 题目
You are given an array `tasks` where `tasks[i] = [actuali, minimumi]`:
- `actuali` is the actual amount of energy you **spend to finish** the `ith` task.
- `minimumi` is the minimum amount of energy you **require to begin** the `ith` task.
For example, if the task is `[10, 12]` and your current energy is `11`, you cannot start this task. However, if your current energy is `13`, you can complete this task, and your energy will be `3` after finishing it.
You can finish the tasks in **any order** you like.
Return *the **minimum** initial amount of energy you will need* *to finish all the tasks*.
**Example 1:**
```
Input: tasks = [[1,2],[2,4],[4,8]]
Output: 8
Explanation:
Starting with 8 energy, we finish the tasks in the following order:
- 3rd task. Now energy = 8 - 4 = 4.
- 2nd task. Now energy = 4 - 2 = 2.
- 1st task. Now energy = 2 - 1 = 1.
Notice that even though we have leftover energy, starting with 7 energy does not work because we cannot do the 3rd task.
```
**Example 2:**
```
Input: tasks = [[1,3],[2,4],[10,11],[10,12],[8,9]]
Output: 32
Explanation:
Starting with 32 energy, we finish the tasks in the following order:
- 1st task. Now energy = 32 - 1 = 31.
- 2nd task. Now energy = 31 - 2 = 29.
- 3rd task. Now energy = 29 - 10 = 19.
- 4th task. Now energy = 19 - 10 = 9.
- 5th task. Now energy = 9 - 8 = 1.
```
**Example 3:**
```
Input: tasks = [[1,7],[2,8],[3,9],[4,10],[5,11],[6,12]]
Output: 27
Explanation:
Starting with 27 energy, we finish the tasks in the following order:
- 5th task. Now energy = 27 - 5 = 22.
- 2nd task. Now energy = 22 - 2 = 20.
- 3rd task. Now energy = 20 - 3 = 17.
- 1st task. Now energy = 17 - 1 = 16.
- 4th task. Now energy = 16 - 4 = 12.
- 6th task. Now energy = 12 - 6 = 6.
```
**Constraints:**
- `1 <= tasks.length <= 105`
- `1 <= actuali <= minimumi <= 104`
## 题目大意
给你一个任务数组 tasks 其中 tasks[i] = [actuali, minimumi] 
- actual i 是完成第 i 个任务 需要耗费 的实际能量。
- minimum i 是开始第 i 个任务前需要达到的最低能量。
比方说,如果任务为 [10, 12] 且你当前的能量为 11 那么你不能开始这个任务。如果你当前的能量为 13 你可以完成这个任务且完成它后剩余能量为 3 。你可以按照 任意顺序 完成任务。请你返回完成所有任务的 最少 初始能量。
## 解题思路
- 给出一个 task 数组,每个元素代表一个任务,每个任务有实际消费能量值和开始这个任务需要的最低能量。要求输出能完成所有任务的最少初始能量。
- 这一题直觉是贪心。先将任务按照 `minimum - actual` 进行排序。先完成差值大的任务,那么接下来的能量能最大限度的满足接下来的任务。这样可能完成所有任务的可能性越大。循环任务数组的时候,保存当前能量在 `cur` 中,如果当前能量不够开启下一个任务,那么这个差值就是需要弥补的,这些能量就是最少初始能量中的,所以加上这些差值能量。如果当前能量可以开启下一个任务,那么就更新当前能量,减去实际消耗的能量以后,再继续循环。循环结束就能得到最少初始能量了。
## 代码
```go
package leetcode
import (
"sort"
)
func minimumEffort(tasks [][]int) int {
sort.Sort(Task(tasks))
res, cur := 0, 0
for _, t := range tasks {
if t[1] > cur {
res += t[1] - cur
cur = t[1] - t[0]
} else {
cur -= t[0]
}
}
return res
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
// Task define
type Task [][]int
func (task Task) Len() int {
return len(task)
}
func (task Task) Less(i, j int) bool {
t1, t2 := task[i][1]-task[i][0], task[j][1]-task[j][0]
if t1 != t2 {
return t2 < t1
}
return task[j][1] < task[i][1]
}
func (task Task) Swap(i, j int) {
t := task[i]
task[i] = task[j]
task[j] = t
}
```

View File

@ -0,0 +1,65 @@
# [1662. Check If Two String Arrays are Equivalent](https://leetcode.com/problems/check-if-two-string-arrays-are-equivalent/)
## 题目
Given two string arrays `word1` and `word2`, return **`true` *if the two arrays **represent** the same string, and* `false` *otherwise.*
A string is **represented** by an array if the array elements concatenated **in order** forms the string.
**Example 1:**
```
Input: word1 = ["ab", "c"], word2 = ["a", "bc"]
Output: true
Explanation:
word1 represents string "ab" + "c" -> "abc"
word2 represents string "a" + "bc" -> "abc"
The strings are the same, so return true.
```
**Example 2:**
```
Input: word1 = ["a", "cb"], word2 = ["ab", "c"]
Output: false
```
**Example 3:**
```
Input: word1 = ["abc", "d", "defg"], word2 = ["abcddefg"]
Output: true
```
**Constraints:**
- `1 <= word1.length, word2.length <= 103`
- `1 <= word1[i].length, word2[i].length <= 103`
- `1 <= sum(word1[i].length), sum(word2[i].length) <= 103`
- `word1[i]` and `word2[i]` consist of lowercase letters.
## 题目大意
给你两个字符串数组 word1 和 word2 。如果两个数组表示的字符串相同,返回 true ;否则,返回 false 。数组表示的字符串 是由数组中的所有元素 按顺序 连接形成的字符串。
## 解题思路
- 简单题,依次拼接 2 个数组内的字符串,然后比较 str1 和 str2 是否相同即可。
## 代码
```go
package leetcode
func arrayStringsAreEqual(word1 []string, word2 []string) bool {
str1, str2 := "", ""
for i := 0; i < len(word1); i++ {
str1 += word1[i]
}
for i := 0; i < len(word2); i++ {
str2 += word2[i]
}
return str1 == str2
}
```

View File

@ -0,0 +1,104 @@
# [1663. Smallest String With A Given Numeric Value](https://leetcode.com/problems/smallest-string-with-a-given-numeric-value/)
## 题目
The **numeric value** of a **lowercase character** is defined as its position `(1-indexed)` in the alphabet, so the numeric value of `a` is `1`, the numeric value of `b` is `2`, the numeric value of `c` is `3`, and so on.
The **numeric value** of a **string** consisting of lowercase characters is defined as the sum of its characters' numeric values. For example, the numeric value of the string `"abe"` is equal to `1 + 2 + 5 = 8`.
You are given two integers `n` and `k`. Return *the **lexicographically smallest string** with **length** equal to `n` and **numeric value** equal to `k`.*
Note that a string `x` is lexicographically smaller than string `y` if `x` comes before `y` in dictionary order, that is, either `x` is a prefix of `y`, or if `i` is the first position such that `x[i] != y[i]`, then `x[i]` comes before `y[i]` in alphabetic order.
**Example 1:**
```
Input: n = 3, k = 27
Output: "aay"
Explanation: The numeric value of the string is 1 + 1 + 25 = 27, and it is the smallest string with such a value and length equal to 3.
```
**Example 2:**
```
Input: n = 5, k = 73
Output: "aaszz"
```
**Constraints:**
- `1 <= n <= 105`
- `n <= k <= 26 * n`
## 题目大意
小写字符 的 数值 是它在字母表中的位置(从 1 开始),因此 a 的数值为 1 b 的数值为 2 c 的数值为 3 ,以此类推。字符串由若干小写字符组成,字符串的数值 为各字符的数值之和。例如,字符串 "abe" 的数值等于 1 + 2 + 5 = 8 。给你两个整数 n 和 k 。返回 长度 等于 n 且 数值 等于 k 的 字典序最小 的字符串。注意,如果字符串 x 在字典排序中位于 y 之前,就认为 x 字典序比 y 小,有以下两种情况:
- x 是 y 的一个前缀;
- 如果 i 是 x[i] != y[i] 的第一个位置,且 x[i] 在字母表中的位置比 y[i] 靠前。
## 解题思路
- 给出 n 和 k要求找到字符串长度为 n字母在字母表内位置总和为 k 的最小字典序字符串。
- 这一题笔者读完题,比赛的时候直接用 DFS 撸了一版。赛后看了时间复杂度马马虎虎感觉还有优化的空间。DFS 会遍历出所有的解,实际上这一题只要求最小字典序,所以 DFS 剪枝的时候要加上判断字典序的判断,如果新添加进来的字母比已经保存的字符串的相应位置上的字母字典序大,那么就直接 return这个答案一定不会是最小字典序。代码见解法二
- 想到这里,其实 DFS 不必要,直接用 for 循环就可找到最小字典序的字符串。代码见解法一。
## 代码
```go
package leetcode
// 解法一 贪心
func getSmallestString(n int, k int) string {
res := make([]rune, n)
for i := n - 1; i >= 0; i-- {
diff := k - i
if diff >= 26 {
// Need to add z
res[i] = 'z'
k = k - 26
} else {
res[i] = rune('a' + diff - 1)
k = k - diff
}
}
return string(res)
}
// 解法二 DFS
func getSmallestString1(n int, k int) string {
if n == 0 {
return ""
}
res, c := "", []byte{}
findSmallestString(0, n, k, 0, c, &res)
return res
}
func findSmallestString(value int, length, k, index int, str []byte, res *string) {
if len(str) == length && value == k {
tmp := string(str)
if (*res) == "" {
*res = tmp
}
if tmp < *res && *res != "" {
*res = tmp
}
return
}
if len(str) >= index && (*res) != "" && str[index-1] > (*res)[index-1] {
return
}
for j := 0; j < 26; j++ {
if k-value > (length-len(str))*26 || value > k {
return
}
str = append(str, byte(int('a')+j))
value += j + 1
findSmallestString(value, length, k, index+1, str, res)
str = str[:len(str)-1]
value -= j + 1
}
}
```

View File

@ -0,0 +1,116 @@
# [1664. Ways to Make a Fair Array](https://leetcode.com/problems/ways-to-make-a-fair-array/)
## 题目
You are given an integer array `nums`. You can choose **exactly one** index (**0-indexed**) and remove the element. Notice that the index of the elements may change after the removal.
For example, if `nums = [6,1,7,4,1]`:
- Choosing to remove index `1` results in `nums = [6,7,4,1]`.
- Choosing to remove index `2` results in `nums = [6,1,4,1]`.
- Choosing to remove index `4` results in `nums = [6,1,7,4]`.
An array is **fair** if the sum of the odd-indexed values equals the sum of the even-indexed values.
Return the ***number** of indices that you could choose such that after the removal,* `nums` *is **fair**.*
**Example 1:**
```
Input: nums = [2,1,6,4]
Output: 1
Explanation:
Remove index 0: [1,6,4] -> Even sum: 1 + 4 = 5. Odd sum: 6. Not fair.
Remove index 1: [2,6,4] -> Even sum: 2 + 4 = 6. Odd sum: 6. Fair.
Remove index 2: [2,1,4] -> Even sum: 2 + 4 = 6. Odd sum: 1. Not fair.
Remove index 3: [2,1,6] -> Even sum: 2 + 6 = 8. Odd sum: 1. Not fair.
There is 1 index that you can remove to make nums fair.
```
**Example 2:**
```
Input: nums = [1,1,1]
Output: 3
Explanation: You can remove any index and the remaining array is fair.
```
**Example 3:**
```
Input: nums = [1,2,3]
Output: 0
Explanation: You cannot make a fair array after removing any index.
```
**Constraints:**
- `1 <= nums.length <= 105`
- `1 <= nums[i] <= 104`
## 题目大意
给你一个整数数组 nums 。你需要选择 恰好 一个下标(下标从 0 开始并删除对应的元素。请注意剩下元素的下标可能会因为删除操作而发生改变。
比方说如果 nums = [6,1,7,4,1] ,那么:
- 选择删除下标 1 剩下的数组为 nums = [6,7,4,1] 。
- 选择删除下标 2 剩下的数组为 nums = [6,1,4,1] 。
- 选择删除下标 4 剩下的数组为 nums = [6,1,7,4] 。
如果一个数组满足奇数下标元素的和与偶数下标元素的和相等,该数组就是一个 平衡数组 。请你返回删除操作后剩下的数组 nums  平衡数组 的 方案数 。
## 解题思路
- 给定一个数组 nums要求输出仅删除一个元素以后能使得整个数组平衡的方案数。平衡的定义是奇数下标元素总和等于偶数下标元素总和。
- 这一题如果暴力解答,会超时。原因是每次删除元素以后,都重新计算奇偶数位总和比较耗时。应该利用前面计算过的累加和,推导出此次删除元素以后的情况。这样修改以后就不超时了。具体的,如果删除的是元素是奇数位,这个下标的前缀和不变,要变化的是后面的。删除元素后面,原来偶数位的总和变成了奇数位了,原来奇数位的总和变成偶数位了。删除元素后面这半段的总和可以用前缀和计算出来,奇数位的总和减去删除元素的前缀和,就得到了删除元素后面的后缀和。通过这个办法就可以得到删除元素后面的,奇数位总和,偶数位总和。注意这个后缀和是包含了删除元素的。所以最后需要判断删除元素是奇数位还是偶数位,如果是奇数位,那么在计算出来的偶数和上再减去这个删除元素;如果是偶数位,就在计算出来的奇数和上再减去这个删除元素。代码见解法二。
- 这一题还有一种更简洁的写法,就是解法一了。通过了解法二的思考,我们可以知道,每次变换以后的操作可以抽象出来,即三步,减去一个数,判断是否相等,再加上一个数。只不过这三步在解法二中都去判断了奇偶性。如果我们不判断奇偶性,那么代码就可以写成解法一的样子。为什么可以不用管奇偶性呢?因为每次删除一个元素以后,下次再删除,奇偶就发生颠倒了,上次的奇数和到了下次就是偶数和了。想通这一点就可以把代码写成解法一的样子。
## 代码
```go
// 解法一 超简洁写法
func waysToMakeFair(nums []int) int {
sum, res := [2]int{}, 0
for i := 0; i < len(nums); i++ {
sum[i%2] += nums[i]
}
for i := 0; i < len(nums); i++ {
sum[i%2] -= nums[i]
if sum[i%2] == sum[1-(i%2)] {
res++
}
sum[1-(i%2)] += nums[i]
}
return res
}
// 解法二 前缀和,后缀和
func waysToMakeFair1(nums []int) int {
evenPrefix, oddPrefix, evenSuffix, oddSuffix, res := 0, 0, 0, 0, 0
for i := 0; i < len(nums); i++ {
if i%2 == 0 {
evenSuffix += nums[i]
} else {
oddSuffix += nums[i]
}
}
for i := 0; i < len(nums); i++ {
if i%2 == 0 {
evenSuffix -= nums[i]
} else {
oddSuffix -= nums[i]
}
if (evenPrefix + oddSuffix) == (oddPrefix + evenSuffix) {
res++
}
if i%2 == 0 {
evenPrefix += nums[i]
} else {
oddPrefix += nums[i]
}
}
return res
}
```

View File

@ -0,0 +1,128 @@
# [1665. Minimum Initial Energy to Finish Tasks](https://leetcode.com/problems/minimum-initial-energy-to-finish-tasks/)
## 题目
You are given an array `tasks` where `tasks[i] = [actuali, minimumi]`:
- `actuali` is the actual amount of energy you **spend to finish** the `ith` task.
- `minimumi` is the minimum amount of energy you **require to begin** the `ith` task.
For example, if the task is `[10, 12]` and your current energy is `11`, you cannot start this task. However, if your current energy is `13`, you can complete this task, and your energy will be `3` after finishing it.
You can finish the tasks in **any order** you like.
Return *the **minimum** initial amount of energy you will need* *to finish all the tasks*.
**Example 1:**
```
Input: tasks = [[1,2],[2,4],[4,8]]
Output: 8
Explanation:
Starting with 8 energy, we finish the tasks in the following order:
- 3rd task. Now energy = 8 - 4 = 4.
- 2nd task. Now energy = 4 - 2 = 2.
- 1st task. Now energy = 2 - 1 = 1.
Notice that even though we have leftover energy, starting with 7 energy does not work because we cannot do the 3rd task.
```
**Example 2:**
```
Input: tasks = [[1,3],[2,4],[10,11],[10,12],[8,9]]
Output: 32
Explanation:
Starting with 32 energy, we finish the tasks in the following order:
- 1st task. Now energy = 32 - 1 = 31.
- 2nd task. Now energy = 31 - 2 = 29.
- 3rd task. Now energy = 29 - 10 = 19.
- 4th task. Now energy = 19 - 10 = 9.
- 5th task. Now energy = 9 - 8 = 1.
```
**Example 3:**
```
Input: tasks = [[1,7],[2,8],[3,9],[4,10],[5,11],[6,12]]
Output: 27
Explanation:
Starting with 27 energy, we finish the tasks in the following order:
- 5th task. Now energy = 27 - 5 = 22.
- 2nd task. Now energy = 22 - 2 = 20.
- 3rd task. Now energy = 20 - 3 = 17.
- 1st task. Now energy = 17 - 1 = 16.
- 4th task. Now energy = 16 - 4 = 12.
- 6th task. Now energy = 12 - 6 = 6.
```
**Constraints:**
- `1 <= tasks.length <= 105`
- `1 <= actuali <= minimumi <= 104`
## 题目大意
给你一个任务数组 tasks 其中 tasks[i] = [actuali, minimumi] 
- actual i 是完成第 i 个任务 需要耗费 的实际能量。
- minimum i 是开始第 i 个任务前需要达到的最低能量。
比方说,如果任务为 [10, 12] 且你当前的能量为 11 那么你不能开始这个任务。如果你当前的能量为 13 你可以完成这个任务且完成它后剩余能量为 3 。你可以按照 任意顺序 完成任务。请你返回完成所有任务的 最少 初始能量。
## 解题思路
- 给出一个 task 数组,每个元素代表一个任务,每个任务有实际消费能量值和开始这个任务需要的最低能量。要求输出能完成所有任务的最少初始能量。
- 这一题直觉是贪心。先将任务按照 `minimum - actual` 进行排序。先完成差值大的任务,那么接下来的能量能最大限度的满足接下来的任务。这样可能完成所有任务的可能性越大。循环任务数组的时候,保存当前能量在 `cur` 中,如果当前能量不够开启下一个任务,那么这个差值就是需要弥补的,这些能量就是最少初始能量中的,所以加上这些差值能量。如果当前能量可以开启下一个任务,那么就更新当前能量,减去实际消耗的能量以后,再继续循环。循环结束就能得到最少初始能量了。
## 代码
```go
package leetcode
import (
"sort"
)
func minimumEffort(tasks [][]int) int {
sort.Sort(Task(tasks))
res, cur := 0, 0
for _, t := range tasks {
if t[1] > cur {
res += t[1] - cur
cur = t[1] - t[0]
} else {
cur -= t[0]
}
}
return res
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
// Task define
type Task [][]int
func (task Task) Len() int {
return len(task)
}
func (task Task) Less(i, j int) bool {
t1, t2 := task[i][1]-task[i][0], task[j][1]-task[j][0]
if t1 != t2 {
return t2 < t1
}
return task[j][1] < task[i][1]
}
func (task Task) Swap(i, j int) {
t := task[i]
task[i] = task[j]
task[j] = t
}
```

View File

@ -556,4 +556,8 @@ headless: true
- [1657.Determine-if-Two-Strings-Are-Close]({{< relref "/ChapterFour/1657.Determine-if-Two-Strings-Are-Close.md" >}})
- [1658.Minimum-Operations-to-Reduce-X-to-Zero]({{< relref "/ChapterFour/1658.Minimum-Operations-to-Reduce-X-to-Zero.md" >}})
- [1659.Maximize-Grid-Happiness]({{< relref "/ChapterFour/1659.Maximize-Grid-Happiness.md" >}})
- [1662.Check-If-Two-String-Arrays-are-Equivalent]({{< relref "/ChapterFour/1662.Check-If-Two-String-Arrays-are-Equivalent.md" >}})
- [1663.Smallest-String-With-A-Given-Numeric-Value]({{< relref "/ChapterFour/1663.Smallest-String-With-A-Given-Numeric-Value.md" >}})
- [1664.Ways-to-Make-a-Fair-Array]({{< relref "/ChapterFour/1664.Ways-to-Make-a-Fair-Array.md" >}})
- [1665.Minimum-Initial-Energy-to-Finish-Tasks]({{< relref "/ChapterFour/1665.Minimum-Initial-Energy-to-Finish-Tasks.md" >}})
<br />