mirror of
https://github.com/halfrost/LeetCode-Go.git
synced 2025-07-06 09:23:19 +08:00
Add solution 560、1763、2164、2165、2166、2167、2169、2170、2171、2180、2181、2182、2183、
This commit is contained in:
@ -0,0 +1,15 @@
|
||||
package leetcode
|
||||
|
||||
func subarraySum(nums []int, k int) int {
|
||||
count, pre := 0, 0
|
||||
m := map[int]int{}
|
||||
m[0] = 1
|
||||
for i := 0; i < len(nums); i++ {
|
||||
pre += nums[i]
|
||||
if _, ok := m[pre-k]; ok {
|
||||
count += m[pre-k]
|
||||
}
|
||||
m[pre] += 1
|
||||
}
|
||||
return count
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question560 struct {
|
||||
para560
|
||||
ans560
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para560 struct {
|
||||
nums []int
|
||||
k int
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans560 struct {
|
||||
one int
|
||||
}
|
||||
|
||||
func Test_Problem560(t *testing.T) {
|
||||
|
||||
qs := []question560{
|
||||
|
||||
{
|
||||
para560{[]int{1, 1, 1}, 2},
|
||||
ans560{2},
|
||||
},
|
||||
|
||||
{
|
||||
para560{[]int{1, 2, 3}, 3},
|
||||
ans560{2},
|
||||
},
|
||||
|
||||
{
|
||||
para560{[]int{1}, 0},
|
||||
ans560{0},
|
||||
},
|
||||
|
||||
{
|
||||
para560{[]int{-1, -1, 1}, 0},
|
||||
ans560{1},
|
||||
},
|
||||
|
||||
{
|
||||
para560{[]int{1, -1, 0}, 0},
|
||||
ans560{3},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 560------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans560, q.para560
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, subarraySum(p.nums, p.k))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
58
leetcode/0560.Subarray-Sum-Equals-K/README.md
Normal file
58
leetcode/0560.Subarray-Sum-Equals-K/README.md
Normal file
@ -0,0 +1,58 @@
|
||||
# [560. Subarray Sum Equals K](https://leetcode.com/problems/subarray-sum-equals-k/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
Given an array of integers `nums` and an integer `k`, return *the total number of continuous subarrays whose sum equals to `k`*.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: nums = [1,1,1], k = 2
|
||||
Output: 2
|
||||
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: nums = [1,2,3], k = 3
|
||||
Output: 2
|
||||
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `1 <= nums.length <= 2 * 104`
|
||||
- `-1000 <= nums[i] <= 1000`
|
||||
- `-10^7 <= k <= 10^7`
|
||||
|
||||
## 题目大意
|
||||
|
||||
给你一个整数数组 `nums` 和一个整数 `k` ,请你统计并返回该数组中和为 `k` ****的连续子数组的个数。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 此题不能使用滑动窗口来解。因为 `nums[i]` 可能为负数。
|
||||
- 前缀和的思路可以解答此题,但是时间复杂度有点高了,`O(n^2)`。考虑优化时间复杂度。
|
||||
- 题目要求找到连续区间和为 `k` 的子区间总数,即区间 `[i,j]` 内的和为 K ⇒ `prefixSum[j] - prefixSum[i-1] == k`。所以 `prefixSum[j] == k - prefixSum[i-1]` 。这样转换以后,题目就转换成类似 A + B = K 的问题了。LeetCode 第一题的优化思路拿来用。用 map 存储累加过的结果。如此优化以后,时间复杂度 `O(n)`。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
func subarraySum(nums []int, k int) int {
|
||||
count, pre := 0, 0
|
||||
m := map[int]int{}
|
||||
m[0] = 1
|
||||
for i := 0; i < len(nums); i++ {
|
||||
pre += nums[i]
|
||||
if _, ok := m[pre-k]; ok {
|
||||
count += m[pre-k]
|
||||
}
|
||||
m[pre] += 1
|
||||
}
|
||||
return count
|
||||
}
|
||||
```
|
@ -0,0 +1,17 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_Problem677(t *testing.T) {
|
||||
obj := Constructor()
|
||||
fmt.Printf("obj = %v\n", obj)
|
||||
obj.Insert("apple", 3)
|
||||
fmt.Printf("obj = %v\n", obj)
|
||||
fmt.Printf("obj.sum = %v\n", obj.Sum("ap"))
|
||||
obj.Insert("app", 2)
|
||||
fmt.Printf("obj = %v\n", obj)
|
||||
fmt.Printf("obj.sum = %v\n", obj.Sum("ap"))
|
||||
}
|
||||
|
@ -0,0 +1,82 @@
|
||||
package leetcode
|
||||
|
||||
import "unicode"
|
||||
|
||||
// 解法一 分治,时间复杂度 O(n)
|
||||
func longestNiceSubstring(s string) string {
|
||||
if len(s) < 2 {
|
||||
return ""
|
||||
}
|
||||
|
||||
chars := map[rune]int{}
|
||||
for _, r := range s {
|
||||
chars[r]++
|
||||
}
|
||||
|
||||
for i := 0; i < len(s); i++ {
|
||||
r := rune(s[i])
|
||||
_, u := chars[unicode.ToUpper(r)]
|
||||
_, l := chars[unicode.ToLower(r)]
|
||||
if u && l {
|
||||
continue
|
||||
}
|
||||
left := longestNiceSubstring(s[:i])
|
||||
right := longestNiceSubstring(s[i+1:])
|
||||
if len(left) >= len(right) {
|
||||
return left
|
||||
} else {
|
||||
return right
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// 解法二 用二进制表示状态
|
||||
func longestNiceSubstring1(s string) (ans string) {
|
||||
for i := range s {
|
||||
lower, upper := 0, 0
|
||||
for j := i; j < len(s); j++ {
|
||||
if unicode.IsLower(rune(s[j])) {
|
||||
lower |= 1 << (s[j] - 'a')
|
||||
} else {
|
||||
upper |= 1 << (s[j] - 'A')
|
||||
}
|
||||
if lower == upper && j-i+1 > len(ans) {
|
||||
ans = s[i : j+1]
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 解法三 暴力枚举,时间复杂度 O(n^2)
|
||||
func longestNiceSubstring2(s string) string {
|
||||
res := ""
|
||||
for i := 0; i < len(s); i++ {
|
||||
m := map[byte]int{}
|
||||
m[s[i]]++
|
||||
for j := i + 1; j < len(s); j++ {
|
||||
m[s[j]]++
|
||||
if checkNiceString(m) && (j-i+1 > len(res)) {
|
||||
res = s[i : j+1]
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func checkNiceString(m map[byte]int) bool {
|
||||
for k := range m {
|
||||
if k >= 97 && k <= 122 {
|
||||
if _, ok := m[k-32]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if k >= 65 && k <= 90 {
|
||||
if _, ok := m[k+32]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question1763 struct {
|
||||
para1763
|
||||
ans1763
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para1763 struct {
|
||||
s string
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans1763 struct {
|
||||
one string
|
||||
}
|
||||
|
||||
func Test_Problem1763(t *testing.T) {
|
||||
|
||||
qs := []question1763{
|
||||
|
||||
{
|
||||
para1763{"YazaAay"},
|
||||
ans1763{"aAa"},
|
||||
},
|
||||
|
||||
{
|
||||
para1763{"Bb"},
|
||||
ans1763{"Bb"},
|
||||
},
|
||||
|
||||
{
|
||||
para1763{"c"},
|
||||
ans1763{""},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 1763------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans1763, q.para1763
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, longestNiceSubstring(p.s))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
140
leetcode/1763.Longest-Nice-Substring/README.md
Normal file
140
leetcode/1763.Longest-Nice-Substring/README.md
Normal file
@ -0,0 +1,140 @@
|
||||
# [1763. Longest Nice Substring](https://leetcode.com/problems/longest-nice-substring/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
A string `s` is **nice** if, for every letter of the alphabet that `s` contains, it appears **both** in uppercase and lowercase. For example, `"abABB"` is nice because `'A'` and `'a'` appear, and `'B'` and `'b'` appear. However, `"abA"` is not because `'b'` appears, but `'B'` does not.
|
||||
|
||||
Given a string `s`, return *the longest **substring** of `s` that is **nice**. If there are multiple, return the substring of the **earliest** occurrence. If there are none, return an empty string*.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: s = "YazaAay"
|
||||
Output: "aAa"
|
||||
Explanation:"aAa" is a nice string because 'A/a' is the only letter of the alphabet in s, and both 'A' and 'a' appear.
|
||||
"aAa" is the longest nice substring.
|
||||
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: s = "Bb"
|
||||
Output: "Bb"
|
||||
Explanation: "Bb" is a nice string because both 'B' and 'b' appear. The whole string is a substring.
|
||||
|
||||
```
|
||||
|
||||
**Example 3:**
|
||||
|
||||
```
|
||||
Input: s = "c"
|
||||
Output: ""
|
||||
Explanation: There are no nice substrings.
|
||||
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `1 <= s.length <= 100`
|
||||
- `s` consists of uppercase and lowercase English letters.
|
||||
|
||||
## 题目大意
|
||||
|
||||
当一个字符串 s 包含的每一种字母的大写和小写形式 同时 出现在 s 中,就称这个字符串 s 是 美好 字符串。比方说,"abABB" 是美好字符串,因为 'A' 和 'a' 同时出现了,且 'B' 和 'b' 也同时出现了。然而,"abA" 不是美好字符串因为 'b' 出现了,而 'B' 没有出现。
|
||||
|
||||
给你一个字符串 s ,请你返回 s 最长的 美好子字符串 。如果有多个答案,请你返回 最早 出现的一个。如果不存在美好子字符串,请你返回一个空字符串。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 解法一,暴力解法。枚举每一段字符串,判断这个子字符串内是否满足美好字符串的定义,即字母的大小写是否同时出现。
|
||||
- 解法二,这个解法是解法一的小幅优化版,利用二进制记录状态。先构造二进制状态串,再利用直接比较这个二进制串。
|
||||
- 解法三,分治。以 `i` 为分割点依次切开字符串。左右两个字符串分别判断是否满足美好字符串的定义。左右分开的字符串还可以继续划分。直至分到一个字母为止。在这个过程中记录最早出现的字符串。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
import "unicode"
|
||||
|
||||
// 解法一 分治,时间复杂度 O(n)
|
||||
func longestNiceSubstring(s string) string {
|
||||
if len(s) < 2 {
|
||||
return ""
|
||||
}
|
||||
|
||||
chars := map[rune]int{}
|
||||
for _, r := range s {
|
||||
chars[r]++
|
||||
}
|
||||
|
||||
for i := 0; i < len(s); i++ {
|
||||
r := rune(s[i])
|
||||
_, u := chars[unicode.ToUpper(r)]
|
||||
_, l := chars[unicode.ToLower(r)]
|
||||
if u && l {
|
||||
continue
|
||||
}
|
||||
left := longestNiceSubstring(s[:i])
|
||||
right := longestNiceSubstring(s[i+1:])
|
||||
if len(left) >= len(right) {
|
||||
return left
|
||||
} else {
|
||||
return right
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// 解法二 用二进制表示状态
|
||||
func longestNiceSubstring1(s string) (ans string) {
|
||||
for i := range s {
|
||||
lower, upper := 0, 0
|
||||
for j := i; j < len(s); j++ {
|
||||
if unicode.IsLower(rune(s[j])) {
|
||||
lower |= 1 << (s[j] - 'a')
|
||||
} else {
|
||||
upper |= 1 << (s[j] - 'A')
|
||||
}
|
||||
if lower == upper && j-i+1 > len(ans) {
|
||||
ans = s[i : j+1]
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 解法三 暴力枚举,时间复杂度 O(n^2)
|
||||
func longestNiceSubstring2(s string) string {
|
||||
res := ""
|
||||
for i := 0; i < len(s); i++ {
|
||||
m := map[byte]int{}
|
||||
m[s[i]]++
|
||||
for j := i + 1; j < len(s); j++ {
|
||||
m[s[j]]++
|
||||
if checkNiceString(m) && (j-i+1 > len(res)) {
|
||||
res = s[i : j+1]
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func checkNiceString(m map[byte]int) bool {
|
||||
for k := range m {
|
||||
if k >= 97 && k <= 122 {
|
||||
if _, ok := m[k-32]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if k >= 65 && k <= 90 {
|
||||
if _, ok := m[k+32]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
```
|
@ -0,0 +1,30 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
func sortEvenOdd(nums []int) []int {
|
||||
odd, even, res := []int{}, []int{}, []int{}
|
||||
for index, v := range nums {
|
||||
if index%2 == 0 {
|
||||
even = append(even, v)
|
||||
} else {
|
||||
odd = append(odd, v)
|
||||
}
|
||||
}
|
||||
sort.Ints(even)
|
||||
sort.Sort(sort.Reverse(sort.IntSlice(odd)))
|
||||
|
||||
indexO, indexE := 0, 0
|
||||
for i := 0; i < len(nums); i++ {
|
||||
if i%2 == 0 {
|
||||
res = append(res, even[indexE])
|
||||
indexE++
|
||||
} else {
|
||||
res = append(res, odd[indexO])
|
||||
indexO++
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question2164 struct {
|
||||
para2164
|
||||
ans2164
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para2164 struct {
|
||||
nums []int
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans2164 struct {
|
||||
one []int
|
||||
}
|
||||
|
||||
func Test_Problem1(t *testing.T) {
|
||||
|
||||
qs := []question2164{
|
||||
{
|
||||
para2164{[]int{4, 1, 2, 3}},
|
||||
ans2164{[]int{2, 3, 4, 1}},
|
||||
},
|
||||
|
||||
{
|
||||
para2164{[]int{2, 1}},
|
||||
ans2164{[]int{2, 1}},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 2164------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans2164, q.para2164
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, sortEvenOdd(p.nums))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
# [2164. Sort Even and Odd Indices Independently](https://leetcode.com/problems/sort-even-and-odd-indices-independently/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
You are given a **0-indexed** integer array `nums`. Rearrange the values of `nums` according to the following rules:
|
||||
|
||||
1. Sort the values at **odd indices** of `nums` in **non-increasing** order.
|
||||
- For example, if `nums = [4,**1**,2,**3**]` before this step, it becomes `[4,**3**,2,**1**]` after. The values at odd indices `1` and `3` are sorted in non-increasing order.
|
||||
2. Sort the values at **even indices** of `nums` in **non-decreasing** order.
|
||||
- For example, if `nums = [**4**,1,**2**,3]` before this step, it becomes `[**2**,1,**4**,3]` after. The values at even indices `0` and `2` are sorted in non-decreasing order.
|
||||
|
||||
Return *the array formed after rearranging the values of* `nums`.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: nums = [4,1,2,3]
|
||||
Output: [2,3,4,1]
|
||||
Explanation:
|
||||
First, we sort the values present at odd indices (1 and 3) in non-increasing order.
|
||||
So, nums changes from [4,1,2,3] to [4,3,2,1].
|
||||
Next, we sort the values present at even indices (0 and 2) in non-decreasing order.
|
||||
So, nums changes from [4,1,2,3] to [2,3,4,1].
|
||||
Thus, the array formed after rearranging the values is [2,3,4,1].
|
||||
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: nums = [2,1]
|
||||
Output: [2,1]
|
||||
Explanation:
|
||||
Since there is exactly one odd index and one even index, no rearrangement of values takes place.
|
||||
The resultant array formed is [2,1], which is the same as the initial array.
|
||||
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `1 <= nums.length <= 100`
|
||||
- `1 <= nums[i] <= 100`
|
||||
|
||||
## 题目大意
|
||||
|
||||
给你一个下标从 0 开始的整数数组 nums 。根据下述规则重排 nums 中的值:
|
||||
|
||||
1. 按 非递增 顺序排列 nums 奇数下标 上的所有值。
|
||||
举个例子,如果排序前 nums = [4,1,2,3] ,对奇数下标的值排序后变为 [4,3,2,1] 。奇数下标 1 和 3 的值按照非递增顺序重排。
|
||||
2. 按 非递减 顺序排列 nums 偶数下标 上的所有值。
|
||||
举个例子,如果排序前 nums = [4,1,2,3] ,对偶数下标的值排序后变为 [2,1,4,3] 。偶数下标 0 和 2 的值按照非递减顺序重排。
|
||||
|
||||
返回重排 nums 的值之后形成的数组。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 简单题。分别将奇数和偶数位上的数字排序,奇数位的数从大到小,偶数位的数从小到大。最后将他们组合成一个数组。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
func sortEvenOdd(nums []int) []int {
|
||||
odd, even, res := []int{}, []int{}, []int{}
|
||||
for index, v := range nums {
|
||||
if index%2 == 0 {
|
||||
even = append(even, v)
|
||||
} else {
|
||||
odd = append(odd, v)
|
||||
}
|
||||
}
|
||||
sort.Ints(even)
|
||||
sort.Sort(sort.Reverse(sort.IntSlice(odd)))
|
||||
|
||||
indexO, indexE := 0, 0
|
||||
for i := 0; i < len(nums); i++ {
|
||||
if i%2 == 0 {
|
||||
res = append(res, even[indexE])
|
||||
indexE++
|
||||
} else {
|
||||
res = append(res, odd[indexO])
|
||||
indexO++
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
```
|
@ -0,0 +1,51 @@
|
||||
package leetcode
|
||||
|
||||
import "sort"
|
||||
|
||||
func smallestNumber(num int64) int64 {
|
||||
pos := true
|
||||
if num < 0 {
|
||||
pos = false
|
||||
num *= -1
|
||||
}
|
||||
nums, m, res := []int{}, map[int]int{}, 0
|
||||
for num != 0 {
|
||||
tmp := int(num % 10)
|
||||
m[tmp]++
|
||||
num = num / 10
|
||||
}
|
||||
|
||||
for k := range m {
|
||||
nums = append(nums, k)
|
||||
}
|
||||
if pos {
|
||||
sort.Ints(nums)
|
||||
} else {
|
||||
sort.Sort(sort.Reverse(sort.IntSlice(nums)))
|
||||
}
|
||||
|
||||
if nums[0] == 0 && len(nums) > 1 {
|
||||
res += nums[1]
|
||||
m[nums[1]]--
|
||||
}
|
||||
|
||||
for _, v := range nums {
|
||||
if res != 0 {
|
||||
for j := m[v]; j > 0; j-- {
|
||||
res = res * 10
|
||||
res += v
|
||||
}
|
||||
} else {
|
||||
res += v
|
||||
tmp := m[v] - 1
|
||||
for j := tmp; j > 0; j-- {
|
||||
res = res * 10
|
||||
res += v
|
||||
}
|
||||
}
|
||||
}
|
||||
if !pos {
|
||||
return -1 * int64(res)
|
||||
}
|
||||
return int64(res)
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question2165 struct {
|
||||
para2165
|
||||
ans2165
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para2165 struct {
|
||||
nums int64
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans2165 struct {
|
||||
one int64
|
||||
}
|
||||
|
||||
func Test_Problem1(t *testing.T) {
|
||||
|
||||
qs := []question2165{
|
||||
|
||||
{
|
||||
para2165{310},
|
||||
ans2165{103},
|
||||
},
|
||||
|
||||
{
|
||||
para2165{5059},
|
||||
ans2165{5059},
|
||||
},
|
||||
|
||||
{
|
||||
para2165{-7605},
|
||||
ans2165{-7650},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 2165------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans2165, q.para2165
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, smallestNumber(p.nums))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
101
leetcode/2165.Smallest-Value-of-the-Rearranged-Number/README.md
Normal file
101
leetcode/2165.Smallest-Value-of-the-Rearranged-Number/README.md
Normal file
@ -0,0 +1,101 @@
|
||||
# [2165. Smallest Value of the Rearranged Number](https://leetcode.com/problems/smallest-value-of-the-rearranged-number/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
You are given an integer `num.` **Rearrange** the digits of `num` such that its value is **minimized** and it does not contain **any** leading zeros.
|
||||
|
||||
Return *the rearranged number with minimal value*.
|
||||
|
||||
Note that the sign of the number does not change after rearranging the digits.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: num = 310
|
||||
Output: 103
|
||||
Explanation: The possible arrangements for the digits of 310 are 013, 031, 103, 130, 301, 310.
|
||||
The arrangement with the smallest value that does not contain any leading zeros is 103.
|
||||
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: num = -7605
|
||||
Output: -7650
|
||||
Explanation: Some possible arrangements for the digits of -7605 are -7650, -6705, -5076, -0567.
|
||||
The arrangement with the smallest value that does not contain any leading zeros is -7650.
|
||||
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `10^15 <= num <= 10^15`
|
||||
|
||||
## 题目大意
|
||||
|
||||
给你一个整数 num 。重排 num 中的各位数字,使其值 最小化 且不含 任何 前导零。
|
||||
|
||||
返回不含前导零且值最小的重排数字。注意,重排各位数字后,num 的符号不会改变。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 先将每个数字出现次数统计出来。然后将数字大小从小到大排序。如果原数是正数,当出现有数字 0 的情况的时候,需先将第二小的数字排列到第一个,再把 0 排列完。再继续排列第二小,第三小。。。
|
||||
- 如果原数是负数。那么就逆序排列,即先排列最大的数字,然后次大的数字,直到排列最小的数字。因为数字越大,对应的这个数的负数就越小。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
import "sort"
|
||||
|
||||
func smallestNumber(num int64) int64 {
|
||||
pos := true
|
||||
if num < 0 {
|
||||
pos = false
|
||||
num *= -1
|
||||
}
|
||||
nums, m, res := []int{}, map[int]int{}, 0
|
||||
for num != 0 {
|
||||
tmp := int(num % 10)
|
||||
m[tmp]++
|
||||
num = num / 10
|
||||
}
|
||||
|
||||
for k := range m {
|
||||
nums = append(nums, k)
|
||||
}
|
||||
if pos {
|
||||
sort.Ints(nums)
|
||||
} else {
|
||||
sort.Sort(sort.Reverse(sort.IntSlice(nums)))
|
||||
}
|
||||
|
||||
if nums[0] == 0 && len(nums) > 1 {
|
||||
res += nums[1]
|
||||
m[nums[1]]--
|
||||
}
|
||||
|
||||
for _, v := range nums {
|
||||
if res != 0 {
|
||||
for j := m[v]; j > 0; j-- {
|
||||
res = res * 10
|
||||
res += v
|
||||
}
|
||||
} else {
|
||||
res += v
|
||||
tmp := m[v] - 1
|
||||
for j := tmp; j > 0; j-- {
|
||||
res = res * 10
|
||||
res += v
|
||||
}
|
||||
}
|
||||
}
|
||||
if !pos {
|
||||
return -1 * int64(res)
|
||||
}
|
||||
return int64(res)
|
||||
}
|
||||
```
|
72
leetcode/2166.Design-Bitset/2166. Design Bitset.go
Normal file
72
leetcode/2166.Design-Bitset/2166. Design Bitset.go
Normal file
@ -0,0 +1,72 @@
|
||||
package leetcode
|
||||
|
||||
type Bitset struct {
|
||||
set []byte
|
||||
flipped []byte
|
||||
oneCount int
|
||||
size int
|
||||
}
|
||||
|
||||
func Constructor(size int) Bitset {
|
||||
set := make([]byte, size)
|
||||
flipped := make([]byte, size)
|
||||
for i := 0; i < size; i++ {
|
||||
set[i] = byte('0')
|
||||
flipped[i] = byte('1')
|
||||
}
|
||||
return Bitset{
|
||||
set: set,
|
||||
flipped: flipped,
|
||||
oneCount: 0,
|
||||
size: size,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Bitset) Fix(idx int) {
|
||||
if this.set[idx] == byte('0') {
|
||||
this.set[idx] = byte('1')
|
||||
this.flipped[idx] = byte('0')
|
||||
this.oneCount++
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Bitset) Unfix(idx int) {
|
||||
if this.set[idx] == byte('1') {
|
||||
this.set[idx] = byte('0')
|
||||
this.flipped[idx] = byte('1')
|
||||
this.oneCount--
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Bitset) Flip() {
|
||||
this.set, this.flipped = this.flipped, this.set
|
||||
this.oneCount = this.size - this.oneCount
|
||||
}
|
||||
|
||||
func (this *Bitset) All() bool {
|
||||
return this.oneCount == this.size
|
||||
}
|
||||
|
||||
func (this *Bitset) One() bool {
|
||||
return this.oneCount != 0
|
||||
}
|
||||
|
||||
func (this *Bitset) Count() int {
|
||||
return this.oneCount
|
||||
}
|
||||
|
||||
func (this *Bitset) ToString() string {
|
||||
return string(this.set)
|
||||
}
|
||||
|
||||
/**
|
||||
* Your Bitset object will be instantiated and called as such:
|
||||
* obj := Constructor(size);
|
||||
* obj.Fix(idx);
|
||||
* obj.Unfix(idx);
|
||||
* obj.Flip();
|
||||
* param_4 := obj.All();
|
||||
* param_5 := obj.One();
|
||||
* param_6 := obj.Count();
|
||||
* param_7 := obj.ToString();
|
||||
*/
|
31
leetcode/2166.Design-Bitset/2166. Design Bitset_test.go
Normal file
31
leetcode/2166.Design-Bitset/2166. Design Bitset_test.go
Normal file
@ -0,0 +1,31 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_Problem2166(t *testing.T) {
|
||||
obj := Constructor(5)
|
||||
fmt.Printf("obj = %v\n", obj)
|
||||
|
||||
obj.Fix(3)
|
||||
fmt.Printf("obj = %v\n", obj)
|
||||
obj.Fix(1)
|
||||
fmt.Printf("obj = %v\n", obj)
|
||||
obj.Flip()
|
||||
fmt.Printf("obj = %v\n", obj)
|
||||
|
||||
fmt.Printf("all = %v\n", obj.All())
|
||||
obj.Unfix(0)
|
||||
fmt.Printf("obj = %v\n", obj)
|
||||
obj.Flip()
|
||||
fmt.Printf("obj = %v\n", obj)
|
||||
|
||||
fmt.Printf("one = %v\n", obj.One())
|
||||
obj.Unfix(0)
|
||||
fmt.Printf("obj = %v\n", obj)
|
||||
|
||||
fmt.Printf("count = %v\n", obj.Count())
|
||||
fmt.Printf("toString = %v\n", obj.ToString())
|
||||
}
|
156
leetcode/2166.Design-Bitset/README.md
Normal file
156
leetcode/2166.Design-Bitset/README.md
Normal file
@ -0,0 +1,156 @@
|
||||
# [2166. Design Bitset](https://leetcode.com/problems/design-bitset/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
A **Bitset** is a data structure that compactly stores bits.
|
||||
|
||||
Implement the `Bitset` class:
|
||||
|
||||
- `Bitset(int size)` Initializes the Bitset with `size` bits, all of which are `0`.
|
||||
- `void fix(int idx)` Updates the value of the bit at the index `idx` to `1`. If the value was already `1`, no change occurs.
|
||||
- `void unfix(int idx)` Updates the value of the bit at the index `idx` to `0`. If the value was already `0`, no change occurs.
|
||||
- `void flip()` Flips the values of each bit in the Bitset. In other words, all bits with value `0` will now have value `1` and vice versa.
|
||||
- `boolean all()` Checks if the value of **each** bit in the Bitset is `1`. Returns `true` if it satisfies the condition, `false` otherwise.
|
||||
- `boolean one()` Checks if there is **at least one** bit in the Bitset with value `1`. Returns `true` if it satisfies the condition, `false` otherwise.
|
||||
- `int count()` Returns the **total number** of bits in the Bitset which have value `1`.
|
||||
- `String toString()` Returns the current composition of the Bitset. Note that in the resultant string, the character at the `ith` index should coincide with the value at the `ith` bit of the Bitset.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input
|
||||
["Bitset", "fix", "fix", "flip", "all", "unfix", "flip", "one", "unfix", "count", "toString"]
|
||||
[[5], [3], [1], [], [], [0], [], [], [0], [], []]
|
||||
Output
|
||||
[null, null, null, null, false, null, null, true, null, 2, "01010"]
|
||||
|
||||
Explanation
|
||||
Bitset bs = new Bitset(5); // bitset = "00000".
|
||||
bs.fix(3); // the value at idx = 3 is updated to 1, so bitset = "00010".
|
||||
bs.fix(1); // the value at idx = 1 is updated to 1, so bitset = "01010".
|
||||
bs.flip(); // the value of each bit is flipped, so bitset = "10101".
|
||||
bs.all(); // return False, as not all values of the bitset are 1.
|
||||
bs.unfix(0); // the value at idx = 0 is updated to 0, so bitset = "00101".
|
||||
bs.flip(); // the value of each bit is flipped, so bitset = "11010".
|
||||
bs.one(); // return True, as there is at least 1 index with value 1.
|
||||
bs.unfix(0); // the value at idx = 0 is updated to 0, so bitset = "01010".
|
||||
bs.count(); // return 2, as there are 2 bits with value 1.
|
||||
bs.toString(); // return "01010", which is the composition of bitset.
|
||||
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `1 <= size <= 10^5`
|
||||
- `0 <= idx <= size - 1`
|
||||
- At most `10^5` calls will be made **in total** to `fix`, `unfix`, `flip`, `all`, `one`, `count`, and `toString`.
|
||||
- At least one call will be made to `all`, `one`, `count`, or `toString`.
|
||||
- At most `5` calls will be made to `toString`.
|
||||
|
||||
## 题目大意
|
||||
|
||||
位集 Bitset 是一种能以紧凑形式存储位的数据结构。
|
||||
|
||||
请你实现 Bitset 类。
|
||||
|
||||
- Bitset(int size) 用 size 个位初始化 Bitset ,所有位都是 0 。
|
||||
- void fix(int idx) 将下标为 idx 的位上的值更新为 1 。如果值已经是 1 ,则不会发生任何改变。
|
||||
- void unfix(int idx) 将下标为 idx 的位上的值更新为 0 。如果值已经是 0 ,则不会发生任何改变。
|
||||
- void flip() 翻转 Bitset 中每一位上的值。换句话说,所有值为 0 的位将会变成 1 ,反之亦然。
|
||||
- boolean all() 检查 Bitset 中 每一位 的值是否都是 1 。如果满足此条件,返回 true ;否则,返回 false 。
|
||||
- boolean one() 检查 Bitset 中 是否 至少一位 的值是 1 。如果满足此条件,返回 true ;否则,返回 false 。
|
||||
- int count() 返回 Bitset 中值为 1 的位的 总数 。
|
||||
- String toString() 返回 Bitset 的当前组成情况。注意,在结果字符串中,第 i 个下标处的字符应该与 Bitset 中的第 i 位一致。
|
||||
|
||||
提示:
|
||||
|
||||
- 1 <= size <= 10^5
|
||||
- 0 <= idx <= size - 1
|
||||
- 至多调用 fix、unfix、flip、all、one、count 和 toString 方法 总共 10^5 次
|
||||
- 至少调用 all、one、count 或 toString 方法一次
|
||||
- 至多调用 toString 方法 5 次
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 题目中给出了 size 大小,10^5 位二进制。所以不能用 int64 数据类型。
|
||||
- 用数组模拟二进制位的一系列操作。flip 操作并不需要每次去翻转,偶数次翻转等于没有翻转,奇数次翻转记下标记,同时更新 1 的个数。这次懒操作在调用 fix 和 unfix 时,更新到原来数组中。
|
||||
- fix 和 unfix 根据懒数组中的标记对应更新二进制位。同时更新 1 的个数。
|
||||
- all,one,count 都是判断 1 的个数。toString 输出即可。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
type Bitset struct {
|
||||
set []byte
|
||||
flipped []byte
|
||||
oneCount int
|
||||
size int
|
||||
}
|
||||
|
||||
func Constructor(size int) Bitset {
|
||||
set := make([]byte, size)
|
||||
flipped := make([]byte, size)
|
||||
for i := 0; i < size; i++ {
|
||||
set[i] = byte('0')
|
||||
flipped[i] = byte('1')
|
||||
}
|
||||
return Bitset{
|
||||
set: set,
|
||||
flipped: flipped,
|
||||
oneCount: 0,
|
||||
size: size,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Bitset) Fix(idx int) {
|
||||
if this.set[idx] == byte('0') {
|
||||
this.set[idx] = byte('1')
|
||||
this.flipped[idx] = byte('0')
|
||||
this.oneCount++
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Bitset) Unfix(idx int) {
|
||||
if this.set[idx] == byte('1') {
|
||||
this.set[idx] = byte('0')
|
||||
this.flipped[idx] = byte('1')
|
||||
this.oneCount--
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Bitset) Flip() {
|
||||
this.set, this.flipped = this.flipped, this.set
|
||||
this.oneCount = this.size - this.oneCount
|
||||
}
|
||||
|
||||
func (this *Bitset) All() bool {
|
||||
return this.oneCount == this.size
|
||||
}
|
||||
|
||||
func (this *Bitset) One() bool {
|
||||
return this.oneCount != 0
|
||||
}
|
||||
|
||||
func (this *Bitset) Count() int {
|
||||
return this.oneCount
|
||||
}
|
||||
|
||||
func (this *Bitset) ToString() string {
|
||||
return string(this.set)
|
||||
}
|
||||
|
||||
/**
|
||||
* Your Bitset object will be instantiated and called as such:
|
||||
* obj := Constructor(size);
|
||||
* obj.Fix(idx);
|
||||
* obj.Unfix(idx);
|
||||
* obj.Flip();
|
||||
* param_4 := obj.All();
|
||||
* param_5 := obj.One();
|
||||
* param_6 := obj.Count();
|
||||
* param_7 := obj.ToString();
|
||||
*/
|
||||
```
|
@ -0,0 +1,48 @@
|
||||
package leetcode
|
||||
|
||||
import "runtime/debug"
|
||||
|
||||
// 解法一 DP
|
||||
func minimumTime(s string) int {
|
||||
suffixSum, prefixSum, res := make([]int, len(s)+1), make([]int, len(s)+1), 0
|
||||
for i := len(s) - 1; i >= 0; i-- {
|
||||
if s[i] == '0' {
|
||||
suffixSum[i] = suffixSum[i+1]
|
||||
} else {
|
||||
suffixSum[i] = min(suffixSum[i+1]+2, len(s)-i)
|
||||
}
|
||||
}
|
||||
res = suffixSum[0]
|
||||
if s[0] == '1' {
|
||||
prefixSum[0] = 1
|
||||
}
|
||||
for i := 1; i < len(s); i++ {
|
||||
if s[i] == '0' {
|
||||
prefixSum[i] = prefixSum[i-1]
|
||||
} else {
|
||||
prefixSum[i] = min(prefixSum[i-1]+2, i+1)
|
||||
}
|
||||
res = min(res, prefixSum[i]+suffixSum[i+1])
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func init() { debug.SetGCPercent(-1) }
|
||||
|
||||
// 解法二 小幅优化时间和空间复杂度
|
||||
func minimumTime1(s string) int {
|
||||
res, count := len(s), 0
|
||||
for i := 0; i < len(s); i++ {
|
||||
count = min(count+int(s[i]-'0')*2, i+1)
|
||||
res = min(res, count+len(s)-i-1)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
} else {
|
||||
return b
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question2167 struct {
|
||||
para2167
|
||||
ans2167
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para2167 struct {
|
||||
s string
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans2167 struct {
|
||||
one int
|
||||
}
|
||||
|
||||
func Test_Problem2167(t *testing.T) {
|
||||
|
||||
qs := []question2167{
|
||||
|
||||
{
|
||||
para2167{"1100101"},
|
||||
ans2167{5},
|
||||
},
|
||||
|
||||
{
|
||||
para2167{"0010"},
|
||||
ans2167{2},
|
||||
},
|
||||
|
||||
{
|
||||
para2167{"1100111101"},
|
||||
ans2167{8},
|
||||
},
|
||||
|
||||
{
|
||||
para2167{"1001010101"},
|
||||
ans2167{8},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 2167------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans2167, q.para2167
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, minimumTime(p.s))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
@ -0,0 +1,145 @@
|
||||
# [2167. Minimum Time to Remove All Cars Containing Illegal Goods](https://leetcode.com/problems/minimum-time-to-remove-all-cars-containing-illegal-goods/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
You are given a **0-indexed** binary string `s` which represents a sequence of train cars. `s[i] = '0'` denotes that the `ith` car does **not** contain illegal goods and `s[i] = '1'` denotes that the `ith` car does contain illegal goods.
|
||||
|
||||
As the train conductor, you would like to get rid of all the cars containing illegal goods. You can do any of the following three operations **any** number of times:
|
||||
|
||||
1. Remove a train car from the **left** end (i.e., remove `s[0]`) which takes 1 unit of time.
|
||||
2. Remove a train car from the **right** end (i.e., remove `s[s.length - 1]`) which takes 1 unit of time.
|
||||
3. Remove a train car from **anywhere** in the sequence which takes 2 units of time.
|
||||
|
||||
Return *the **minimum** time to remove all the cars containing illegal goods*.
|
||||
|
||||
Note that an empty sequence of cars is considered to have no cars containing illegal goods.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: s = "1100101"
|
||||
Output: 5
|
||||
Explanation:
|
||||
One way to remove all the cars containing illegal goods from the sequence is to
|
||||
- remove a car from the left end 2 times. Time taken is 2 * 1 = 2.
|
||||
- remove a car from the right end. Time taken is 1.
|
||||
- remove the car containing illegal goods found in the middle. Time taken is 2.
|
||||
This obtains a total time of 2 + 1 + 2 = 5.
|
||||
|
||||
An alternative way is to
|
||||
- remove a car from the left end 2 times. Time taken is 2 * 1 = 2.
|
||||
- remove a car from the right end 3 times. Time taken is 3 * 1 = 3.
|
||||
This also obtains a total time of 2 + 3 = 5.
|
||||
|
||||
5 is the minimum time taken to remove all the cars containing illegal goods.
|
||||
There are no other ways to remove them with less time.
|
||||
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: s = "0010"
|
||||
Output: 2
|
||||
Explanation:
|
||||
One way to remove all the cars containing illegal goods from the sequence is to
|
||||
- remove a car from the left end 3 times. Time taken is 3 * 1 = 3.
|
||||
This obtains a total time of 3.
|
||||
|
||||
Another way to remove all the cars containing illegal goods from the sequence is to
|
||||
- remove the car containing illegal goods found in the middle. Time taken is 2.
|
||||
This obtains a total time of 2.
|
||||
|
||||
Another way to remove all the cars containing illegal goods from the sequence is to
|
||||
- remove a car from the right end 2 times. Time taken is 2 * 1 = 2.
|
||||
This obtains a total time of 2.
|
||||
|
||||
2 is the minimum time taken to remove all the cars containing illegal goods.
|
||||
There are no other ways to remove them with less time.
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `1 <= s.length <= 2 * 10^5`
|
||||
- `s[i]` is either `'0'` or `'1'`.
|
||||
|
||||
## 题目大意
|
||||
|
||||
给你一个下标从 0 开始的二进制字符串 s ,表示一个列车车厢序列。s[i] = '0' 表示第 i 节车厢 不 含违禁货物,而 s[i] = '1' 表示第 i 节车厢含违禁货物。
|
||||
|
||||
作为列车长,你需要清理掉所有载有违禁货物的车厢。你可以不限次数执行下述三种操作中的任意一个:
|
||||
|
||||
1. 从列车 左 端移除一节车厢(即移除 s[0]),用去 1 单位时间。
|
||||
2. 从列车 右 端移除一节车厢(即移除 s[s.length - 1]),用去 1 单位时间。
|
||||
3. 从列车车厢序列的 任意位置 移除一节车厢,用去 2 单位时间。
|
||||
|
||||
返回移除所有载有违禁货物车厢所需要的 最少 单位时间数。注意,空的列车车厢序列视为没有车厢含违禁货物。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 这道题求最少单位时间数,最少时间数一定是尽量少使用 2 个单位时间的操作,多用 1 个时间的操作。从列车两头移除车厢,只需要移除和旁边车厢的金属连接处即可。由于列车位于两边,所以与其他车厢的金属连接处只有 1 个,故只需要 1 个单位时间;当车厢在中间,该车厢与两边的车厢有 2 个金属连接处,移除它需要断开与两边车厢的连接。所以需要 2 个单位时间。
|
||||
- 断开中间一节车厢以后,列车会被断成 2 部分。2 部分列车分别有 2 个头 2 个尾。举例:`1100111101`,如果把它从第 5 节开始断开,剩下的列车为 `11001 (1)` 和 `1101`。剩下的 1 都位于 2 边,移除他们都只需要 1 个单位时间。那么移除所有违禁品最少时间是 2 * 1 + 1 * 6 = 8。
|
||||
- 左半部分,定义 prefixSum[i] 表示移除前 i 节车厢所花费的最少时间。状态转移方程为:
|
||||
|
||||
$prefixSum[i] =\left\{\begin{matrix}prefixSum[i-1],s[i]=0\\ min(prefixSum[i-1]+2, i+1), s[i]=1\end{matrix}\right.$
|
||||
|
||||
- 同理,右半部分定义 suffixSum[i] 表示移除后 i 节车厢所花费的最少时间。状态转移方程为:
|
||||
|
||||
$suffixSum[i] =\left\{\begin{matrix} suffixSum[i+1],s[i]=0\\ min(suffixSum[i+1]+2, n-i), s[i]=1\end{matrix}\right.$
|
||||
|
||||
- 最后一层循环枚举 prefixSum[i] + suffixSum[i+1] 的最小值即为答案。
|
||||
- 这一题在解法一的基础上还可以再简化。当 s[i] = 1 时,prefixSum 和 suffixSum 是两种计算方法。我们可以假设中间断开的部分在 prefixSum 中。于是可以合并上面两个状态转移方程。简化以后的代码见解法二。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
import "runtime/debug"
|
||||
|
||||
// 解法一 DP
|
||||
func minimumTime(s string) int {
|
||||
suffixSum, prefixSum, res := make([]int, len(s)+1), make([]int, len(s)+1), 0
|
||||
for i := len(s) - 1; i >= 0; i-- {
|
||||
if s[i] == '0' {
|
||||
suffixSum[i] = suffixSum[i+1]
|
||||
} else {
|
||||
suffixSum[i] = min(suffixSum[i+1]+2, len(s)-i)
|
||||
}
|
||||
}
|
||||
res = suffixSum[0]
|
||||
if s[0] == '1' {
|
||||
prefixSum[0] = 1
|
||||
}
|
||||
for i := 1; i < len(s); i++ {
|
||||
if s[i] == '0' {
|
||||
prefixSum[i] = prefixSum[i-1]
|
||||
} else {
|
||||
prefixSum[i] = min(prefixSum[i-1]+2, i+1)
|
||||
}
|
||||
res = min(res, prefixSum[i]+suffixSum[i+1])
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func init() { debug.SetGCPercent(-1) }
|
||||
|
||||
// 解法二 小幅优化时间和空间复杂度
|
||||
func minimumTime1(s string) int {
|
||||
res, count := len(s), 0
|
||||
for i := 0; i < len(s); i++ {
|
||||
count = min(count+int(s[i]-'0')*2, i+1)
|
||||
res = min(res, count+len(s)-i-1)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
} else {
|
||||
return b
|
||||
}
|
||||
}
|
||||
```
|
@ -0,0 +1,14 @@
|
||||
package leetcode
|
||||
|
||||
func countOperations(num1 int, num2 int) int {
|
||||
res := 0
|
||||
for num1 != 0 && num2 != 0 {
|
||||
if num1 >= num2 {
|
||||
num1 -= num2
|
||||
} else {
|
||||
num2 -= num1
|
||||
}
|
||||
res++
|
||||
}
|
||||
return res
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question2169 struct {
|
||||
para2169
|
||||
ans2169
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para2169 struct {
|
||||
num1 int
|
||||
num2 int
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans2169 struct {
|
||||
one int
|
||||
}
|
||||
|
||||
func Test_Problem2169(t *testing.T) {
|
||||
|
||||
qs := []question2169{
|
||||
|
||||
{
|
||||
para2169{2, 3},
|
||||
ans2169{3},
|
||||
},
|
||||
|
||||
{
|
||||
para2169{10, 10},
|
||||
ans2169{1},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 2169------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans2169, q.para2169
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, countOperations(p.num1, p.num2))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
73
leetcode/2169.Count-Operations-to-Obtain-Zero/README.md
Normal file
73
leetcode/2169.Count-Operations-to-Obtain-Zero/README.md
Normal file
@ -0,0 +1,73 @@
|
||||
# [2169. Count Operations to Obtain Zero](https://leetcode.com/problems/count-operations-to-obtain-zero/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
You are given two **non-negative** integers `num1` and `num2`.
|
||||
|
||||
In one **operation**, if `num1 >= num2`, you must subtract `num2` from `num1`, otherwise subtract `num1` from `num2`.
|
||||
|
||||
- For example, if `num1 = 5` and `num2 = 4`, subtract `num2` from `num1`, thus obtaining `num1 = 1` and `num2 = 4`. However, if `num1 = 4` and `num2 = 5`, after one operation, `num1 = 4` and `num2 = 1`.
|
||||
|
||||
Return *the **number of operations** required to make either* `num1 = 0` *or* `num2 = 0`.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: num1 = 2, num2 = 3
|
||||
Output: 3
|
||||
Explanation:
|
||||
- Operation 1: num1 = 2, num2 = 3. Since num1 < num2, we subtract num1 from num2 and get num1 = 2, num2 = 3 - 2 = 1.
|
||||
- Operation 2: num1 = 2, num2 = 1. Since num1 > num2, we subtract num2 from num1.
|
||||
- Operation 3: num1 = 1, num2 = 1. Since num1 == num2, we subtract num2 from num1.
|
||||
Now num1 = 0 and num2 = 1. Since num1 == 0, we do not need to perform any further operations.
|
||||
So the total number of operations required is 3.
|
||||
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: num1 = 10, num2 = 10
|
||||
Output: 1
|
||||
Explanation:
|
||||
- Operation 1: num1 = 10, num2 = 10. Since num1 == num2, we subtract num2 from num1 and get num1 = 10 - 10 = 0.
|
||||
Now num1 = 0 and num2 = 10. Since num1 == 0, we are done.
|
||||
So the total number of operations required is 1.
|
||||
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `0 <= num1, num2 <= 10^5`
|
||||
|
||||
## 题目大意
|
||||
|
||||
给你两个 非负 整数 num1 和 num2 。每一步 操作 中,如果 num1 >= num2 ,你必须用 num1 减 num2 ;否则,你必须用 num2 减 num1 。
|
||||
|
||||
- 例如,num1 = 5 且 num2 = 4 ,应该用 num1 减 num2 ,因此,得到 num1 = 1 和 num2 = 4 。然而,如果 num1 = 4且 num2 = 5 ,一步操作后,得到 num1 = 4 和 num2 = 1 。
|
||||
|
||||
返回使 num1 = 0 或 num2 = 0 的 操作数 。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 简单题,按照题意模拟,每次两个数字相减,便累加操作次数。当某个数字变为 0 时,输出操作次数。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
func countOperations(num1 int, num2 int) int {
|
||||
res := 0
|
||||
for num1 != 0 && num2 != 0 {
|
||||
if num1 >= num2 {
|
||||
num1 -= num2
|
||||
} else {
|
||||
num2 -= num1
|
||||
}
|
||||
res++
|
||||
}
|
||||
return res
|
||||
}
|
||||
```
|
@ -0,0 +1,60 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
type node struct {
|
||||
value int
|
||||
count int
|
||||
}
|
||||
|
||||
func minimumOperations(nums []int) int {
|
||||
if len(nums) == 1 {
|
||||
return 0
|
||||
}
|
||||
res, odd, even, oddMap, evenMap := 0, []node{}, []node{}, map[int]int{}, map[int]int{}
|
||||
|
||||
for i := 0; i < len(nums); i += 2 {
|
||||
evenMap[nums[i]]++
|
||||
}
|
||||
for k, v := range evenMap {
|
||||
even = append(even, node{value: k, count: v})
|
||||
}
|
||||
sort.Slice(even, func(i, j int) bool {
|
||||
return even[i].count > even[j].count
|
||||
})
|
||||
|
||||
for i := 1; i < len(nums); i += 2 {
|
||||
oddMap[nums[i]]++
|
||||
}
|
||||
for k, v := range oddMap {
|
||||
odd = append(odd, node{value: k, count: v})
|
||||
}
|
||||
sort.Slice(odd, func(i, j int) bool {
|
||||
return odd[i].count > odd[j].count
|
||||
})
|
||||
|
||||
if even[0].value == odd[0].value {
|
||||
if len(even) == 1 && len(odd) != 1 {
|
||||
res = len(nums) - even[0].count - odd[1].count
|
||||
} else if len(odd) == 1 && len(even) != 1 {
|
||||
res = len(nums) - odd[0].count - even[1].count
|
||||
} else if len(odd) == 1 && len(even) == 1 {
|
||||
res = len(nums) / 2
|
||||
} else {
|
||||
// both != 1
|
||||
res = min(len(nums)-odd[0].count-even[1].count, len(nums)-odd[1].count-even[0].count)
|
||||
}
|
||||
} else {
|
||||
res = len(nums) - even[0].count - odd[0].count
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a > b {
|
||||
return b
|
||||
}
|
||||
return a
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question2170 struct {
|
||||
para2170
|
||||
ans2170
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para2170 struct {
|
||||
nums []int
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans2170 struct {
|
||||
one int
|
||||
}
|
||||
|
||||
func Test_Problem1(t *testing.T) {
|
||||
|
||||
qs := []question2170{
|
||||
|
||||
{
|
||||
para2170{[]int{1}},
|
||||
ans2170{0},
|
||||
},
|
||||
|
||||
{
|
||||
para2170{[]int{3, 1, 3, 2, 4, 3}},
|
||||
ans2170{3},
|
||||
},
|
||||
|
||||
{
|
||||
para2170{[]int{1, 2, 2, 2, 2}},
|
||||
ans2170{2},
|
||||
},
|
||||
|
||||
{
|
||||
para2170{[]int{69, 91, 47, 74, 75, 94, 22, 100, 43, 50, 82, 47, 40, 51, 90, 27, 98, 85, 47, 14, 55, 82, 52, 9, 65, 90, 86, 45, 52, 52, 95, 40, 85, 3, 46, 77, 16, 59, 32, 22, 41, 87, 89, 78, 59, 78, 34, 26, 71, 9, 82, 68, 80, 74, 100, 6, 10, 53, 84, 80, 7, 87, 3, 82, 26, 26, 14, 37, 26, 58, 96, 73, 41, 2, 79, 43, 56, 74, 30, 71, 6, 100, 72, 93, 83, 40, 28, 79, 24}},
|
||||
ans2170{84},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 2170------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans2170, q.para2170
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, minimumOperations(p.nums))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
# [2170. Minimum Operations to Make the Array Alternating](https://leetcode.com/problems/minimum-operations-to-make-the-array-alternating/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
You are given a **0-indexed** array `nums` consisting of `n` positive integers.
|
||||
|
||||
The array `nums` is called **alternating** if:
|
||||
|
||||
- `nums[i - 2] == nums[i]`, where `2 <= i <= n - 1`.
|
||||
- `nums[i - 1] != nums[i]`, where `1 <= i <= n - 1`.
|
||||
|
||||
In one **operation**, you can choose an index `i` and **change** `nums[i]` into **any** positive integer.
|
||||
|
||||
Return *the **minimum number of operations** required to make the array alternating*.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: nums = [3,1,3,2,4,3]
|
||||
Output: 3
|
||||
Explanation:
|
||||
One way to make the array alternating is by converting it to [3,1,3,1,3,1].
|
||||
The number of operations required in this case is 3.
|
||||
It can be proven that it is not possible to make the array alternating in less than 3 operations.
|
||||
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: nums = [1,2,2,2,2]
|
||||
Output: 2
|
||||
Explanation:
|
||||
One way to make the array alternating is by converting it to [1,2,1,2,1].
|
||||
The number of operations required in this case is 2.
|
||||
Note that the array cannot be converted to [2,2,2,2,2] because in this case nums[0] == nums[1] which violates the conditions of an alternating array.
|
||||
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `1 <= nums.length <= 10^5`
|
||||
- `1 <= nums[i] <= 10^5`
|
||||
|
||||
## 题目大意
|
||||
|
||||
给你一个下标从 0 开始的数组 nums ,该数组由 n 个正整数组成。
|
||||
|
||||
如果满足下述条件,则数组 nums 是一个 交替数组 :
|
||||
|
||||
- nums[i - 2] == nums[i] ,其中 2 <= i <= n - 1 。
|
||||
- nums[i - 1] != nums[i] ,其中 1 <= i <= n - 1 。
|
||||
|
||||
在一步 操作 中,你可以选择下标 i 并将 nums[i] 更改 为 任一 正整数。返回使数组变成交替数组的 最少操作数 。
|
||||
|
||||
**提示:**
|
||||
|
||||
- `1 <= nums.length <= 10^5`
|
||||
- `1 <= nums[i] <= 10^5`
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 题目要求最少操作数,即留下出现频次最多的数字,剩下的数字都替换成这个数字。先将每个数字出现的频次统计出来,然后按照频次从大到小排序。优先选择出现频次高的数字。
|
||||
- 有几种“特殊”情况需要处理:当奇数下标的数字频次最大的数字和偶数下标的数字频次最大的数字相同(数字相同,频次不同),这时应选取频次大的数字留下;当数字相同,频次也相同,这时要看奇数下标和偶数下标的数字分别有几个。 如果其中一个只有一种数字,那么另外一组数字则需都变成该组频次第二大的数字,例如奇数下标的数字全是 1,频次是 3,偶数下标的数字是 1,最大频次是 2。第二频次的数字是 9,频次是 1 。那么这种情况下,选择奇数下标的数字 1,和偶数下标数字 9 。将偶数下标不是 9 的数字改变成 9 ;更近一步,如果奇数下标和偶数下标都只有一个数字,频次相同,那么只能改变奇数下标或者偶数下标的所有数字。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
type node struct {
|
||||
value int
|
||||
count int
|
||||
}
|
||||
|
||||
func minimumOperations(nums []int) int {
|
||||
if len(nums) == 1 {
|
||||
return 0
|
||||
}
|
||||
res, odd, even, oddMap, evenMap := 0, []node{}, []node{}, map[int]int{}, map[int]int{}
|
||||
|
||||
for i := 0; i < len(nums); i += 2 {
|
||||
evenMap[nums[i]]++
|
||||
}
|
||||
for k, v := range evenMap {
|
||||
even = append(even, node{value: k, count: v})
|
||||
}
|
||||
sort.Slice(even, func(i, j int) bool {
|
||||
return even[i].count > even[j].count
|
||||
})
|
||||
|
||||
for i := 1; i < len(nums); i += 2 {
|
||||
oddMap[nums[i]]++
|
||||
}
|
||||
for k, v := range oddMap {
|
||||
odd = append(odd, node{value: k, count: v})
|
||||
}
|
||||
sort.Slice(odd, func(i, j int) bool {
|
||||
return odd[i].count > odd[j].count
|
||||
})
|
||||
|
||||
if even[0].value == odd[0].value {
|
||||
if len(even) == 1 && len(odd) != 1 {
|
||||
res = len(nums) - even[0].count - odd[1].count
|
||||
} else if len(odd) == 1 && len(even) != 1 {
|
||||
res = len(nums) - odd[0].count - even[1].count
|
||||
} else if len(odd) == 1 && len(even) == 1 {
|
||||
res = len(nums) / 2
|
||||
} else {
|
||||
// both != 1
|
||||
res = min(len(nums)-odd[0].count-even[1].count, len(nums)-odd[1].count-even[0].count)
|
||||
}
|
||||
} else {
|
||||
res = len(nums) - even[0].count - odd[0].count
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a > b {
|
||||
return b
|
||||
}
|
||||
return a
|
||||
}
|
||||
```
|
@ -0,0 +1,20 @@
|
||||
package leetcode
|
||||
|
||||
import "sort"
|
||||
|
||||
func minimumRemoval(beans []int) int64 {
|
||||
sort.Ints(beans)
|
||||
sum, mx := 0, 0
|
||||
for i, v := range beans {
|
||||
sum += v
|
||||
mx = max(mx, (len(beans)-i)*v)
|
||||
}
|
||||
return int64(sum - mx)
|
||||
}
|
||||
|
||||
func max(a, b int) int {
|
||||
if b > a {
|
||||
return b
|
||||
}
|
||||
return a
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question2170 struct {
|
||||
para2170
|
||||
ans2170
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para2170 struct {
|
||||
beans []int
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans2170 struct {
|
||||
one int
|
||||
}
|
||||
|
||||
func Test_Problem1(t *testing.T) {
|
||||
|
||||
qs := []question2170{
|
||||
|
||||
{
|
||||
para2170{[]int{4, 1, 6, 5}},
|
||||
ans2170{4},
|
||||
},
|
||||
|
||||
{
|
||||
para2170{[]int{2, 10, 3, 2}},
|
||||
ans2170{7},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 2170------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans2170, q.para2170
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, minimumRemoval(p.beans))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
# [2171. Removing Minimum Number of Magic Beans](https://leetcode.com/problems/removing-minimum-number-of-magic-beans/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
You are given an array of **positive** integers `beans`, where each integer represents the number of magic beans found in a particular magic bag.
|
||||
|
||||
**Remove** any number of beans (**possibly none**) from each bag such that the number of beans in each remaining **non-empty** bag (still containing **at least one** bean) is **equal**. Once a bean has been removed from a bag, you are **not** allowed to return it to any of the bags.
|
||||
|
||||
Return *the **minimum** number of magic beans that you have to remove*.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: beans = [4,1,6,5]
|
||||
Output: 4
|
||||
Explanation:
|
||||
- We remove 1 bean from the bag with only 1 bean.
|
||||
This results in the remaining bags: [4,0,6,5]
|
||||
- Then we remove 2 beans from the bag with 6 beans.
|
||||
This results in the remaining bags: [4,0,4,5]
|
||||
- Then we remove 1 bean from the bag with 5 beans.
|
||||
This results in the remaining bags: [4,0,4,4]
|
||||
We removed a total of 1 + 2 + 1 = 4 beans to make the remaining non-empty bags have an equal number of beans.
|
||||
There are no other solutions that remove 4 beans or fewer.
|
||||
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: beans = [2,10,3,2]
|
||||
Output: 7
|
||||
Explanation:
|
||||
- We remove 2 beans from one of the bags with 2 beans.
|
||||
This results in the remaining bags: [0,10,3,2]
|
||||
- Then we remove 2 beans from the other bag with 2 beans.
|
||||
This results in the remaining bags: [0,10,3,0]
|
||||
- Then we remove 3 beans from the bag with 3 beans.
|
||||
This results in the remaining bags: [0,10,0,0]
|
||||
We removed a total of 2 + 2 + 3 = 7 beans to make the remaining non-empty bags have an equal number of beans.
|
||||
There are no other solutions that removes 7 beans or fewer.
|
||||
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `1 <= beans.length <= 10^5`
|
||||
- `1 <= beans[i] <= 10^5`
|
||||
|
||||
## 题目大意
|
||||
|
||||
给你一个 正 整数数组 beans ,其中每个整数表示一个袋子里装的魔法豆的数目。
|
||||
|
||||
请你从每个袋子中 拿出 一些豆子(也可以 不拿出),使得剩下的 非空 袋子中(即 至少 还有 一颗 魔法豆的袋子)魔法豆的数目 相等 。一旦魔法豆从袋子中取出,你不能将它放到任何其他的袋子中。请你返回你需要拿出魔法豆的 最少数目。
|
||||
|
||||
**提示:**
|
||||
|
||||
- `1 <= beans.length <= 10^5`
|
||||
- `1 <= beans[i] <= 10^5`
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 这一题没有特别巧妙的方法。最初思路来源于暴力解法。从第一个袋子开始,依次以每个袋子中的豆子为基准,改变其他袋子里面的豆子数,使得其他袋子里面的豆子都和基准袋子中豆子一样多。
|
||||
- 如果从下标为 0 扫到下标 n-1 ,这中间会有大量重复计算。有些计算区间和的操作,反复计算了很多遍,导致算法不高效。由于移除豆子数量多少和基准袋豆子数量强相关,所以先排序。如果袋子内豆子数目小于基准袋的豆子,`0 ≤ j < i`,那么这些袋子内的豆子数量会归零。需要移除 `beans[0] + beans[1] + ... + beans[i-1]` 个豆子;如果袋子内豆子数目大于等于基准袋的豆子,`j ≥ i` ,那么这些袋子内的豆子需要调整为 `beans[i]` 个。需要移除 `(beans[i] - beans[i]) + (beans[i+1] - beans[i]) + (beans[i+2] - beans[i]) + ... + (beans[n-1] - beans[i]) = beans[i]+ ... + beans[n-1] - (n-i) * beans[i]` 个豆子。将这 2 种情况综合起来,那么总共需要移除 `sum(beans) - (N - i) * beans[i]` 个豆子。综上,先排序,然后从小到大扫一遍数组,动态维护最少移除豆子的个数即可。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
import "sort"
|
||||
|
||||
func minimumRemoval(beans []int) int64 {
|
||||
sort.Ints(beans)
|
||||
sum, mx := 0, 0
|
||||
for i, v := range beans {
|
||||
sum += v
|
||||
mx = max(mx, (len(beans)-i)*v)
|
||||
}
|
||||
return int64(sum - mx)
|
||||
}
|
||||
|
||||
func max(a, b int) int {
|
||||
if b > a {
|
||||
return b
|
||||
}
|
||||
return a
|
||||
}
|
||||
```
|
@ -0,0 +1,21 @@
|
||||
package leetcode
|
||||
|
||||
func countEven(num int) int {
|
||||
count := 0
|
||||
for i := 1; i <= num; i++ {
|
||||
if addSum(i)%2 == 0 {
|
||||
count++
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func addSum(num int) int {
|
||||
sum := 0
|
||||
tmp := num
|
||||
for tmp != 0 {
|
||||
sum += tmp % 10
|
||||
tmp = tmp / 10
|
||||
}
|
||||
return sum
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question2180 struct {
|
||||
para2180
|
||||
ans2180
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para2180 struct {
|
||||
target int
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans2180 struct {
|
||||
one int
|
||||
}
|
||||
|
||||
func Test_Problem1(t *testing.T) {
|
||||
|
||||
qs := []question2180{
|
||||
{
|
||||
para2180{4},
|
||||
ans2180{2},
|
||||
},
|
||||
|
||||
{
|
||||
para2180{30},
|
||||
ans2180{14},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 2180------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans2180, q.para2180
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, countEven(p.target))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
69
leetcode/2180.Count-Integers-With-Even-Digit-Sum/README.md
Normal file
69
leetcode/2180.Count-Integers-With-Even-Digit-Sum/README.md
Normal file
@ -0,0 +1,69 @@
|
||||
# [2180. Count Integers With Even Digit Sum](https://leetcode.com/problems/count-integers-with-even-digit-sum/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
Given a positive integer `num`, return *the number of positive integers **less than or equal to*** `num` *whose digit sums are **even***.
|
||||
|
||||
The **digit sum** of a positive integer is the sum of all its digits.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: num = 4
|
||||
Output: 2
|
||||
Explanation:
|
||||
The only integers less than or equal to 4 whose digit sums are even are 2 and 4.
|
||||
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: num = 30
|
||||
Output: 14
|
||||
Explanation:
|
||||
The 14 integers less than or equal to 30 whose digit sums are even are
|
||||
2, 4, 6, 8, 11, 13, 15, 17, 19, 20, 22, 24, 26, and 28.
|
||||
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `1 <= num <= 1000`
|
||||
|
||||
## 题目大意
|
||||
|
||||
给你一个正整数 num ,请你统计并返回 小于或等于 num 且各位数字之和为 偶数 的正整数的数目。
|
||||
|
||||
正整数的 各位数字之和 是其所有位上的对应数字相加的结果。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 简单题。依照题意,计算每个数的各位数字之和,如何和为偶数,则统计结果加一。最后输出统计结果即可。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
func countEven(num int) int {
|
||||
count := 0
|
||||
for i := 1; i <= num; i++ {
|
||||
if addSum(i)%2 == 0 {
|
||||
count++
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func addSum(num int) int {
|
||||
sum := 0
|
||||
tmp := num
|
||||
for tmp != 0 {
|
||||
sum += tmp % 10
|
||||
tmp = tmp / 10
|
||||
}
|
||||
return sum
|
||||
}
|
||||
```
|
@ -0,0 +1,36 @@
|
||||
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 mergeNodes(head *ListNode) *ListNode {
|
||||
res := &ListNode{}
|
||||
h := res
|
||||
if head.Next == nil {
|
||||
return &structures.ListNode{}
|
||||
}
|
||||
cur := head
|
||||
sum := 0
|
||||
for cur.Next != nil {
|
||||
if cur.Next.Val != 0 {
|
||||
sum += cur.Next.Val
|
||||
} else {
|
||||
h.Next = &ListNode{Val: sum, Next: nil}
|
||||
h = h.Next
|
||||
sum = 0
|
||||
}
|
||||
cur = cur.Next
|
||||
}
|
||||
return res.Next
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/halfrost/LeetCode-Go/structures"
|
||||
)
|
||||
|
||||
type question2181 struct {
|
||||
para2181
|
||||
ans2181
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para2181 struct {
|
||||
one []int
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans2181 struct {
|
||||
one []int
|
||||
}
|
||||
|
||||
func Test_Problem2181(t *testing.T) {
|
||||
|
||||
qs := []question2181{
|
||||
|
||||
{
|
||||
para2181{[]int{0, 3, 1, 0, 4, 5, 2, 0}},
|
||||
ans2181{[]int{4, 11}},
|
||||
},
|
||||
|
||||
{
|
||||
para2181{[]int{0, 1, 0, 3, 0, 2, 2, 0}},
|
||||
ans2181{[]int{1, 3, 4}},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 2181------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans2181, q.para2181
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, structures.List2Ints(mergeNodes(structures.Ints2List(p.one))))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
||||
|
||||
func removeElements(head *ListNode, val int) *ListNode {
|
||||
if head == nil {
|
||||
return head
|
||||
}
|
||||
newHead := &ListNode{Val: 0, Next: head}
|
||||
pre := newHead
|
||||
cur := head
|
||||
for cur != nil {
|
||||
if cur.Val == val {
|
||||
pre.Next = cur.Next
|
||||
} else {
|
||||
pre = cur
|
||||
}
|
||||
cur = cur.Next
|
||||
}
|
||||
return newHead.Next
|
||||
}
|
96
leetcode/2181.Merge-Nodes-in-Between-Zeros/README.md
Normal file
96
leetcode/2181.Merge-Nodes-in-Between-Zeros/README.md
Normal file
@ -0,0 +1,96 @@
|
||||
# [2181. Merge Nodes in Between Zeros](https://leetcode.com/problems/merge-nodes-in-between-zeros/)
|
||||
|
||||
## 题目
|
||||
|
||||
You are given the `head` of a linked list, which contains a series of integers **separated** by `0`'s. The **beginning** and **end** of the linked list will have `Node.val == 0`.
|
||||
|
||||
For **every** two consecutive `0`'s, **merge** all the nodes lying in between them into a single node whose value is the **sum** of all the merged nodes. The modified list should not contain any `0`'s.
|
||||
|
||||
Return *the* `head` *of the modified linked list*.
|
||||
|
||||
**Example 1:**
|
||||
|
||||

|
||||
|
||||
```
|
||||
Input: head = [0,3,1,0,4,5,2,0]
|
||||
Output: [4,11]
|
||||
Explanation:
|
||||
The above figure represents the given linked list. The modified list contains
|
||||
- The sum of the nodes marked in green: 3 + 1 = 4.
|
||||
- The sum of the nodes marked in red: 4 + 5 + 2 = 11.
|
||||
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||

|
||||
|
||||
```
|
||||
Input: head = [0,1,0,3,0,2,2,0]
|
||||
Output: [1,3,4]
|
||||
Explanation:
|
||||
The above figure represents the given linked list. The modified list contains
|
||||
- The sum of the nodes marked in green: 1 = 1.
|
||||
- The sum of the nodes marked in red: 3 = 3.
|
||||
- The sum of the nodes marked in yellow: 2 + 2 = 4.
|
||||
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- The number of nodes in the list is in the range `[3, 2 * 10^5]`.
|
||||
- `0 <= Node.val <= 1000`
|
||||
- There are **no** two consecutive nodes with `Node.val == 0`.
|
||||
- The **beginning** and **end** of the linked list have `Node.val == 0`.
|
||||
|
||||
## 题目大意
|
||||
|
||||
给你一个链表的头节点 head ,该链表包含由 0 分隔开的一连串整数。链表的 开端 和 末尾 的节点都满足 Node.val == 0 。对于每两个相邻的 0 ,请你将它们之间的所有节点合并成一个节点,其值是所有已合并节点的值之和。然后将所有 0 移除,修改后的链表不应该含有任何 0 。
|
||||
|
||||
返回修改后链表的头节点 head 。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 简单题。合并链表中两个值为 0 的节点。从头开始遍历链表,遇到节点值不为 0 的节点便累加;遇到节点值为 0 的节点,将累加值转换成结果链表要输出的节点值,然后继续遍历。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
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 mergeNodes(head *ListNode) *ListNode {
|
||||
res := &ListNode{}
|
||||
h := res
|
||||
if head.Next == nil {
|
||||
return &structures.ListNode{}
|
||||
}
|
||||
cur := head
|
||||
sum := 0
|
||||
for cur.Next != nil {
|
||||
if cur.Next.Val != 0 {
|
||||
sum += cur.Next.Val
|
||||
} else {
|
||||
h.Next = &ListNode{Val: sum, Next: nil}
|
||||
h = h.Next
|
||||
sum = 0
|
||||
}
|
||||
cur = cur.Next
|
||||
}
|
||||
return res.Next
|
||||
}
|
||||
```
|
@ -0,0 +1,37 @@
|
||||
package leetcode
|
||||
|
||||
func repeatLimitedString(s string, repeatLimit int) string {
|
||||
cnt := make([]int, 26)
|
||||
for _, c := range s {
|
||||
cnt[int(c-'a')]++
|
||||
}
|
||||
var ns []byte
|
||||
for i := 25; i >= 0; {
|
||||
k := i - 1
|
||||
for cnt[i] > 0 {
|
||||
for j := 0; j < min(cnt[i], repeatLimit); j++ {
|
||||
ns = append(ns, byte(i)+'a')
|
||||
}
|
||||
cnt[i] -= repeatLimit
|
||||
if cnt[i] > 0 {
|
||||
for ; k >= 0 && cnt[k] == 0; k-- {
|
||||
}
|
||||
if k < 0 {
|
||||
break
|
||||
} else {
|
||||
ns = append(ns, byte(k)+'a')
|
||||
cnt[k]--
|
||||
}
|
||||
}
|
||||
}
|
||||
i = k
|
||||
}
|
||||
return string(ns)
|
||||
}
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
} else {
|
||||
return b
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question2182 struct {
|
||||
para2182
|
||||
ans2182
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para2182 struct {
|
||||
one string
|
||||
limit int
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans2182 struct {
|
||||
one string
|
||||
}
|
||||
|
||||
func Test_Problem2182(t *testing.T) {
|
||||
|
||||
qs := []question2182{
|
||||
|
||||
{
|
||||
para2182{"cczazcc", 3},
|
||||
ans2182{"zzcccac"},
|
||||
},
|
||||
|
||||
{
|
||||
para2182{"aababab", 2},
|
||||
ans2182{"bbabaa"},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 2182------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans2182, q.para2182
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, repeatLimitedString(p.one, p.limit))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
98
leetcode/2182.Construct-String-With-Repeat-Limit/README.md
Normal file
98
leetcode/2182.Construct-String-With-Repeat-Limit/README.md
Normal file
@ -0,0 +1,98 @@
|
||||
# [2182. Construct String With Repeat Limit](https://leetcode.com/problems/construct-string-with-repeat-limit/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
You are given a string `s` and an integer `repeatLimit`. Construct a new string `repeatLimitedString` using the characters of `s` such that no letter appears **more than** `repeatLimit` times **in a row**. You do **not** have to use all characters from `s`.
|
||||
|
||||
Return *the **lexicographically largest*** `repeatLimitedString` *possible*.
|
||||
|
||||
A string `a` is **lexicographically larger** than a string `b` if in the first position where `a` and `b` differ, string `a` has a letter that appears later in the alphabet than the corresponding letter in `b`. If the first `min(a.length, b.length)` characters do not differ, then the longer string is the lexicographically larger one.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: s = "cczazcc", repeatLimit = 3
|
||||
Output: "zzcccac"
|
||||
Explanation: We use all of the characters from s to construct the repeatLimitedString "zzcccac".
|
||||
The letter 'a' appears at most 1 time in a row.
|
||||
The letter 'c' appears at most 3 times in a row.
|
||||
The letter 'z' appears at most 2 times in a row.
|
||||
Hence, no letter appears more than repeatLimit times in a row and the string is a valid repeatLimitedString.
|
||||
The string is the lexicographically largest repeatLimitedString possible so we return "zzcccac".
|
||||
Note that the string "zzcccca" is lexicographically larger but the letter 'c' appears more than 3 times in a row, so it is not a valid repeatLimitedString.
|
||||
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: s = "aababab", repeatLimit = 2
|
||||
Output: "bbabaa"
|
||||
Explanation: We use only some of the characters from s to construct the repeatLimitedString "bbabaa".
|
||||
The letter 'a' appears at most 2 times in a row.
|
||||
The letter 'b' appears at most 2 times in a row.
|
||||
Hence, no letter appears more than repeatLimit times in a row and the string is a valid repeatLimitedString.
|
||||
The string is the lexicographically largest repeatLimitedString possible so we return "bbabaa".
|
||||
Note that the string "bbabaaa" is lexicographically larger but the letter 'a' appears more than 2 times in a row, so it is not a valid repeatLimitedString.
|
||||
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `1 <= repeatLimit <= s.length <= 10^5`
|
||||
- `s` consists of lowercase English letters.
|
||||
|
||||
## 题目大意
|
||||
|
||||
给你一个字符串 s 和一个整数 repeatLimit ,用 s 中的字符构造一个新字符串 repeatLimitedString ,使任何字母 连续 出现的次数都不超过 repeatLimit 次。你不必使用 s 中的全部字符。
|
||||
|
||||
返回 字典序最大的 repeatLimitedString 。
|
||||
|
||||
如果在字符串 a 和 b 不同的第一个位置,字符串 a 中的字母在字母表中出现时间比字符串 b 对应的字母晚,则认为字符串 a 比字符串 b 字典序更大 。如果字符串中前 min(a.length, b.length) 个字符都相同,那么较长的字符串字典序更大。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 利用贪心的思想,由于题意要求返回字典序最大的字符串,所以先从字典序最大的字母开始选起。然后选择当前字典序最大的字母个数和 limit 的最小值。如果当前字典序最大的字母比较多,多于 limit,不能一直选择它。选完 limit 个以后,需要选一个字典序次大的字母,选完这个字母以后再次选择字典序最大的字母。因为 limit 限制字母不能连续多于 limit 个。如此循环,直到所有的字母都选完。这样的策略排列出来的字母串为最大字典序。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
func repeatLimitedString(s string, repeatLimit int) string {
|
||||
cnt := make([]int, 26)
|
||||
for _, c := range s {
|
||||
cnt[int(c-'a')]++
|
||||
}
|
||||
var ns []byte
|
||||
for i := 25; i >= 0; {
|
||||
k := i - 1
|
||||
for cnt[i] > 0 {
|
||||
for j := 0; j < min(cnt[i], repeatLimit); j++ {
|
||||
ns = append(ns, byte(i)+'a')
|
||||
}
|
||||
cnt[i] -= repeatLimit
|
||||
if cnt[i] > 0 {
|
||||
for ; k >= 0 && cnt[k] == 0; k-- {
|
||||
}
|
||||
if k < 0 {
|
||||
break
|
||||
} else {
|
||||
ns = append(ns, byte(k)+'a')
|
||||
cnt[k]--
|
||||
}
|
||||
}
|
||||
}
|
||||
i = k
|
||||
}
|
||||
return string(ns)
|
||||
}
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
} else {
|
||||
return b
|
||||
}
|
||||
}
|
||||
```
|
@ -0,0 +1,32 @@
|
||||
package leetcode
|
||||
|
||||
import "math"
|
||||
|
||||
func countPairs(nums []int, k int) int64 {
|
||||
n := int(math.Sqrt(float64(k)))
|
||||
gcds, res := make(map[int]int, n), 0
|
||||
for _, num := range nums {
|
||||
gcds[gcd(num, k)]++
|
||||
}
|
||||
|
||||
for a, n1 := range gcds {
|
||||
for b, n2 := range gcds {
|
||||
if a > b || (a*b)%k != 0 {
|
||||
continue
|
||||
}
|
||||
if a != b {
|
||||
res += n1 * n2
|
||||
} else { // a == b
|
||||
res += n1 * (n1 - 1) / 2
|
||||
}
|
||||
}
|
||||
}
|
||||
return int64(res)
|
||||
}
|
||||
|
||||
func gcd(a, b int) int {
|
||||
for a%b != 0 {
|
||||
a, b = b, a%b
|
||||
}
|
||||
return b
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question2182 struct {
|
||||
para2182
|
||||
ans2182
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para2182 struct {
|
||||
nums []int
|
||||
k int
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans2182 struct {
|
||||
one int64
|
||||
}
|
||||
|
||||
func Test_Problem2182(t *testing.T) {
|
||||
|
||||
qs := []question2182{
|
||||
|
||||
{
|
||||
para2182{[]int{1, 2, 3, 4, 5}, 2},
|
||||
ans2182{7},
|
||||
},
|
||||
|
||||
{
|
||||
para2182{[]int{1, 2, 3, 4}, 5},
|
||||
ans2182{0},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 2183------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans2182, q.para2182
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, countPairs(p.nums, p.k))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
85
leetcode/2183.Count-Array-Pairs-Divisible-by-K/README.md
Normal file
85
leetcode/2183.Count-Array-Pairs-Divisible-by-K/README.md
Normal file
@ -0,0 +1,85 @@
|
||||
# [2183. Count Array Pairs Divisible by K](https://leetcode.com/problems/count-array-pairs-divisible-by-k/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
Given a **0-indexed** integer array `nums` of length `n` and an integer `k`, return *the **number of pairs*** `(i, j)` *such that:*
|
||||
|
||||
- `0 <= i < j <= n - 1` *and*
|
||||
- `nums[i] * nums[j]` *is divisible by* `k`.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: nums = [1,2,3,4,5], k = 2
|
||||
Output: 7
|
||||
Explanation:
|
||||
The 7 pairs of indices whose corresponding products are divisible by 2 are
|
||||
(0, 1), (0, 3), (1, 2), (1, 3), (1, 4), (2, 3), and (3, 4).
|
||||
Their products are 2, 4, 6, 8, 10, 12, and 20 respectively.
|
||||
Other pairs such as (0, 2) and (2, 4) have products 3 and 15 respectively, which are not divisible by 2.
|
||||
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: nums = [1,2,3,4], k = 5
|
||||
Output: 0
|
||||
Explanation: There does not exist any pair of indices whose corresponding product is divisible by 5.
|
||||
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `1 <= nums.length <= 10^5`
|
||||
- `1 <= nums[i], k <= 10^5`
|
||||
|
||||
## 题目大意
|
||||
|
||||
给你一个下标从 0 开始、长度为 n 的整数数组 nums 和一个整数 k ,返回满足下述条件的下标对 (i, j) 的数目:
|
||||
|
||||
- 0 <= i < j <= n - 1 且
|
||||
- nums[i] * nums[j] 能被 k 整除。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 先找出 num 中每个元素与 k 的最大公约数。并统计这些公约数出现的频次,将数据保存在 map 中。在计算过程中,循环可以只需算到 ${O(\sqrt {k})}$ , 因为每一个 gcd[i] 一定是 k 的因数,而它出现的频次不会超过 ${O(\sqrt {k})}$。简单证明一下:假设因子 v 和 k/v 这两个因数为 k 的因子。v 和 k/v 必至少有 1 个小于等于 $\sqrt {k}$。所以 k 的因子也不会超过 2 * $\sqrt {k}$ = ${O(\sqrt {k})}$ 个。
|
||||
- 算出上述的 map 以后,2 层循环暴力遍历 key 值,如果 a * b 能被 k 整除,并且 a 和 b 不相同,那么 a 和 b 对应的 value 值相乘即为满足条件的下标对数;如果 a 和 b 相同,那么下标对数为 $C_{n}^{2}$。最后累加结果即可。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
import "math"
|
||||
|
||||
func countPairs(nums []int, k int) int64 {
|
||||
n := int(math.Sqrt(float64(k)))
|
||||
gcds, res := make(map[int]int, n), 0
|
||||
for _, num := range nums {
|
||||
gcds[gcd(num, k)]++
|
||||
}
|
||||
|
||||
for a, n1 := range gcds {
|
||||
for b, n2 := range gcds {
|
||||
if a > b || (a*b)%k != 0 {
|
||||
continue
|
||||
}
|
||||
if a != b {
|
||||
res += n1 * n2
|
||||
} else { // a == b
|
||||
res += n1 * (n1 - 1) / 2
|
||||
}
|
||||
}
|
||||
}
|
||||
return int64(res)
|
||||
}
|
||||
|
||||
func gcd(a, b int) int {
|
||||
for a%b != 0 {
|
||||
a, b = b, a%b
|
||||
}
|
||||
return b
|
||||
}
|
||||
```
|
Reference in New Issue
Block a user