mirror of
https://github.com/halfrost/LeetCode-Go.git
synced 2025-07-06 09:23:19 +08:00
Add solution 0368、0377、0696
This commit is contained in:
@ -0,0 +1,33 @@
|
||||
package leetcode
|
||||
|
||||
import "sort"
|
||||
|
||||
func largestDivisibleSubset(nums []int) []int {
|
||||
sort.Ints(nums)
|
||||
dp, res := make([]int, len(nums)), []int{}
|
||||
for i := range dp {
|
||||
dp[i] = 1
|
||||
}
|
||||
maxSize, maxVal := 1, 1
|
||||
for i := 1; i < len(nums); i++ {
|
||||
for j, v := range nums[:i] {
|
||||
if nums[i]%v == 0 && dp[j]+1 > dp[i] {
|
||||
dp[i] = dp[j] + 1
|
||||
}
|
||||
}
|
||||
if dp[i] > maxSize {
|
||||
maxSize, maxVal = dp[i], nums[i]
|
||||
}
|
||||
}
|
||||
if maxSize == 1 {
|
||||
return []int{nums[0]}
|
||||
}
|
||||
for i := len(nums) - 1; i >= 0 && maxSize > 0; i-- {
|
||||
if dp[i] == maxSize && maxVal%nums[i] == 0 {
|
||||
res = append(res, nums[i])
|
||||
maxVal = nums[i]
|
||||
maxSize--
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question368 struct {
|
||||
para368
|
||||
ans368
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para368 struct {
|
||||
one []int
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans368 struct {
|
||||
one []int
|
||||
}
|
||||
|
||||
func Test_Problem368(t *testing.T) {
|
||||
|
||||
qs := []question368{
|
||||
|
||||
{
|
||||
para368{[]int{1, 2, 3}},
|
||||
ans368{[]int{1, 2}},
|
||||
},
|
||||
|
||||
{
|
||||
para368{[]int{1, 2, 4, 8}},
|
||||
ans368{[]int{1, 2, 4, 8}},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 368------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans368, q.para368
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, largestDivisibleSubset(p.one))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
86
leetcode/0368.Largest-Divisible-Subset/README.md
Normal file
86
leetcode/0368.Largest-Divisible-Subset/README.md
Normal file
@ -0,0 +1,86 @@
|
||||
# [368. Largest Divisible Subset](https://leetcode.com/problems/largest-divisible-subset/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
Given a set of **distinct** positive integers `nums`, return the largest subset `answer` such that every pair `(answer[i], answer[j])` of elements in this subset satisfies:
|
||||
|
||||
- `answer[i] % answer[j] == 0`, or
|
||||
- `answer[j] % answer[i] == 0`
|
||||
|
||||
If there are multiple solutions, return any of them.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: nums = [1,2,3]
|
||||
Output: [1,2]
|
||||
Explanation: [1,3] is also accepted.
|
||||
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: nums = [1,2,4,8]
|
||||
Output: [1,2,4,8]
|
||||
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `1 <= nums.length <= 1000`
|
||||
- `1 <= nums[i] <= 2 * 109`
|
||||
- All the integers in `nums` are **unique**.
|
||||
|
||||
## 题目大意
|
||||
|
||||
给你一个由 无重复 正整数组成的集合 nums ,请你找出并返回其中最大的整除子集 answer ,子集中每一元素对 (answer[i], answer[j]) 都应当满足:
|
||||
|
||||
- answer[i] % answer[j] == 0 ,或
|
||||
- answer[j] % answer[i] == 0
|
||||
|
||||
如果存在多个有效解子集,返回其中任何一个均可。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 根据题目数据规模 1000,可以估计此题大概率是动态规划,并且时间复杂度是 O(n^2)。先将集合排序,以某一个小的数作为基准,不断的选择能整除的数加入集合。按照这个思路考虑,此题和第 300 题经典的 LIS 解题思路一致。只不过 LIS 每次选择更大的数,此题除了选择更大的数,只不过多了一个判断,这个更大的数能否整除当前集合里面的所有元素。按照此法一定可以找出最大的集合。
|
||||
- 剩下的问题是如何输出最大集合。这道题的集合具有重叠子集的性质,例如 [2,4,8,16] 这个集合,长度是 4,它一定包含长度为 3 的子集,因为从它里面随便取 3 个数形成的子集也满足元素相互能整除的条件。同理,它也一定包含长度为 2,长度为 1 的子集。由于有这个性质,可以利用 dp 数组里面的数据,输出最大集合。例如,[2,4,6,8,9,13,16,40],由动态规划可以找到最大集合是 [2,4,8,16]。长度为 4 的找到了,再找长度为 3 的,[2,4,8],[2,4,40]。在最大集合中,最大元素是 16,所以 [2,4,40] 这个集合排除,它的最大元素大于 16。选定 [2,4,8] 这个集合,此时最大元素是 8 。以此类推,筛选到最后,便可以输出 [16,8,4,2] 这个组最大集合的答案了。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
import "sort"
|
||||
|
||||
func largestDivisibleSubset(nums []int) []int {
|
||||
sort.Ints(nums)
|
||||
dp, res := make([]int, len(nums)), []int{}
|
||||
for i := range dp {
|
||||
dp[i] = 1
|
||||
}
|
||||
maxSize, maxVal := 1, 1
|
||||
for i := 1; i < len(nums); i++ {
|
||||
for j, v := range nums[:i] {
|
||||
if nums[i]%v == 0 && dp[j]+1 > dp[i] {
|
||||
dp[i] = dp[j] + 1
|
||||
}
|
||||
}
|
||||
if dp[i] > maxSize {
|
||||
maxSize, maxVal = dp[i], nums[i]
|
||||
}
|
||||
}
|
||||
if maxSize == 1 {
|
||||
return []int{nums[0]}
|
||||
}
|
||||
for i := len(nums) - 1; i >= 0 && maxSize > 0; i-- {
|
||||
if dp[i] == maxSize && maxVal%nums[i] == 0 {
|
||||
res = append(res, nums[i])
|
||||
maxVal = nums[i]
|
||||
maxSize--
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
```
|
@ -1,6 +1,20 @@
|
||||
package leetcode
|
||||
|
||||
func combinationSum4(nums []int, target int) int {
|
||||
dp := make([]int, target+1)
|
||||
dp[0] = 1
|
||||
for i := 1; i <= target; i++ {
|
||||
for _, num := range nums {
|
||||
if i-num >= 0 {
|
||||
dp[i] += dp[i-num]
|
||||
}
|
||||
}
|
||||
}
|
||||
return dp[target]
|
||||
}
|
||||
|
||||
// 暴力解法超时
|
||||
func combinationSum41(nums []int, target int) int {
|
||||
if len(nums) == 0 {
|
||||
return 0
|
||||
}
|
@ -34,7 +34,7 @@ func Test_Problem377(t *testing.T) {
|
||||
|
||||
{
|
||||
para377{[]int{1, 2, 3}, 32},
|
||||
ans377{7},
|
||||
ans377{181997601},
|
||||
},
|
||||
}
|
||||
|
98
leetcode/0377.Combination-Sum-IV/README.md
Normal file
98
leetcode/0377.Combination-Sum-IV/README.md
Normal file
@ -0,0 +1,98 @@
|
||||
# [377. Combination Sum IV](https://leetcode.com/problems/combination-sum-iv/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
Given an array of **distinct** integers `nums` and a target integer `target`, return *the number of possible combinations that add up to* `target`.
|
||||
|
||||
The answer is **guaranteed** to fit in a **32-bit** integer.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: nums = [1,2,3], target = 4
|
||||
Output: 7
|
||||
Explanation:
|
||||
The possible combination ways are:
|
||||
(1, 1, 1, 1)
|
||||
(1, 1, 2)
|
||||
(1, 2, 1)
|
||||
(1, 3)
|
||||
(2, 1, 1)
|
||||
(2, 2)
|
||||
(3, 1)
|
||||
Note that different sequences are counted as different combinations.
|
||||
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: nums = [9], target = 3
|
||||
Output: 0
|
||||
```
|
||||
|
||||
**Constraints:**
|
||||
|
||||
- `1 <= nums.length <= 200`
|
||||
- `1 <= nums[i] <= 1000`
|
||||
- All the elements of `nums` are **unique**.
|
||||
- `1 <= target <= 1000`
|
||||
|
||||
**Follow up:** What if negative numbers are allowed in the given array? How does it change the problem? What limitation we need to add to the question to allow negative numbers?
|
||||
|
||||
## 题目大意
|
||||
|
||||
给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。题目数据保证答案符合 32 位整数范围。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- Combination Sum 这是系列问题。拿到题目,笔者先用暴力解法 dfs 尝试了一版,包含的重叠子问题特别多,剪枝条件也没有写好,果然超时。元素只有 [1,2,3] 这三种,target = 32,这组数据居然有 181997601 这么多种情况。仔细看了题目数据规模 1000,基本可以断定此题是动态规划,并且时间复杂度是 O(n^2)。
|
||||
- 本题和完全背包有点像,但是还是有区别。完全背包的取法内部不区分顺序。例如 5 = 1 + 2 + 2。但是本题是 3 种答案 (1,2,2),(2,1,2),(2,2,1)。定义 dp[i] 为总和为 target = i 的组合总数。最终答案存在 dp[target] 中。状态转移方程为:
|
||||
|
||||
$$dp[i] =\left\{\begin{matrix}1,i=0\\ \sum dp[i-j],i\neq 0\end{matrix}\right.$$
|
||||
|
||||
- 这道题最后有一个进阶问题。如果给定的数组中含有负数,则会导致出现无限长度的排列。例如,假设数组 nums 中含有正整数 a 和负整数 −b(其中 a>0,b>0,-b<0),则有 a×b+(−b)×a=0,对于任意一个元素之和等于 target 的排列,在该排列的后面添加 b 个 a 和 a 个 −b 之后,得到的新排列的元素之和仍然等于 target,而且还可以在新排列的后面继续 b 个 a 和 a 个 −b。因此只要存在元素之和等于 target 的排列,就能构造出无限长度的排列。如果允许负数出现,则必须限制排列的最大长度,不然会出现无限长度的排列。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
func combinationSum4(nums []int, target int) int {
|
||||
dp := make([]int, target+1)
|
||||
dp[0] = 1
|
||||
for i := 1; i <= target; i++ {
|
||||
for _, num := range nums {
|
||||
if i-num >= 0 {
|
||||
dp[i] += dp[i-num]
|
||||
}
|
||||
}
|
||||
}
|
||||
return dp[target]
|
||||
}
|
||||
|
||||
// 暴力解法超时
|
||||
func combinationSum41(nums []int, target int) int {
|
||||
if len(nums) == 0 {
|
||||
return 0
|
||||
}
|
||||
c, res := []int{}, 0
|
||||
findcombinationSum4(nums, target, 0, c, &res)
|
||||
return res
|
||||
}
|
||||
|
||||
func findcombinationSum4(nums []int, target, index int, c []int, res *int) {
|
||||
if target <= 0 {
|
||||
if target == 0 {
|
||||
*res++
|
||||
}
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(nums); i++ {
|
||||
c = append(c, nums[i])
|
||||
findcombinationSum4(nums, target-nums[i], i, c, res)
|
||||
c = c[:len(c)-1]
|
||||
}
|
||||
}
|
||||
```
|
@ -0,0 +1,21 @@
|
||||
package leetcode
|
||||
|
||||
func countBinarySubstrings(s string) int {
|
||||
last, res := 0, 0
|
||||
for i := 0; i < len(s); {
|
||||
c, count := s[i], 1
|
||||
for i++; i < len(s) && s[i] == c; i++ {
|
||||
count++
|
||||
}
|
||||
res += min(count, last)
|
||||
last = count
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question696 struct {
|
||||
para696
|
||||
ans696
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para696 struct {
|
||||
one string
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans696 struct {
|
||||
one int
|
||||
}
|
||||
|
||||
func Test_Problem696(t *testing.T) {
|
||||
|
||||
qs := []question696{
|
||||
|
||||
{
|
||||
para696{"00110011"},
|
||||
ans696{6},
|
||||
},
|
||||
|
||||
{
|
||||
para696{"10101"},
|
||||
ans696{4},
|
||||
},
|
||||
|
||||
{
|
||||
para696{"0110001111"},
|
||||
ans696{6},
|
||||
},
|
||||
|
||||
{
|
||||
para696{"0001111"},
|
||||
ans696{3},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 696------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans696, q.para696
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, countBinarySubstrings(p.one))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
69
leetcode/0696.Count-Binary-Substrings/README.md
Normal file
69
leetcode/0696.Count-Binary-Substrings/README.md
Normal file
@ -0,0 +1,69 @@
|
||||
# [696. Count Binary Substrings](https://leetcode.com/problems/count-binary-substrings/)
|
||||
|
||||
|
||||
## 题目
|
||||
|
||||
Give a string `s`, count the number of non-empty (contiguous) substrings that have the same number of 0's and 1's, and all the 0's and all the 1's in these substrings are grouped consecutively.
|
||||
|
||||
Substrings that occur multiple times are counted the number of times they occur.
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```
|
||||
Input: "00110011"
|
||||
Output: 6
|
||||
Explanation: There are 6 substrings that have equal number of consecutive 1's and 0's: "0011", "01", "1100", "10", "0011", and "01".
|
||||
|
||||
Notice that some of these substrings repeat and are counted the number of times they occur.
|
||||
|
||||
Also, "00110011" is not a valid substring becauseall the 0's (and 1's) are not grouped together.
|
||||
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```
|
||||
Input: "10101"
|
||||
Output: 4
|
||||
Explanation: There are 4 substrings: "10", "01", "10", "01" that have equal number of consecutive 1's and 0's.
|
||||
|
||||
```
|
||||
|
||||
**Note:**
|
||||
|
||||
- `s.length` will be between 1 and 50,000.
|
||||
- `s` will only consist of "0" or "1" characters.
|
||||
|
||||
## 题目大意
|
||||
|
||||
给定一个字符串 s,计算具有相同数量 0 和 1 的非空(连续)子字符串的数量,并且这些子字符串中的所有 0 和所有 1 都是连续的。重复出现的子串要计算它们出现的次数。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 简单题。先分组统计 0 和 1 的个数,例如,`0110001111` 按照 0 和 1 分组统计出来的结果是 [1, 2, 3, 4]。再拼凑结果。相邻 2 组取两者最短的,例如 `0110001111`,凑成的结果应该是 min(1,2),min(2,3),min(3,4),即 `01`,`01`,`10`,`1100`,`0011`,`000111`。时间复杂度 O(n),空间复杂度 O(1)。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
func countBinarySubstrings(s string) int {
|
||||
last, res := 0, 0
|
||||
for i := 0; i < len(s); {
|
||||
c, count := s[i], 1
|
||||
for i++; i < len(s) && s[i] == c; i++ {
|
||||
count++
|
||||
}
|
||||
res += min(count, last)
|
||||
last = count
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
```
|
Reference in New Issue
Block a user