添加 problems

This commit is contained in:
YDZ
2019-06-26 20:30:28 +08:00
parent 6300c1779f
commit 14f08bfe41
12 changed files with 690 additions and 0 deletions

View File

@ -0,0 +1,24 @@
package leetcode
func subarraysWithKDistinct(A []int, K int) int {
return subarraysWithKDistinctSlideWindow(A, K) - subarraysWithKDistinctSlideWindow(A, K-1)
}
func subarraysWithKDistinctSlideWindow(A []int, K int) int {
left, right, counter, res, freq := 0, 0, K, 0, map[int]int{}
for right = 0; right < len(A); right++ {
if freq[A[right]] == 0 {
counter--
}
freq[A[right]]++
for counter < 0 {
freq[A[left]]--
if freq[A[left]] == 0 {
counter++
}
left++
}
res += right - left + 1
}
return res
}

View File

@ -0,0 +1,73 @@
package leetcode
import (
"fmt"
"testing"
)
type question992 struct {
para992
ans992
}
// para 是参数
// one 代表第一个参数
type para992 struct {
one []int
k int
}
// ans 是答案
// one 代表第一个答案
type ans992 struct {
one int
}
func Test_Problem992(t *testing.T) {
qs := []question992{
question992{
para992{[]int{1, 1, 1, 1, 1, 1, 1, 1}, 1},
ans992{36},
},
question992{
para992{[]int{2, 1, 1, 1, 2}, 1},
ans992{8},
},
question992{
para992{[]int{1, 2}, 1},
ans992{2},
},
question992{
para992{[]int{1, 2, 1, 2, 3}, 2},
ans992{7},
},
question992{
para992{[]int{1, 2, 1, 3, 4}, 3},
ans992{3},
},
question992{
para992{[]int{1}, 5},
ans992{1},
},
question992{
para992{[]int{}, 10},
ans992{0},
},
}
fmt.Printf("------------------------Leetcode Problem 992------------------------\n")
for _, q := range qs {
_, p := q.ans992, q.para992
fmt.Printf("【input】:%v 【output】:%v\n", p, subarraysWithKDistinct(p.one, p.k))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,77 @@
# [992. Subarrays with K Different Integers](https://leetcode.com/problems/subarrays-with-k-different-integers/)
## 题目
Given an array A of positive integers, call a (contiguous, not necessarily distinct) subarray of A good if the number of different integers in that subarray is exactly K.
(For example, [1,2,3,1,2] has 3 different integers: 1, 2, and 3.)
Return the number of good subarrays of A.
Example 1:
```c
Input: A = [1,2,1,2,3], K = 2
Output: 7
Explanation: Subarrays formed with exactly 2 different integers: [1,2], [2,1], [1,2], [2,3], [1,2,1], [2,1,2], [1,2,1,2].
```
Example 2:
```c
Input: A = [1,2,1,3,4], K = 3
Output: 3
Explanation: Subarrays formed with exactly 3 different integers: [1,2,1,3], [2,1,3], [1,3,4].
```
Note:
- 1 <= A.length <= 20000
- 1 <= A[i] <= A.length
- 1 <= K <= A.length
## 题目大意
这道题考察的是滑动窗口的问题。
给出一个数组 和 KK 代表窗口能能包含的不同数字的个数。K = 2 代表窗口内只能有 2 个不同的数字。求数组中满足条件 K 的窗口个数。
## 解题思路
如果只是单纯的滑动窗口去做,会错过一些解。比如在例子 1 中,滑动窗口可以得到 [1,2], [1,2,1], [1,2,1,2], [2,1,2], [1,2], [2,3], 会少 [2,1] 这个解,原因是右边窗口滑动到最右边了,左边窗口在缩小的过程中,右边窗口不会再跟着动了。有同学可能会说,每次左边窗口移动的时候,右边窗口都再次从左边窗口的位置开始重新滑动。这样做确实可以,但是这样做完会发现超时。因为中间包含大量的重复计算。
这道题就需要第 3 个指针。原有滑动窗口的 2 个指针,右窗口保留这个窗口里面最长的子数组,正好有 K 个元素,左窗口右移的逻辑不变。再多用一个指针用来标识正好有 K - 1 个元素的位置。那么正好有 K 个不同元素的解就等于 ans = atMostK(A, K) - atMostK(A, K - 1)。最多有 K 个元素减去最多有 K - 1 个元素得到的窗口中正好有 K 个元素的解。
以例子 1 为例,先求最多有 K 个元素的窗口个数。
```c
[1]
[1,2], [2]
[1,2,1], [2,1], [1]
[1,2,1,2], [2,1,2], [1,2], [2]
[2,3], [3]
```
每当窗口滑动到把 K 消耗为 0 的时候res = right - left + 1 。为什么要这么计算right - left + 1 代表的含义是,终点为 right至多为 K 个元素的窗口有多少个。[left,right], [left + 1,right], [left + 2,right] …… [right,right]。这样算出来的解是包含这道题最终求得的解的,还多出了一部分解。多出来的部分减掉即可,即减掉最多为 K - 1 个元素的解。
最多为 K - 1 个元素的解如下:
```c
[1]
[2]
[1]
[2]
[3]
```
两者相减以后得到的结果就是最终结果:
```c
[1,2]
[1,2,1], [2,1]
[1,2,1,2], [2,1,2], [1,2]
[2,3]
```

View File

@ -0,0 +1,105 @@
package leetcode
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
// 解法一 递归
func isCousins(root *TreeNode, x int, y int) bool {
if root == nil {
return false
}
levelX, levelY := findLevel(root, x, 1), findLevel(root, y, 1)
if levelX != levelY {
return false
}
return !haveSameParents(root, x, y)
}
func findLevel(root *TreeNode, x, level int) int {
if root == nil {
return 0
}
if root.Val != x {
leftLevel, rightLevel := findLevel(root.Left, x, level+1), findLevel(root.Right, x, level+1)
if leftLevel == 0 {
return rightLevel
}
return leftLevel
}
return level
}
func haveSameParents(root *TreeNode, x, y int) bool {
if root == nil {
return false
}
if (root.Left != nil && root.Right != nil && root.Left.Val == x && root.Right.Val == y) ||
(root.Left != nil && root.Right != nil && root.Left.Val == y && root.Right.Val == x) {
return true
}
return haveSameParents(root.Left, x, y) || haveSameParents(root.Right, x, y)
}
// 解法二 BFS
type mark struct {
prev int
depth int
}
func isCousins_BFS(root *TreeNode, x int, y int) bool {
if root == nil {
return false
}
queue := []*TreeNode{root}
visited := [101]*mark{}
visited[root.Val] = &mark{prev: -1, depth: 1}
for len(queue) > 0 {
node := queue[0]
queue = queue[1:]
depth := visited[node.Val].depth
if node.Left != nil {
visited[node.Left.Val] = &mark{prev: node.Val, depth: depth + 1}
queue = append(queue, node.Left)
}
if node.Right != nil {
visited[node.Right.Val] = &mark{prev: node.Val, depth: depth + 1}
queue = append(queue, node.Right)
}
}
if visited[x] == nil || visited[y] == nil {
return false
}
if visited[x].depth == visited[y].depth && visited[x].prev != visited[y].prev {
return true
}
return false
}
// 解法三 DFS
func isCousins_DFS(root *TreeNode, x int, y int) bool {
var depth1, depth2, parent1, parent2 int
dfsCousins(root, x, 0, -1, &parent1, &depth1)
dfsCousins(root, y, 0, -1, &parent2, &depth2)
return depth1 > 1 && depth1 == depth2 && parent1 != parent2
}
func dfsCousins(root *TreeNode, val, depth, last int, parent, res *int) {
if root == nil {
return
}
if root.Val == val {
*res = depth
*parent = last
return
}
depth++
dfsCousins(root.Left, val, depth, root.Val, parent, res)
dfsCousins(root.Right, val, depth, root.Val, parent, res)
}

View File

@ -0,0 +1,56 @@
package leetcode
import (
"fmt"
"testing"
)
type question993 struct {
para993
ans993
}
// para 是参数
// one 代表第一个参数
type para993 struct {
one []int
x int
y int
}
// ans 是答案
// one 代表第一个答案
type ans993 struct {
one bool
}
func Test_Problem993(t *testing.T) {
qs := []question993{
question993{
para993{[]int{1, 2, 3, 4}, 4, 3},
ans993{false},
},
question993{
para993{[]int{1, 2, 3, NULL, 4, NULL, 5}, 5, 4},
ans993{true},
},
question993{
para993{[]int{1, 2, 3, NULL, 4}, 2, 3},
ans993{false},
},
}
fmt.Printf("------------------------Leetcode Problem 993------------------------\n")
for _, q := range qs {
_, p := q.ans993, q.para993
fmt.Printf("【input】:%v ", p)
root := Ints2TreeNode(p.one)
fmt.Printf("【output】:%v \n", isCousins(root, p.x, p.y))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,50 @@
# [993. Cousins in Binary Tree](https://leetcode.com/problems/cousins-in-binary-tree/)
## 题目
In a binary tree, the root node is at depth `0`, and children of each depth `k` node are at depth `k+1`.
Two nodes of a binary tree are *cousins* if they have the same depth, but have **different parents**.
We are given the `root` of a binary tree with unique values, and the values `x` and `y` of two different nodes in the tree.
Return `true` if and only if the nodes corresponding to the values `x` and `y` are cousins.
**Example 1:**
![](https://assets.leetcode.com/uploads/2019/02/12/q1248-01.png)
Input: root = [1,2,3,4], x = 4, y = 3
Output: false
**Example 2:**
![](https://assets.leetcode.com/uploads/2019/02/12/q1248-02.png)
Input: root = [1,2,3,null,4,null,5], x = 5, y = 4
Output: true
**Example 3:**
![](https://assets.leetcode.com/uploads/2019/02/13/q1248-03.png)
Input: root = [1,2,3,null,4], x = 2, y = 3
Output: false
**Note:**
1. The number of nodes in the tree will be between `2` and `100`.
2. Each node has a unique integer value from `1` to `100`.
## 题目大意
在二叉树中,根节点位于深度 0 处,每个深度为 k 的节点的子节点位于深度 k+1 处。如果二叉树的两个节点深度相同,但父节点不同,则它们是一对堂兄弟节点。我们给出了具有唯一值的二叉树的根节点 root以及树中两个不同节点的值 x 和 y。只有与值 x 和 y 对应的节点是堂兄弟节点时,才返回 true。否则返回 false。
## 解题思路
- 给出一个二叉树,和 x y 两个值,要求判断这两个值是不是兄弟结点。兄弟结点的定义:都位于同一层,并且父结点是同一个结点。
- 这一题有 3 种解题方法DFS、BFS、递归。思路都不难。

View File

@ -0,0 +1,58 @@
package leetcode
import (
"math"
"sort"
)
func numSquarefulPerms(A []int) int {
if len(A) == 0 {
return 0
}
used, p, res := make([]bool, len(A)), []int{}, [][]int{}
sort.Ints(A) // 这里是去重的关键逻辑
generatePermutation_996(A, 0, p, &res, &used)
return len(res)
}
func generatePermutation_996(nums []int, index int, p []int, res *[][]int, used *[]bool) {
if index == len(nums) {
checkSquareful := true
for i := 0; i < len(p)-1; i++ {
if !checkSquare(p[i] + p[i+1]) {
checkSquareful = false
break
}
}
if checkSquareful {
temp := make([]int, len(p))
copy(temp, p)
*res = append(*res, temp)
}
return
}
for i := 0; i < len(nums); i++ {
if !(*used)[i] {
if i > 0 && nums[i] == nums[i-1] && !(*used)[i-1] { // 这里是去重的关键逻辑
continue
}
if len(p) > 0 && !checkSquare(nums[i]+p[len(p)-1]) { // 关键的剪枝条件
continue
}
(*used)[i] = true
p = append(p, nums[i])
generatePermutation_996(nums, index+1, p, res, used)
p = p[:len(p)-1]
(*used)[i] = false
}
}
return
}
func checkSquare(num int) bool {
tmp := math.Sqrt(float64(num))
if int(tmp)*int(tmp) == num {
return true
}
return false
}

View File

@ -0,0 +1,57 @@
package leetcode
import (
"fmt"
"testing"
)
type question996 struct {
para996
ans996
}
// para 是参数
// one 代表第一个参数
type para996 struct {
one []int
}
// ans 是答案
// one 代表第一个答案
type ans996 struct {
one int
}
func Test_Problem996(t *testing.T) {
qs := []question996{
question996{
para996{[]int{1, 17, 8}},
ans996{2},
},
question996{
para996{[]int{1}},
ans996{1},
},
question996{
para996{[]int{2, 2, 2}},
ans996{1},
},
question996{
para996{[]int{51768, 47861, 48143, 33221, 50893, 56758, 39946, 10312, 20276, 40616, 43633}},
ans996{1},
},
}
fmt.Printf("------------------------Leetcode Problem 996------------------------\n")
for _, q := range qs {
_, p := q.ans996, q.para996
fmt.Printf("【input】:%v 【output】:%v\n", p, numSquarefulPerms(p.one))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,41 @@
# [996. Number of Squareful Arrays](https://leetcode.com/problems/number-of-squareful-arrays/)
## 题目
Given an array `A` of non-negative integers, the array is *squareful* if for every pair of adjacent elements, their sum is a perfect square.
Return the number of permutations of A that are squareful. Two permutations `A1` and `A2` differ if and only if there is some index `i` such that `A1[i] != A2[i]`.
**Example 1:**
Input: [1,17,8]
Output: 2
Explanation:
[1,8,17] and [17,8,1] are the valid permutations.
**Example 2:**
Input: [2,2,2]
Output: 1
**Note:**
1. `1 <= A.length <= 12`
2. `0 <= A[i] <= 1e9`
## 题目大意
给定一个非负整数数组 A如果该数组每对相邻元素之和是一个完全平方数则称这一数组为正方形数组。
返回 A 的正方形排列的数目。两个排列 A1 和 A2 不同的充要条件是存在某个索引 i使得 A1[i] != A2[i]。
## 解题思路
- 这一题是第 47 题的加强版。第 47 题要求求出一个数组的所有不重复的排列。这一题要求求出一个数组的所有不重复,且相邻两个数字之和都为完全平方数的排列。
- 思路和第 47 题完全一致,只不过增加判断相邻两个数字之和为完全平方数的判断,注意在 DFS 的过程中,需要剪枝,否则时间复杂度很高,会超时。

View File

@ -0,0 +1,26 @@
package leetcode
func isValid_(S string) bool {
if len(S) < 3 {
return false
}
stack := []byte{}
for i := 0; i < len(S); i++ {
if S[i] == 'a' {
stack = append(stack, S[i])
} else if S[i] == 'b' {
if len(stack) > 0 && stack[len(stack)-1] == 'a' {
stack = append(stack, S[i])
} else {
return false
}
} else {
if len(stack) > 1 && stack[len(stack)-1] == 'b' && stack[len(stack)-2] == 'a' {
stack = stack[:len(stack)-2]
} else {
return false
}
}
}
return len(stack) == 0
}

View File

@ -0,0 +1,57 @@
package leetcode
import (
"fmt"
"testing"
)
type question1003 struct {
para1003
ans1003
}
// para 是参数
// one 代表第一个参数
type para1003 struct {
s string
}
// ans 是答案
// one 代表第一个答案
type ans1003 struct {
one bool
}
func Test_Problem1003(t *testing.T) {
qs := []question1003{
question1003{
para1003{"aabcbc"},
ans1003{true},
},
question1003{
para1003{"abcabcababcc"},
ans1003{true},
},
question1003{
para1003{"abccba"},
ans1003{false},
},
question1003{
para1003{"cababc"},
ans1003{false},
},
}
fmt.Printf("------------------------Leetcode Problem 1003------------------------\n")
for _, q := range qs {
_, p := q.ans1003, q.para1003
fmt.Printf("【input】:%v 【output】:%v\n", p, isValid_(p.s))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,66 @@
# [1003. Check If Word Is Valid After Substitutions](https://leetcode.com/problems/check-if-word-is-valid-after-substitutions/)
## 题目
We are given that the string "abc" is valid.
From any valid string V, we may split V into two pieces X and Y such that X + Y (X concatenated with Y) is equal to V. (X or Y may be empty.) Then, X + "abc" + Y is also valid.
If for example S = "abc", then examples of valid strings are: "abc", "aabcbc", "abcabc", "abcabcababcc". Examples of invalid strings are: "abccba", "ab", "cababc", "bac".
Return true if and only if the given string S is valid.
Example 1:
```c
Input: "aabcbc"
Output: true
Explanation:
We start with the valid string "abc".
Then we can insert another "abc" between "a" and "bc", resulting in "a" + "abc" + "bc" which is "aabcbc".
```
Example 2:
```c
Input: "abcabcababcc"
Output: true
Explanation:
"abcabcabc" is valid after consecutive insertings of "abc".
Then we can insert "abc" before the last letter, resulting in "abcabcab" + "abc" + "c" which is "abcabcababcc".
```
Example 3:
```c
Input: "abccba"
Output: false
```
Example 4:
```c
Input: "cababc"
Output: false
```
Note:
1. 1 <= S.length <= 20000
2. S[i] is 'a', 'b', or 'c'
## 题目大意
假设 abc 是有效的字符串,对于任何 字符串 V如果用 abc 把字符串 V 切成 2 半X 和 Y组成 X + abc + Y 的字符串X + abc + Y 的这个字符串依旧是有效的。X 和 Y 可以是空字符串。
例如,"abc"( "" + "abc" + ""), "aabcbc"( "a" + "abc" + "bc"), "abcabc"( "" + "abc" + "abc"), "abcabcababcc"( "abc" + "abc" + "ababcc",其中 "ababcc" 也是有效的,"ab" + "abc" + "c") 都是有效的字符串。
"abccba"( "" + "abc" + "cba""cba" 不是有效的字符串), "ab"("ab" 也不是有效字符串), "cababc"("c" + "abc" + "bc""c""bc" 都不是有效字符串), "bac" ("bac" 也不是有效字符串)这些都不是有效的字符串。
任意给一个字符串 S ,要求判断它是否有效,如果有效则输出 true。
## 解题思路
这一题可以类似括号匹配问题,因为 "abc" 这样的组合就代表是有效的,类似于括号匹配,遇到 "a" 就入栈,当遇到 "b" 字符的时候判断栈顶是不是 "a",当遇到 "c" 字符的时候需要判断栈顶是不是 "a" 和 "b"。最后如果栈都清空了,就输出 true。