文章目录

  • 2020/4/1
    • leetcode 914. 卡牌分组_Go
    • leetcode 1111. 有效括号的嵌套深度_Go
  • 2020/4/2
    • leetcode 289. 生命游戏_Go
  • 2020/4/3
    • leetcode 8. 字符串转换整数_Go
  • 2020/4/4
    • leetcode 42. 接雨水_Go
  • 2020/4/5
    • leetcode 460. LFU缓存_Go
  • 2020/4/6
    • leetcode 1013. 将数组分成相等的三个部分_Go
  • 2020/4/7
    • leetcode 面试题 01.07. 旋转矩阵_Go
  • 2020/4/8
    • leetcode 面试题13. 机器人的运动范围_Go
  • 2020/4/9
    • leetcode 22. 括号生成_Go
  • 2020/4/10
    • leetcode 151.翻转字符串里的单词_Go
    • leetcode 面试题 01.06. 字符串压缩_Go
  • 2020/4/11
    • leetcode 887.鸡蛋掉落_Go
  • 2020/4/12
    • leetcode 面试题 16.03. 交点_Go
  • 2020/4/14
    • leetcode 455. 两数相加Ⅱ_Go
    • leetcode 53. 最大字序和_Go
  • 2020/4/15
    • leetcode 542. 01矩阵_Go
  • 2020/4/16
    • leetcode 52. 合并区间_Go
  • 2020/4/17
    • leetcode 55. 跳跃游戏_Go
  • 2020/4/18
    • leetcode 11. 盛水最多的容器_Go
    • leetcode 104. 二叉树的最大深度_C++
    • leetcode 101. 对称二叉树_C++
  • 2020/4/19 && 20
    • leetcode 455. 分发饼干_C++
    • leetcode 股票题C++
      • leetcode 121. 买卖股票的最佳时机_C++
      • leetcode 122. 买卖股票的最佳时机 II_C++
      • leetcode 123. 买卖股票的最佳时机 III_C++
      • leetcode 188. 买卖股票的最佳时机IV_C++
      • leetcode 309. 最佳买卖股票时机含冷冻期_C++
      • leetcode 714. 买卖股票的最佳时机含手续费_C++
    • leetcode 200. 岛屿数量_Go
  • 2020/4/21
    • leetcode 1248. 统计优美子数组_Go
  • 2020/4/22
    • leetcode 199. 二叉树的右视图_Go
  • 2020/4/23
    • leetcode 面试题 08.11. 硬币_Go
  • 2020/4/24
    • leetcode 面试题51. 数组中的逆序对_Go
  • 2020/4/25 && 26
    • 背包九讲_C++
      • 0/1背包问题
      • 完全背包问题
    • leetcode 46. 全排列_Go
    • leetcode 23. 合并K个排序链表_Go
  • 2020/4/27
    • leetcode 33. 搜索旋转排序数组_Go
  • 2020/4/28
    • leetcode 1. 两数之和_C++
    • leetcode 面试题56 - I. 数组中数字出现的次数_Go
  • 2020/4/29
    • leetcode 1095. 山脉数组中查找目标值_Go

hexo链接: link

2020/4/1

leetcode 914. 卡牌分组_Go

package mainimport ("fmt"
)func gcd(a, b int) int {if b == 0 {return a}return gcd(b, a%b)
}func hasGroupsSizeX(deck []int) bool {m := make(map[int]int)for i := 0; i < len(deck); i++ {m[deck[i]]++}for _, value := range m {for _, k := range m {if gcd(value, k) < 2 {return false}}}return true
}// 感觉就是一个Hash,再加上gcd
func main() {deck := []int{1, 1, 1, 1, 2, 2, 2, 2, 2, 2}fmt.Println(hasGroupsSizeX(deck))
}

leetcode 1111. 有效括号的嵌套深度_Go

package mainimport "fmt"func maxDepthAfterSplit(seq string) []int {stack := make([]int, 0, len(seq))var deep = -1for _, v := range seq {if string(v) == "(" {deep++stack = append(stack, deep%2)}if string(v) == ")" {stack = append(stack, deep%2)deep--}}return stack
}// 说实话,这题目我都看了半天
// depth("(" + A + ")") = 1 + depth(A) 关键是这句话理解就好了
// 分析到最后就是把左括号竟可能的分成两个序列即可
func main() {seq := "(()())"ans := maxDepthAfterSplit(seq)fmt.Println(ans)
}

2020/4/2

leetcode 289. 生命游戏_Go

package mainimport ("fmt"
)func abs(a int) int {if a < 0 {return -a}return a
}func gameOfLife(board [][]int) {way := [3]int{0, 1, -1}row := len(board)col := len(board[0])// select every nodefor i := 0; i < row; i++ {for j := 0; j < col; j++ {aliveNum := 0// select each direction// 和迷宫走法一样for x := 0; x < 3; x++ {for y := 0; y < 3; y++ {if way[x] != 0 || way[y] != 0 {r := way[x] + ic := way[y] + j// check borderif (r >= 0 && r < row) && (c >= 0 && c < col) {if abs(board[r][c]) == 1 {aliveNum++fmt.Println(aliveNum, i, j)}}}}}// check status// alive ->deadif (board[i][j] == 1) && (aliveNum < 2 || aliveNum > 3) {board[i][j] = -1}// dead ->aliveif (board[i][j] == 0) && (aliveNum == 3) {board[i][j] = 2}}}for i := 0; i < row; i++ {for j := 0; j < col; j++ {if board[i][j] > 0 {board[i][j] = 1} else {board[i][j] = 0}}}
}// 生命游戏,第一眼觉得是个图题,后来才知道主要是为了练符合状态
// 需要变化的是结点本身的状态,改变依据是周围结点的状态
// 硬做的话提前备份一个二维数组就好,尝试一下原地算法
// 原地算法不依赖额外的资源或者依赖少数的额外资源,仅依靠输出来覆盖输入的一种算法操作。
// 需要对改变后的数组状态做一些新的标记,来避免与0/1状态混淆
/*
alive->dead :-1
alive->alive :1
dead->alive :2
*/
func main() {var board = make([][]int, 0)temp := []int{0, 1, 0}board = append(board, temp)temp = []int{0, 0, 1}board = append(board, temp)temp = []int{1, 1, 1}board = append(board, temp)temp = []int{0, 0, 0}board = append(board, temp)fmt.Println(board)gameOfLife(board)fmt.Println(board)
}

2020/4/3

leetcode 8. 字符串转换整数_Go

package mainimport ("fmt""math""strings""unicode"
)// 自动机什么的是学不会的,但各种情况的逻辑判断需要好好锻炼
func myAtoi(str string) int {flag := 1// 按找空白符分割字符串成一个切片strSlice := strings.FieldsFunc(str, unicode.IsSpace)//fmt.Println(strSlice, reflect.TypeOf(strSlice))// 分割后只需要判断切片内第一个元素即可var temp string// 防止输入""if len(strSlice) == 0 {return 0}if !unicode.IsDigit(rune(strSlice[0][0])) {if strSlice[0][0] == '+' {flag = 1strSlice[0] = strSlice[0][1:]//fmt.Println(strSlice[0])} else if strSlice[0][0] == '-' {flag = -1strSlice[0] = strSlice[0][1:]} else {return 0}}first := strSlice[0]for i := 0; i < len(first); i++ {if !unicode.IsDigit(rune(first[i])) {break} else {temp += string(first[i])}}// strToNumans := 0for i := 0; i < len(temp); i++ {ans = int(temp[i]-'0') + ans*10if ans*flag > math.MaxInt32 {return math.MaxInt32}if ans*flag < math.MinInt32 {return math.MinInt32}}return flag * ans
}func main() {//str := "-996 9k3 and 987"//str2 := "words and 987"str3 := "-91283472332"fmt.Println(myAtoi(str3))
}

2020/4/4

leetcode 42. 接雨水_Go

package mainimport "fmt"// 暴力思维:两边最大高度的较小值减去当前高度的值
// 但暴力不可取,还是不暴力了……
// 题解里那个栈的应用是真的没想到,tcl
// 用two pointers来解决
func trap(height []int) int {left := 0right := len(height) - 1ans := 0leftMax, rightMax := 0, 0for left < right {if height[left] < height[right] {if height[left] >= leftMax {leftMax = height[left]} else {ans += leftMax - height[left]}left++} else {if height[right] >= rightMax {rightMax = height[right]} else {ans += rightMax - height[right]}right--}}return ans
}func main() {height := []int{0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}fmt.Println(trap(height))
}

2020/4/5

leetcode 460. LFU缓存_Go

真难……

package mainimport "fmt"// Node struct
type Node struct {key, value intnum        int   // 调用次数prev, next *Node // 前序,后继指针,为双重链表做准备
}// DoubleList prepare for freeList
type DoubleList struct {head, tail *Node
}// ConstructorDB init
func ConstructorDB() *DoubleList {head, tail := &Node{}, &Node{}head.next, tail.prev = tail, headreturn &DoubleList{head: head,tail: tail,}
}// LFUCache struct
type LFUCache struct {capacity intrest     int // 剩余容量minFreq  int // 当前最少numcache    map[int]*NodefreqList map[int]*DoubleList // key是调用的num,每个建对应的值是一个链表,越靠近头结点调用的越近
}// Constructor init
func Constructor(capacity int) LFUCache {return LFUCache{capacity: capacity,rest:     capacity,cache:    make(map[int]*Node),freqList: make(map[int]*DoubleList),minFreq:  0,}
}// Remove node from DoubleList
func (p *DoubleList) Remove(node *Node) {node.prev.next = node.nextnode.next.prev = node.prevnode.next = nilnode.prev = nil
}// IsEmpty -> Judge if DoubleList is empty
func (p *DoubleList) IsEmpty() bool {return p.head.next == p.tail
}// AddNode -> add node to doubleList
func (p *DoubleList) AddNode(node *Node) {node.next = p.head.nextnode.prev = p.headp.head.next.prev = nodep.head.next = node
}// UpdateFre freeList
func (p *LFUCache) UpdateFre(node *Node) {freq := node.nump.freqList[freq].Remove(node)// Judge if its num is minif p.minFreq == freq && p.freqList[freq].IsEmpty() {p.minFreq++delete(p.freqList, freq)}node.num++if p.freqList[node.num] == nil {p.freqList[node.num] = ConstructorDB()}p.freqList[node.num].AddNode(node)
}// Get output
func (p *LFUCache) Get(key int) int {node, ok := p.cache[key]if ok {p.UpdateFre(node)return node.value}return -1
}// RemoveLast -> remove last node
func (p *DoubleList) RemoveLast() *Node {if p.IsEmpty() {return nil}last := p.tail.prevp.Remove(last)return last
}// Put input
func (p *LFUCache) Put(key int, value int) {if p.capacity == 0 {return}node, ok := p.cache[key]if ok {node.value = valuep.UpdateFre(node)} else {if p.rest == 0 {node := p.freqList[p.minFreq].RemoveLast()delete(p.cache, node.key)p.rest++}temp := &Node{key: key, value: value, num: 1}p.cache[key] = tempif p.freqList[1] == nil {p.freqList[1] = ConstructorDB()}p.freqList[1].AddNode(temp)p.minFreq = 1p.rest--}
}func main() {cache := Constructor(2)cache.Put(1, 1)cache.Put(2, 2)fmt.Println(cache.Get(1)) // 返回 1cache.Put(3, 3)           // 去除 key 2fmt.Println(cache.Get(2)) // 返回 -1 (未找到key 2)fmt.Println(cache.Get(3)) // 返回 3cache.Put(4, 4)           // 去除 key 1fmt.Println(cache.Get(1)) // 返回 -1 (未找到 key 1)fmt.Println(cache.Get(3)) // 返回 3fmt.Println(cache.Get(4)) // 返回 4
}

2020/4/6

今天的每日一题我直接放弃了,做之前简单的吧……

leetcode 1013. 将数组分成相等的三个部分_Go

package mainimport "fmt"func canThreePartsEqualSum(A []int) bool {sum := 0for i := 0; i < len(A); i++ {sum += A[i]}if sum%3 != 0 {return false}target := sum / 3idx, sumTemp := 0, 0for idx < len(A) {sumTemp += A[idx]if sumTemp == target {break}idx++}if sumTemp != target {return false}idx++for idx+1 < len(A) { // 满足最后一部分非空sumTemp += A[idx]if sumTemp == 2*target {return true}idx++}return false
}func main() {A := []int{0, 2, 1, -6, 6, -7, 9, 1, 2, 0, 1}fmt.Println(canThreePartsEqualSum(A))
}

2020/4/7

leetcode 面试题 01.07. 旋转矩阵_Go

我自己本身没有去纠结原地算法,我觉得这一题让我进一步了解copy这个机制已经有收获了

package mainimport "fmt"func rotate(matrix [][]int) {length := len(matrix)ans := make([][]int, length)for i := 0; i < length; i++ {ans[i] = make([]int, length)}for i := 0; i < length; i++ {for j := 0; j < length; j++ {ans[j][length-i-1] = matrix[i][j]}}copy(matrix, ans)
}func main() {matrix := [][]int{{1, 2, 3},{4, 5, 6},{7, 8, 9},}rotate(matrix)fmt.Println(matrix)
}

2020/4/8

leetcode 面试题13. 机器人的运动范围_Go

package mainimport "fmt"func addNum(a int) int {ans := 0for a > 0 {ans += a % 10a /= 10}return ans
}func judge(row, col, m, n, k int, visit [][]int) bool {if row < 0 || row >= m {return false}if col < 0 || col >= n {return false}if visit[row][col] == 1 {return false}visit[row][col] = 1ans := addNum(row) + addNum(col)return ans <= k
}func movingCount(m int, n int, k int) int {visit := make([][]int, m)for i := 0; i < m; i++ {visit[i] = make([]int, n)}num := 0// init queuequeue := [][]int{}temp := []int{0, 0}queue = append(queue, temp)visit[0][0] = 1// BFSfor len(queue) != 0 {top := queue[0]queue = queue[1:]num++if judge(top[0]-1, top[1], m, n, k, visit) {temp = []int{top[0] - 1, top[1]}queue = append(queue, temp)}if judge(top[0]+1, top[1], m, n, k, visit) {temp = []int{top[0] + 1, top[1]}queue = append(queue, temp)}if judge(top[0], top[1]-1, m, n, k, visit) {temp = []int{top[0], top[1] - 1}queue = append(queue, temp)}if judge(top[0], top[1]+1, m, n, k, visit) {temp = []int{top[0], top[1] + 1}queue = append(queue, temp)}}return num
}func main() {fmt.Println(movingCount(2, 3, 1))
}

2020/4/9

leetcode 22. 括号生成_Go

这题我是用暴力做的

但引出了切片作为函数参数这个大坑,资料:https://www.jianshu.com/p/7439e7ae3c4c

从输出可以看出,当slice传递给函数的时候,新建了切片s。在函数中给s进行了append一个元素,由于此时s的容量足够到,并没有生成新的底层数组。当修改返回的ret的时候,ret也共用了底层的数组,因此修改ret的原始,相应的也看到了slice的改变。

append 操作

如果在函数内,append操作超过了原始切片的容量,将会有一个新建底层数组的过程,那么此时再修改函数返回切片,应该不会再影响原始切片

也就是说不在共享一个底层数组,那么即使是全局变量也无法修改了,大坑!!!

package mainimport "fmt"// 先用暴力算法写
// 要是这题的思路弄清楚,我觉得递归就入门了,学习一下func generateParenthesis(n int) []string {var current stringvar result = []string{}generateAll(&current, n*2, &result)//fmt.Println(result)return result
}func generateAll(current *string, n int, result *[]string) {if n == len(*current) {if valid(*current) {*result = append(*result, *current)//fmt.Println(result)}return}*current += "("generateAll(current, n, result)*current = (*current)[:len(*current)-1]*current += ")"generateAll(current, n, result)*current = (*current)[:len(*current)-1]
}func valid(str string) bool {balance := 0for i := 0; i < len(str); i++ {if string(str[i]) == "(" {balance++} else {balance--if balance < 0 {return false}}}return balance == 0
}func main() {ans := generateParenthesis(3)fmt.Println(ans)
}

package mainimport "fmt"// 回溯法
func generateParenthesis(n int) []string {var current stringvar result = []string{}generateAll(&current, n, &result, 0, 0)//fmt.Println(result)return result
}func generateAll(current *string, n int, result *[]string, open int, close int) {if len(*current) == 2*n {*result = append(*result, *current)return}if open < n {*current += "("generateAll(current, n, result, open+1, close)*current = (*current)[:len(*current)-1]}if close < open {*current += ")"generateAll(current, n, result, open, close+1)*current = (*current)[:len(*current)-1]}
}func main() {ans := generateParenthesis(3)fmt.Println(ans)
}

用了回溯时间快了两倍,剪枝还是重要的

2020/4/10

leetcode 151.翻转字符串里的单词_Go

这题用相关api做起来是很快的,既然可以直接写,用双端队列我觉得就有点得不偿失了,毕竟go中要用stack需要自己写

package mainimport ("fmt""strings""unicode"
)func reverseWords(s string) string {var ans stringslice := strings.FieldsFunc(s, unicode.IsSpace)for i := len(slice) - 1; i >= 0; i-- {ans += slice[i]if i > 0 {ans += " "}}return ans
}func main() {ans := "the sky is blue"fmt.Println(reverseWords(ans))
}

leetcode 面试题 01.06. 字符串压缩_Go

package mainimport ("fmt""strconv"
)// 掌握到了一个int转换成string的函数
func compressString(S string) string {if len(S) == 0 {return ""}var ans stringtemp := S[0]count := 0for i := 0; i < len(S); i++ {if S[i] != temp {ans += (string(temp) + strconv.Itoa(count))temp = S[i]count = 1} else {count++}}ans += (string(temp) + strconv.Itoa(count))if len(ans) >= len(S) {ans = S}return ans
}func main() {ans := "aabcccccaaa"fmt.Println(compressString(ans))
}

2020/4/11

leetcode 887.鸡蛋掉落_Go

说实话有点懵,就当学习dp了,之前看过dp,但也不至于这么难想公式

首先,第一步,直接阅读题解

第二步,解法一有二分,哦,想法一样

第三步,嗯?咋是这么写的,那没事了,我不会

这个视频讲的蛮好的:https://www.bilibili.com/video/BV1CJ411s7ud?from=search&seid=18159411945702423360

毕竟就算了解了dp怎么推到代码这个阶段水平要求还是高的

只用了DP的思路,超时的答案如下,还是很清晰易懂的

package mainimport ("fmt""math"
)func max(a, b int) int {if a >= b {return a}return b
}func min(a, b int) int {if a < b {return a}return b
}func superEggDrop(K int, N int) int {// init dp arrayDP := [101][10001]int{}for i := 0; i <= K; i++ {for j := 0; j <= N; j++ {DP[i][j] = math.MaxInt32}}for i := 0; i <= N; i++ {DP[0][i] = 0DP[1][i] = i}for i := 0; i <= K; i++ {DP[i][0] = 0}for k := 2; k <= K; k++ {for n := 1; n <= N; n++ {for i := 1; i <= n; i++ {DP[k][n] = min(DP[k][n], max(DP[k-1][i-1], DP[k][n-i])+1)}}}return DP[K][N]
}func main() {fmt.Println(superEggDrop(3, 14))
}

尝试一下优化

这里用到了题解中的单调性,真厉害啊,在第五层

package mainimport ("fmt""math"
)func max(a, b int) int {if a >= b {return a}return b
}func min(a, b int) int {if a < b {return a}return b
}func superEggDrop(K int, N int) int {// init dp arrayDP := [101][10001]int{}for i := 0; i <= K; i++ {for j := 0; j <= N; j++ {DP[i][j] = math.MaxInt32}}for i := 0; i <= N; i++ {DP[0][i] = 0DP[1][i] = i}for i := 0; i <= K; i++ {DP[i][0] = 0}for k := 2; k <= K; k++ {for n := 1; n <= N; n++ {// for i := 1; i <= n; i++ {//     DP[k][n] = min(DP[k][n], max(DP[k-1][i-1], DP[k][n-i])+1)// }// 二分搜索low, high := 1, nm := 0for low <= high {m = (high-low)/2 + lowx, y := DP[k-1][m-1], DP[k][n-m]if x > y {high = m - 1} else {low = m + 1}DP[k][n] = min(DP[k][n], max(x, y)+1)}}}return DP[K][N]
}func main() {fmt.Println(superEggDrop(3, 14))
}

终于搞定了,对dp的理解又加深了

2020/4/12

leetcode 面试题 16.03. 交点_Go

因为精度问题失败了

package mainimport ("fmt""math"
)// 这题完全不会,几何学一般性的面试也不会考吧,图像和游戏?
// 单纯因为好奇怎么做才看着题解学习了一下,这题其实感觉没什么必要
// 然后看到一堆数学直接放弃
// 只能用分类讨论了,还好昨天练了一下dp,今天用上了,怀疑官方就是这么考虑才出的题
func intersection(start1 []int, end1 []int, start2 []int, end2 []int) []float64 {if start1[0] > end1[0] {start1, end1 = end1, start1}if start2[0] > end2[0] {start2, end2 = end2, start2}// 两条垂直线if start1[0] == end1[0] && start2[0] == end2[0] {if start1[1] > end1[1] {start1, end1 = end1, start1}if start2[1] > end2[1] {start2, end2 = end2, start2}ans := twoVertical(start1, end1, start2, end2)return ans} else if start1[0] == end1[0] { // 一条垂线if start1[1] > end1[1] {start1, end1 = end1, start1}return oneVertical(start1, end1, start2, end2)} else if start2[0] == end2[0] {if start2[1] > end2[1] {start2, end2 = end2, start2}return oneVertical(start2, end2, start1, end1)}// 无垂直线return noVertical(start1, end1, start2, end2)
}func twoVertical(start1 []int, end1 []int, start2 []int, end2 []int) []float64 {ans := []float64{}if start1[0] != start2[0] {return ans}low, high := math.Max(float64(start1[1]), float64(start2[1])), math.Min(float64(end1[1]), float64(end2[1]))if low <= high {ans = []float64{float64(start1[0]), low}return ans}return ans
}func oneVertical(start1 []int, end1 []int, start2 []int, end2 []int) []float64 {ans := []float64{}if start1[0] < start2[0] || start1[0] > end2[0] {return ans}y := calY(start2, end2, start1[0])if y >= start1[1] && y <= end1[1] {ans = []float64{float64(start1[0]), float64(y)}return ans}return ans
}func noVertical(start1 []int, end1 []int, start2 []int, end2 []int) []float64 {ans := []float64{}interX1, interX2 := math.Max(float64(start1[0]), float64(start2[0])), math.Min(float64(end1[0]), float64(end2[0]))if interX1 > interX2 {return ans}left, right := interX1, interX2interY1Left := calY(start1, end1, int(left))interY2Left := calY(start2, end2, int(left))interY1Right := calY(start1, end1, int(right))interY2Right := calY(start2, end2, int(right))if interY1Left == interY2Left {ans = []float64{left, float64(interY1Left)}return ans}if interY1Right == interY2Right {ans = []float64{right, float64(interY2Right)}return ans}if (interY1Left-interY2Left)*(interY1Right-interY2Right) > 0 {return ans}// 二分,精度为给定的10^(-6)sign := -1if interY1Left > interY2Left {sign = 1}for right-left > math.Pow10(-6) {mid := (int(right) + int(left)) / 2y1 := calY(start1, end1, mid)y2 := calY(start2, end2, mid)if y1 == y2 {ans = []float64{float64(mid), float64(y1)}return ans}if (y1-y2)*sign > 0 {left = float64(mid)}right = float64(mid)}ans = []float64{left, right}return ans
}func calY(start []int, end []int, x int) int {slope := (end[1] - start[1]) / (end[0] - start[0])return slope*(x-start[0]) + start[1]
}func main() {start1, end1 := []int{0, 0}, []int{1, 0}start2, end2 := []int{1, 1}, []int{0, -1}fmt.Println(intersection(start1, end1, start2, end2))
}

用数学的做法做,我反正是学不来的,挂个答案记录一下,也没提交反正,慢慢学习

func intersection(start1 []int, end1 []int, start2 []int, end2 []int) []float64 {const eps = 1e-6sub := func(a, b []int) []int {c := make([]int, 2)c[0] = a[0] - b[0]c[1] = a[1] - b[1]return c}det := func(a, b []int) int { // 行列式或叉积return a[0]*b[1]-a[1]*b[0]}inline := func(s, v, p []int) bool { // 检测p是否在线段 p=s+vt 上 (0<=t<=1)i := 0if v[i]==0 { i = 1 }t := float64((p[i]-s[i])) / float64(v[i])if -eps <= t && t <= 1+eps { return true }return false}v1 := sub(end1, start1)v2 := sub(end2, start2)b := sub(start2, start1)denominator := det(v1, v2)ans := []float64{}if denominator == 0 { // 平行if det(v1, b) == 0 { // 共线tmp := [][]int{start1, end1, start2, end2}// 排序后第二个点为候选点sort.Slice(tmp, func(i, j int) bool {if tmp[i][0] < tmp[j][0] {return true} else if tmp[i][0]==tmp[j][0] && tmp[i][1]<tmp[j][1] {return true}return false})// 检测是否同时在两线段上if inline(start1, v1, tmp[1]) && inline(start2, v2, tmp[1]) {ans = []float64{float64(tmp[1][0]), float64(tmp[1][1])}}}} else { // 直线相交t1 := float64(det(b, v2)) / float64(denominator) // p=s1+v1*t1 (0<=t1<=1)t2 := -float64(det(v1, b)) / float64(denominator)if 0<=t1&&t1<=1 && 0<=t2&&t2<=1 { // 交点是否在线段上ans = []float64{float64(start1[0])+float64(v1[0])*t1, float64(start1[1])+float64(v1[1])*t1}}}return ans
}

2020/4/14

leetcode 455. 两数相加Ⅱ_Go

package mainimport ("container/list""fmt"
)/*** Definition for singly-linked list.* type ListNode struct {*     Val int*     Next *ListNode* }*/// ListNode struct
type ListNode struct {Val  intNext *ListNode
}// 逆序处理要想到栈,关键就是这点
// 之前看了container/list的库,立刻就派上用处了
// 这个我是直接模改的算法笔记上面C++的模板
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {stack1 := list.New()stack2 := list.New()for l1 != nil {stack1.PushFront(l1.Val)l1 = l1.Next}for l2 != nil {stack2.PushFront(l2.Val)l2 = l2.Next}p := l1carry := 0for stack1.Len() > 0 && stack2.Len() > 0 {val := stack1.Front().Value.(int) + stack2.Front().Value.(int) + carrycarry = 0if val > 9 {val -= 10carry = 1}node := &ListNode{Val:  val,Next: p,}p = nodestack1.Remove(stack1.Front())stack2.Remove(stack2.Front())}for stack1.Len() > 0 {val := stack1.Front().Value.(int) + carrycarry = 0if val > 9 {val -= 10carry = 1}node := &ListNode{Val:  val,Next: p,}p = nodestack1.Remove(stack1.Front())}for stack2.Len() > 0 {val := stack2.Front().Value.(int) + carrycarry = 0if val > 9 {val -= 10carry = 1}node := &ListNode{Val:  val,Next: p,}p = nodestack2.Remove(stack2.Front())}if carry > 0 {node := &ListNode{Val:  carry,Next: p,}p = node}return p
}func main() {l1 := &ListNode{7, nil}l1.Next = new(ListNode)l1.Next = &ListNode{2, nil}l1.Next.Next = new(ListNode)l1.Next.Next = &ListNode{4, nil}l1.Next.Next.Next = new(ListNode)l1.Next.Next.Next = &ListNode{3, nil}l2 := &ListNode{5, nil}l2.Next = new(ListNode)l2.Next = &ListNode{6, nil}l2.Next.Next = new(ListNode)l2.Next.Next = &ListNode{4, nil}ans := addTwoNumbers(l1, l2)for ans != nil {fmt.Println(ans.Val, "->")ans = ans.Next}fmt.Println("nil")
}

leetcode 53. 最大字序和_Go

package mainimport "fmt"// basic dp
func maxSubArray(nums []int) int {length := len(nums)dp := make([]int, length+1)ans := nums[0]for i := 1; i < length+1; i++ {dp[i] = max(dp[i-1]+nums[i-1], nums[i-1])if ans < dp[i] {ans = dp[i]}}return ans
}func max(a, b int) int {if a > b {return a}return b
}func main() {nums := []int{-1}fmt.Println(maxSubArray(nums))
}

2020/4/15

leetcode 542. 01矩阵_Go

package mainimport "fmt"// BFS
func updateMatrix(matrix [][]int) [][]int {wayx := [4]int{0, 0, 1, -1}wayy := [4]int{1, -1, 0, 0}queue := [][]int{}row := len(matrix)col := len(matrix[0])for i := 0; i < row; i++ {for j := 0; j < col; j++ {if matrix[i][j] == 0 {queue = append(queue, []int{i, j})} else {// 未访问过的1设置为-1matrix[i][j] = -1}}}for len(queue) != 0 {top := queue[0]queue = queue[1:]x, y := top[0], top[1]for i := 0; i < 4; i++ {newX := x + wayx[i]newY := y + wayy[i]if newX >= 0 && newX < row && newY >= 0 && newY < col && matrix[newX][newY] == -1 {matrix[newX][newY] = matrix[x][y] + 1queue = append(queue, []int{newX, newY})}}}return matrix
}func main() {matrix := [][]int{{0, 0, 0},{0, 1, 0},{0, 0, 0}}fmt.Println(updateMatrix(matrix))
}

2020/4/16

leetcode 52. 合并区间_Go

package mainimport ("fmt""sort"
)func merge(intervals [][]int) [][]int {if len(intervals) <= 0 {return nil}// 利用匿名函数排序sort.Slice(intervals, func(i, j int) bool {return intervals[i][0] < intervals[j][0]})ans := [][]int{}ans = append(ans, intervals[0])for i := 1; i < len(intervals); i++ {right := ans[len(ans)-1]temp := intervals[i]if temp[0] > right[1] {ans = append(ans, temp)continue} else {if temp[1] > right[1] {right[1] = temp[1]}}}return ans
}func main() {intervals := [][]int{{1, 3}, {2, 6}, {8, 10}, {15, 18}}fmt.Println(merge(intervals))
}

2020/4/17

leetcode 55. 跳跃游戏_Go

package mainimport "fmt"func canJump(nums []int) bool {length := len(nums)max := 0if length <= 1 {return true}for i := 0; i < length; i++ {// 当前位置可到达if i <= max {if max < nums[i]+i {max = nums[i] + i}if max >= length-1 {return true}}}return false
}func main() {nums := []int{3, 2, 1, 0, 4}fmt.Println(canJump(nums))
}

2020/4/18

leetcode 11. 盛水最多的容器_Go

package mainimport ("fmt"
)// 第一个反应就是two pointers
// 从两侧往中间遍历,一次o(n)即可
func maxArea(height []int) int {length := len(height)left, right := 0, length-1ans := 0for left < right {tempAns := (right - left) * min(height[left], height[right])if ans < tempAns {ans = tempAns}if height[left] < height[right] {left++} else {right--}}return ans
}func min(a, b int) int {if a < b {return a}return b
}func main() {height := []int{2, 3, 4, 5, 18, 17, 6}fmt.Println(maxArea(height))
}

leetcode 104. 二叉树的最大深度_C++

我们从本地的测试集开始写才是真正的写好一道题哦

不觉得构造一颗树更有收获么,开始重新回忆C++

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string>
#include <string.h>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>using namespace std;
// 104. 二叉树的最大深度
// 最大深度用DFS处理每个节点左右子树的深度即可struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};int maxDepth(TreeNode* root){if(root==NULL) return 0;int leftHeight=maxDepth(root->left);int rightHeight=maxDepth(root->right);return max(leftHeight,rightHeight)+1;
}TreeNode* newNode(int v){TreeNode* node = new TreeNode(v);
}TreeNode* CreateTree(int a[],int n){if (n==0){return NULL;}TreeNode* root=new TreeNode(a[0]);queue<TreeNode*> q;q.push(root);int num=1;while(num<n){TreeNode* top=q.front();q.pop();if(top->left==NULL){if(a[num]!=-1){top->left=new TreeNode(a[num]);q.push(top->left);}num++;}if(num==n){break;}if(top->right==NULL){if(a[num]!=-1){top->right=new TreeNode(a[num]);q.push(top->right);}num++;}}return root;
}int main()
{int n;scanf("%d",&n); // 7int a[n]; // 3 9 20 -1 -1 15 7for(int i=0;i<n;i++){  // -1 represents NULLscanf("%d",&a[i]);//printf("%d\n",a[i]);}TreeNode* root=CreateTree(a,n);//printf("%d\n",root->val);//printf("%d\n",root->right->right->val);int ans=maxDepth(root);printf("%d\n",ans);return 0;
}

leetcode 101. 对称二叉树_C++

第一反应是懵的,看了一下官方题解,有个思路很重要

  1. 它们的两个根结点具有相同的值。
  2. 每个树的右子树都与另一个树的左子树镜像对称

什么我也能这么拆解题目就好了呢

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string>
#include <string.h>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>using namespace std;
// 101. 对称二叉树struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};bool isMirror(TreeNode* a,TreeNode* b){if(a==nullptr && b==nullptr) return true;if(a==nullptr || b==nullptr) return false;return ((a->val == b->val)&& isMirror(a->left, b->right)&& isMirror(b->left, a->right));
}bool isSymmetric(TreeNode* root) {if(root==NULL){return true;}else{return isMirror(root->left,root->right);}
}TreeNode* newNode(int v){TreeNode* node = new TreeNode(v);
}TreeNode* CreateTree(int a[],int n){if (n==0){return NULL;}TreeNode* root=new TreeNode(a[0]);queue<TreeNode*> q;q.push(root);int num=1;while(num<n){TreeNode* top=q.front();q.pop();if(top->left==NULL){if(a[num]!=-1){top->left=new TreeNode(a[num]);q.push(top->left);}num++;}if(num==n){break;}if(top->right==NULL){if(a[num]!=-1){top->right=new TreeNode(a[num]);q.push(top->right);}num++;}}return root;
}int main()
{int n;scanf("%d",&n); // 7int a[n]; // 1 2 2 3 4 4 3for(int i=0;i<n;i++){  // -1 represents NULLscanf("%d",&a[i]);//printf("%d\n",a[i]);}TreeNode* root=CreateTree(a,n);bool ans=isSymmetric(root);printf("%d\n",ans);return 0;
}

2020/4/19 && 20

leetcode 455. 分发饼干_C++

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string>
#include <string.h>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>using namespace std;
// 455. 分发饼干
int findContentChildren(vector<int>& g, vector<int>& s) {sort(g.begin(),g.end());sort(s.begin(),s.end());int gIndex=0;int num=0;for(int i=0;i<s.size();i++){if(gIndex==g.size()) break;if(g[gIndex]<=s[i]){num++;gIndex++;}}return num;
}int main()
{vector<int> g,s;int n,m; // 3 2int temp;scanf("%d%d",&n,&m);for(int i=0;i<n;i++){ // 1 2 3scanf("%d",&temp);g.push_back(temp);}for(int i=0;i<m;i++){ // 1 1scanf("%d",&temp);s.push_back(temp);}int ans=findContentChildren(g,s);printf("%d\n",ans);return 0;
}

leetcode 股票题C++

通解,花里胡哨的情况有一堆,打算采用暴力枚举dp状态的方式想把所有的题目都做了,然后再改进

所有题目的状态无非就是三类,天数(n);允许交易的最大次数(K);是否持有股票(0/1)

总状态开一个三维的dp数组能应付一切情况

leetcode 121. 买卖股票的最佳时机_C++

K==1,这个状态对dp没有什么影响了,成功降维省空间

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string>
#include <string.h>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>using namespace std;
// 121. 买卖股票的最佳时机
int maxProfit(vector<int>& prices) {int len=prices.size();if(len==0) return 0;int dp[100000][2];// 处理边界dp[0][0]=0;dp[0][1]=-prices[0];for(int i=1;i<len;i++){dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]);dp[i][1]=max(dp[i-1][1],-prices[i]);}return dp[len-1][0];
}int main()
{int n,temp;scanf("%d",&n); // 6vector<int> prices;for(int i=0;i<n;i++){ // 7 1 5 3 6 4scanf("%d",&temp);prices.push_back(temp);}int ans=maxProfit(prices);printf("%d\n",ans);return 0;
}
leetcode 122. 买卖股票的最佳时机 II_C++

这次K变成了正无穷大

只展示maxProfit函数

我们推理一下状态转移公式

dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1] + prices[i])
dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i])
如果 k 为正无穷,那么就可以认为 k 和 k - 1 是一样的(很关键的一步)
这样就可以再次降维,丢弃k的那个维度
// 122. 买卖股票的最佳时机 II
int maxProfit2(vector<int>& prices) {int len=prices.size();if(len==0) return 0;int dp[100000][2];// 处理边界dp[0][0]=0;dp[0][1]=-prices[0];for(int i=1;i<len;i++){dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]);dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i]);}return dp[len-1][0];
}
leetcode 123. 买卖股票的最佳时机 III_C++

仔细分析和上面的题目基本一样了,k为2

但是我实在是忍受不了0代表第一天了,就改了下下标

// 123. 买卖股票的最佳时机 III
// dp[i][j][k]表示第i天,进行了j次交易,当前状态为k时的最大利润
int maxProfit3(vector<int>& prices) {const int inf = 1 << 30;int len=prices.size();int dp[100001][3][2];// 处理边界for(int i=0;i<=len;i++){dp[i][0][0]=0;dp[i][0][1]=-inf;}for(int i=1;i<=2;i++){dp[0][i][0]=-inf;dp[0][i][1]=-inf;}// 状态转移方程for(int i=1;i<=len;i++){for(int j=0;j<=2;j++){dp[i][j][0]=max(dp[i-1][j][0],dp[i-1][j][1]+prices[i-1]);if(j!=0)dp[i][j][1]=max(dp[i-1][j][1],dp[i-1][j-1][0]-prices[i-1]);}}return max(max(dp[len][0][0], dp[len][1][0]), dp[len][2][0]);
}
leetcode 188. 买卖股票的最佳时机IV_C++

这题只不过k变成了我们输入的值

然后做了一下发现出了个问题,样例中k可以为1000000000,我们直接开dp数组会超过可用的内存空间

所以我们需要对K>len/2的情况单独讨论

那么K上限是无穷大,对于本次问题没有约束力了,那么我们直接降维即可

// 188. 买卖股票的最佳时机 IV
int maxProfit(int k, vector<int>& prices) {if(k==0) return 0;const int inf = 1 << 30;int len=prices.size();if(len<2) return 0;int K=k;if (K>len/2){int maxpro=0;int dp2[len][2];dp2[0][0] = 0;dp2[0][1] = -prices[0];for (int i = 1; i < len; i++){dp2[i][0] = max(dp2[i - 1][0], dp2[i - 1][1] + prices[i]);dp2[i][1] = max(dp2[i - 1][1], dp2[i - 1][0] - prices[i]);maxpro = max(max(dp2[i][0], dp2[i][1]), maxpro);}return maxpro;}int dp[len+1][K+1][2];// 处理边界for(int i=0;i<=len;i++){dp[i][0][0]=0;dp[i][0][1]=-inf;}for(int i=1;i<=K;i++){dp[0][i][0]=-inf;dp[0][i][1]=-inf;}// 状态转移方程for(int i=1;i<=len;i++){for(int j=0;j<=K;j++){dp[i][j][0]=max(dp[i-1][j][0],dp[i-1][j][1]+prices[i-1]);if(j!=0)dp[i][j][1]=max(dp[i-1][j][1],dp[i-1][j-1][0]-prices[i-1]);}}int ans=dp[len][0][0];for(int i=1;i<=K;i++){ans=max(ans,dp[len][i][0]);}return ans;
}
leetcode 309. 最佳买卖股票时机含冷冻期_C++

可以看到对K没有限制,又可以降维了

// 309. 最佳买卖股票时机含冷冻期
int maxProfit(vector<int>& prices) {int n=prices.size();const int inf = 1 << 30;if(n<=1) return 0;int dp[n+1][2];dp[0][1]=-inf;dp[0][0]=0;dp[1][0]=0;dp[1][1]=-prices[0];for(int i=2;i<=n;i++){dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i-1]);dp[i][1]=max(dp[i-1][1],dp[i-2][0]-prices[i-1]);}return dp[n][0];
}
leetcode 714. 买卖股票的最佳时机含手续费_C++

easy,改改我们的参数就好了

// 714. 买卖股票的最佳时机含手续费
int maxProfit(vector<int>& prices, int fee) {int n=prices.size();const int inf = 1 << 30;if(n<=1) return 0;int dp[n+1][2];dp[0][1]=-inf;dp[0][0]=0;for(int i=1;i<=n;i++){dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i-1]);dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i-1]-fee);}return dp[n][0];
}

leetcode 200. 岛屿数量_Go

一开始用的BFS,提交之后发现很慢,for嵌套的太多了,就用DFS又写了一次,快了些

package mainimport "fmt"// BFS
func numIslands(grid [][]byte) int {wayX := []int{0, 0, 1, -1}wayY := []int{1, -1, 0, 0}row := len(grid)if row == 0 {return 0}col := len(grid[0])num := 0for i := 0; i < row; i++ {for j := 0; j < col; j++ {if grid[i][j] == '1' {grid[i][j] = '2'num++queue := [][]int{}queue = append(queue, []int{i, j})for len(queue) != 0 {top := queue[0]queue = queue[1:]x, y := top[0], top[1]for z := 0; z < 4; z++ {newX := x + wayX[z]newY := y + wayY[z]if newX >= 0 && newX < row && newY >= 0 && newY < col && grid[newX][newY] == '1' {grid[newX][newY] = '2'queue = append(queue, []int{newX, newY})}}}}}}return num
}// DFS
func numIslands2(grid [][]byte) int {row := len(grid)if row == 0 {return 0}col := len(grid[0])num := 0for i := 0; i < row; i++ {for j := 0; j < col; j++ {if grid[i][j] == '1' {num++dfs(grid, i, j)}}}return num
}func dfs(grid [][]byte, r int, c int) {nr := len(grid)nc := len(grid[0])grid[r][c] = '0'if r-1 >= 0 && grid[r-1][c] == '1' {dfs(grid, r-1, c)}if r+1 < nr && grid[r+1][c] == '1' {dfs(grid, r+1, c)}if c-1 >= 0 && grid[r][c-1] == '1' {dfs(grid, r, c-1)}if c+1 < nc && grid[r][c+1] == '1' {dfs(grid, r, c+1)}
}func main() {grid := [][]byte{{'1', '1', '0', '0', '0'},{'1', '1', '0', '0', '0'},{'0', '0', '1', '0', '0'},{'0', '0', '0', '1', '1'}}ans := numIslands2(grid)fmt.Println(ans)
}

并查集暂时不看了,有些遗忘,而且总觉得使用率不高

2020/4/21

leetcode 1248. 统计优美子数组_Go

package mainimport "fmt"// 奇数为1, 偶数为0, 子区间和为k的种类数
// 前缀和
// 有多少个sum-k,就有多少个k
func numberOfSubarrays(nums []int, k int) int {length := len(nums)for i := 0; i < length; i++ {if nums[i]&1 == 1 {nums[i] = 1} else {nums[i] = 0}}mp := make(map[int]int)sum, ans := 0, 0mp[0] = 1for i := 1; i <= length; i++ {sum += nums[i-1]x := sum - kans += mp[x]mp[sum]++}return ans
}func main() {nums := []int{2, 2, 2, 1, 2, 2, 1, 2, 2, 2}fmt.Println(numberOfSubarrays(nums, 2))
}

2020/4/22

leetcode 199. 二叉树的右视图_Go

package mainimport "fmt"// TreeNode struct
type TreeNode struct {Val   intLeft  *TreeNodeRight *TreeNode
}func newNode(val int) *TreeNode {return &TreeNode{Val:   val,Left:  nil,Right: nil,}
}func creatTree(a []int) *TreeNode {length := len(a)if length == 0 {return nil}node := newNode(a[0])queue := []*TreeNode{}queue = append(queue, node)num := 1for num < length {top := queue[0]queue = queue[1:]if top.Left == nil {if a[num] != -1 {top.Left = newNode(a[num])queue = append(queue, top.Left)}num++}if num == length {break}if top.Right == nil {if a[num] != -1 {top.Right = newNode(a[num])queue = append(queue, top.Right)}num++}}return node
}// 层序遍历
func rightSideView(root *TreeNode) []int {if root == nil {return []int{}}ans := []int{}queue := []*TreeNode{}queue = append(queue, root)for len(queue) != 0 {size := len(queue)ans = append(ans, queue[0].Val)for i := 0; i < size; i++ {top := queue[0]queue = queue[1:]if top.Right != nil {queue = append(queue, top.Right)}if top.Left != nil {queue = append(queue, top.Left)}}}return ans
}func main() {input := []int{1, 2, 3, -1, 5, -1, 4}root := creatTree(input)//fmt.Println(root)ans := rightSideView(root)fmt.Println(ans)
}

2020/4/23

leetcode 面试题 08.11. 硬币_Go

package mainimport ("fmt""math"
)// 暴力数学算法
func waysToChange(n int) int {mod := int(math.Pow10(9)) + 7ans := 0for i := 0; i <= n/25; i++ {x := n - i*25y := x/5 + 1z := x/10 + 1ans += (y - z + 1) * zans %= mod}return ans
}func main() {fmt.Println(waysToChange(5))
}

2020/4/24

leetcode 面试题51. 数组中的逆序对_Go

package mainimport "fmt"// 第一反应双循环,但必定超时
// 归并排序
func reversePairs(nums []int) int {length := len(nums)if length < 2 {return 0}newNums := make([]int, length)temp := make([]int, length)copy(newNums, nums)return mergeSort(newNums, 0, length-1, temp)
}func mergeSort(newNums []int, left int, right int, temp []int) int {if right == left {return 0}mid := left + (right-left)/2leftPairs := mergeSort(newNums, left, mid, temp)rightPairs := mergeSort(newNums, mid+1, right, temp)if newNums[mid] <= newNums[mid+1] {return leftPairs + rightPairs}cross := crossPairs(newNums, left, mid, right, temp)return cross + leftPairs + rightPairs
}func crossPairs(newNums []int, left int, mid int, right int, temp []int) int {for i := left; i <= right; i++ {temp[i] = newNums[i]}i, j := left, mid+1count := 0for k := left; k <= right; k++ {if i == mid+1 {newNums[k] = temp[j]j++} else if j == right+1 {newNums[k] = temp[i]i++} else if temp[i] <= temp[j] {newNums[k] = temp[i]i++} else {newNums[k] = temp[j]j++count += (mid - i + 1)}}return count
}func main() {nums := []int{7, 5, 6, 4}fmt.Println(reversePairs(nums))
}

2020/4/25 && 26

背包九讲_C++

题目来自ACWing

0/1背包问题
#include <iostream>
#include <stdio.h>
using namespace std;
// ACWing 0/1 packageconst int n=1010;
int N,V;
int v[n]; // volume
int w[n]; // weight
int f[n][n];
int F[n];// 基础二维状态
/*f[i][j] 根据前i件物品,且手头背包空间为j的时候,做出的最优选择1.若不选择第i件物品 f[i][j]=f[i-1][j]2.若选择了第i件物品 f[i][j]=f[i-1][j-v[i]]+w[i]f[i][j]=max{1,2}边界:f[0][j]=0
*/
int basicTwo(){scanf("%d%d",&N,&V);for(int i=1;i<=N;i++){scanf("%d%d",&v[i],&w[i]);}for(int i=1;i<=N;i++){for(int j=0;j<=V;j++){f[i][j]=f[i-1][j];if(j>=v[i]){f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i]);}}}int ans=0;for(int i=0;i<=V;i++){ans=max(ans,f[N][i]);}return ans;
}// 降维
/*每个f[i][j]只和上个f[i-1]的状态相关,没有必要记录全局的f[i][j]滚动数组为何要逆序循环可以画个表格观察
*/
int basicOne(){scanf("%d%d",&N,&V);for(int i=1;i<=N;i++){scanf("%d%d",&v[i],&w[i]);}for(int i=1;i<=N;i++){for(int j=V;j>=v[i];j--){F[j]=max(F[j],F[j-v[i]]+w[i]);}}int ans=0;ans=F[V];return ans;
}int main()
{int ans=basicOne();printf("%d\n",ans);return 0;
}
完全背包问题
#include <iostream>
#include <stdio.h>
using namespace std;
// ACWing 完全背包问题
/*更进了一步,0/1背包每个物品只有选和不选完全背包可以放无穷次,在不超过背包限制的情况下那么在前i个物品,体积剩余j时,选择放k个物品,最基本的状态转移方程就需要三个for循环当然在一定条件下可以降维,慢慢分析
*/const int n=1010;
int N,V;
int v[n]; // volume
int w[n]; // weight
int f[n][n];
int F[n];// 基础的三维状态
/*f[i][j][k]f[i][j]=max(f[i-1][j-k*v[i]]+w[i]*k)  0<=k<=j/v[i]f[i][j]=max(f[i-1][j],f[i-1][j-k*v[i]]+w[i]*k)  1<=k<=j/v[i]遗憾的是,这么些会超时,so sad
*/
int basicThree(){scanf("%d%d",&N,&V);for(int i=1;i<=N;i++){scanf("%d%d",&v[i],&w[i]);}for(int i=1;i<=N;i++){for(int j=0;j<=V;j++){for(int k=0;k<=(j/v[i]);k++){f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+k*w[i]);}}}int ans=f[N][V];return ans;
}/*优化写法f[i][j]-max{f[i-1][j],f[i][j-v[i]]+w[i]}推导过程就不写了比较一下f[i-1][j-k*v[i]]+k*w[i] 与 f[i][j-v]即可
*/
int better(){scanf("%d%d",&N,&V);for(int i=1;i<=N;i++){scanf("%d%d",&v[i],&w[i]);}for(int i=1;i<=N;i++){for(int j=0;j<=V;j++){f[i][j]=f[i-1][j];if(v[i]<=j){f[i][j]=max(f[i][j],f[i][j-v[i]]+w[i]);}}}int ans=f[N][V];return ans;
}/*进一步优化就很简单了,和0/1背包的优化方式一样
*/int best(){scanf("%d%d",&N,&V);for(int i=1;i<=N;i++){scanf("%d%d",&v[i],&w[i]);}for(int i=1;i<=N;i++){for(int j=V;j>=v[i];j--){F[j]=max(F[j],F[j-v[i]]+w[i]);}}int ans=F[V];return ans;
}int main()
{int ans=best();printf("%d\n",ans);return 0;
}

leetcode 46. 全排列_Go

package mainimport "fmt"// 不会回溯法,直接看题解学习
func permute(nums []int) [][]int {ans := [][]int{}length := len(nums)if length == 0 {return ans}path := []int{}used := make([]bool, length)dfs(nums, length, path, used, &ans)return ans
}func dfs(nums []int, count int, path []int, used []bool, ans *[][]int) {if len(path) == count {*ans = append(*ans, path)return}for i := 0; i < count; i++ {if used[i] != false {continue}used[i] = truex := append(path, nums[i])dfs(nums, count, x, used, ans)used[i] = false}
}func main() {nums := []int{1, 2, 3}fmt.Println(permute(nums))
}

leetcode 23. 合并K个排序链表_Go

package mainimport "fmt"// ListNode : Definition for singly-linked list.
type ListNode struct {Val  intNext *ListNode
}// 最朴素的想法就是合并k次
func mergeKLists(lists []*ListNode) *ListNode {k := len(lists)var ans *ListNodefor i := 0; i < k; i++ {ans = mergeLists(ans, lists[i])}return ans
}func mergeLists(a *ListNode, b *ListNode) *ListNode {head := ListNode{}tail := &headif a != nil && b == nil {return a} else if a == nil && b != nil {return b} else if a != nil && b != nil {for a != nil && b != nil {if a.Val < b.Val {tail.Next = aa = a.Next} else {tail.Next = bb = b.Next}tail = tail.Next}}if a != nil {tail.Next = a} else {tail.Next = b}return head.Next
}func main() {l1 := &ListNode{}l1.Val = 1l1.Next = &ListNode{}l1.Next.Val = 4l1.Next.Next = &ListNode{}l1.Next.Next.Val = 5l2 := &ListNode{}l2.Val = 1l2.Next = &ListNode{}l2.Next.Val = 3l2.Next.Next = &ListNode{}l2.Next.Next.Val = 4l3 := &ListNode{}l3.Val = 2l3.Next = &ListNode{}l3.Next.Val = 6list := []*ListNode{l1, l2, l3}ans := mergeKLists(list)fmt.Println(ans.Val)
}

想要优化很容易想到就是直接类似于归并排序来提速

2020/4/27

leetcode 33. 搜索旋转排序数组_Go

package mainimport "fmt"// 时间复杂度怎么讲到o(logn)是个问题
// 想到的就是二分
// 但具体怎么操作还是走一步看一步的
func search(nums []int, target int) int {n := len(nums)if n == 0 {return -1}if n == 1 {if target == nums[0] {return 0}return -1}left, right := 0, n-1for left <= right {mid := left + (right-left)/2if nums[mid] == target {return mid}if nums[left] <= nums[mid] {if nums[left] <= target && target < nums[mid] {right = mid - 1} else {left = mid + 1}} else {if nums[mid] < target && target <= nums[right] {left = mid + 1} else {right = mid - 1}}}return -1
}func main() {nums := []int{4, 5, 6, 7, 0, 1, 2}fmt.Println(search(nums, 0))
}

2020/4/28

今天主要配置了一下vscode下C++的配置,做点实验

leetcode 1. 两数之和_C++

#include<stdio.h>
#include<vector>using namespace std;
// brute forcevector<int> twoSum(vector<int>& nums, int target) {vector<int> ans;int n=nums.size();for(int i=0;i<n;i++){for(int j=i+1;j<n;j++){if(nums[i]+nums[j]==target){ans.push_back(i);ans.push_back(j);}}}return ans;
}int main(){int a[4]={2, 7, 11, 15};vector<int> b(a,a+4);vector<int> ans=twoSum(b,9);printf("%d %d\n",ans[0],ans[1]);return 0;
}

#include<stdio.h>
#include<vector>
#include<map>using namespace std;
// 说是说hashTable,我觉得map更方便vector<int> twoSum(vector<int>& nums, int target) {vector<int> ans;map<int,int> mp;int n=nums.size();for(int i=0;i<n;i++){int rest=target-nums[i];if(mp.find(rest)!=mp.end()){map<int,int>::iterator it=mp.find(rest);ans.push_back(it->second);ans.push_back(i);}mp[nums[i]]=i;}return ans;
}int main(){int a[4]={2, 7, 11, 15};vector<int> b(a,a+4);vector<int> ans=twoSum(b,9);printf("%d %d\n",ans[0],ans[1]);return 0;return 0;
}

leetcode 面试题56 - I. 数组中数字出现的次数_Go

package mainimport "fmt"// 时间复杂度是o(n)还是容易的,空间复杂度要是O(1),我们就不能hashTable了
// 直接看题解了,做法真的想不到
// 分组异或,位运算
func singleNumbers(nums []int) []int {temp := 0n := len(nums)for i := 0; i < n; i++ {temp ^= nums[i]}a, b := 0, 0mask := 1// find the last 1for mask&temp == 0 {mask <<= 1}temp = 0for i := 0; i < n; i++ {if mask&nums[i] == 0 {a ^= nums[i]} else {b ^= nums[i]}}return []int{a, b}
}func main() {nums := []int{4, 1, 4, 6}fmt.Println(singleNumbers(nums))
}

2020/4/29

leetcode 1095. 山脉数组中查找目标值_Go

package mainimport "fmt"// MountainArray Struct
type MountainArray struct {array []intcount int
}func create(nums []int) *MountainArray {return &MountainArray{array: nums,count: len(nums),}
}
func (p *MountainArray) get(index int) int {if index >= p.count {return -1}return p.array[index]
}
func (p *MountainArray) length() int {return p.count
}func findInMountainArray(target int, mountainArr *MountainArray) int {if mountainArr.length() == 0 {return -1}if mountainArr.length() == 1 {if mountainArr.get(0) == target {return 0}return -1}// find peak indexleft, right := 0, mountainArr.length()-1mid := 0for left < right {mid = left + (right-left)/2if mountainArr.get(mid) <= mountainArr.get(mid+1) {left = mid + 1} else {right = mid}}peakIndex := 0if mountainArr.get(mid) < mountainArr.get(mid+1) {peakIndex = mid + 1} else {peakIndex = mid}// find targetleft, right = 0, peakIndexfor left < right {mid = left + (right-left)/2if mountainArr.get(mid) == target {return mid}if mountainArr.get(mid) < target {left = mid + 1} else {right = mid}}if right > 0 {mid = right}if mountainArr.get(mid) == target {return mid}if mid+1 < mountainArr.length() {if mountainArr.get(mid+1) == target {return mid + 1}}left, right = peakIndex, mountainArr.length()-1for left < right {mid = left + (right-left)/2if mountainArr.get(mid) == target {return mid}if mountainArr.get(mid) < target {right = mid} else {left = mid + 1}}if right > 0 {mid = right}if mountainArr.get(mid) == target {return mid}if mid+1 < mountainArr.length() {if mountainArr.get(mid+1) == target {return mid + 1}}return -1
}func main() {array := []int{0, 5, 3, 1}nums := create(array)fmt.Println(nums)fmt.Println(findInMountainArray(1, nums))
}

2020/4/30
四月收官了,也做了不少算法题,最近压力也有一些,还算满意吧

leetcode 202. 快乐数_Go

package main
​
import "fmt"
​
// 4月最后一天,leetcode希望我们快乐
func isHappy(n int) bool {mp := make(map[int]int, 10)temp := 0for n != 1 {temp = 0for n != 0 {temp = (n%10)*(n%10) + tempn /= 10}n = temp_, ok := mp[n]if ok {return false}mp[n] = 1}return true
}
​
func main() {fmt.Println(isHappy(19))
}
​
快慢指针法,挂个官方的吧,很好理解```go
func isHappy(n int) bool {slow, fast := n, step(n)for fast != 1 && slow != fast {slow = step(slow)fast = step(step(fast))}return fast == 1
}
​
func step(n int) int {sum := 0for n > 0 {sum += (n%10) * (n%10)n = n/10}return sum
}
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/happy-number/solution/kuai-le-shu-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

算法唯手熟尔4月(PAT剩余清单 or leetcode)---希望可以日更相关推荐

  1. 算法唯手熟尔(PAT剩余清单 or leetcode)---希望可以日更

    文章目录 2020/3/5 PAT A1119_C 2020/3/6 PAT A1123_C PAT A1115_C PAT A1114_C leetcode 206. 反转链表_C leetcode ...

  2. 樊登读书搞定读后感_读书笔记/读后感《读懂一本书,樊登读书法》——无他唯手熟尔...

    当我们在生活及工作中遇到问题的时候,通常会请教同事或者上网搜索解决方法,但是我们忽略了另外一个解决问题的途径,那就是通过阅读书籍积累知识.为什么大家并不习惯于阅读书籍呢,那是因为大家认为眼前遇到问题最 ...

  3. 136. 只出现一次的数字【我亦无他唯手熟尔】

    136. 只出现一次的数字 136. 只出现一次的数字 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素.说明:你的算法应该具有线性时间复杂度. 你 ...

  4. 438. 找到字符串中所有字母异位词【我亦无他唯手熟尔】

    438. 找到字符串中所有字母异位词 438. 找到字符串中所有字母异位词 题解 官方 438. 找到字符串中所有字母异位词 难度 中等 给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 ...

  5. 237. 删除链表中的节点【我亦无他唯手熟尔】

    237. 删除链表中的节点 请编写一个函数,用于 删除单链表中某个特定节点 .在设计函数时需要注意,你无法访问链表的头节点 head ,只能直接访问 要被删除的节点 . 题目数据保证需要删除的节点 不 ...

  6. 编程思想:我亦无他,唯手熟尔

    目录 一.编程思想三大定理 二.编程思想四大特性 三.做到高内聚,低耦合 (一)内聚 (二)耦合 一.编程思想三大定理 (1)思路分析,化繁为简:将需求拆成多个步骤实现,先完成基本功能和大致框架,在往 ...

  7. 1929. 数组串联【我亦无他唯手熟尔】

    1929. 数组串联 题目 题解 题目 给你一个长度为 n 的整数数组 nums .请你构建一个长度为 2n 的答案数组 ans ,数组下标 从 0 开始计数 ,对于所有 0 <= i < ...

  8. 786. 第 K 个最小的素数分数【我亦无他唯手熟尔】

    786. 第 K 个最小的素数分数 786. 第 K 个最小的素数分数 题解 786. 第 K 个最小的素数分数 难度 困难 给你一个按递增顺序排序的数组 arr 和一个整数 k .数组 arr 由 ...

  9. 卖油翁 欧阳修 无他,但手熟尔

    陈康肃公尧咨善射,当世无双,公亦以此自矜.尝射于家圃,有卖油翁释担而立,睨之,久而不去.见其发矢十中八九,但微颔之. 康肃问曰:"汝亦知射乎?吾射不亦精乎?"翁曰:"无他 ...

最新文章

  1. 【渝粤教育】广东开放大学 标准化理论与方法 形成性考核 (53)
  2. var s=+newDate();的用法,表示对应的时间截
  3. python提取图片文字视频教学_用Python提取视频中的图片
  4. Nand flash驱动的编写与移植
  5. 爷青结是什么意思,爷青回是什么意思,爷青结和爷青回是什么梗
  6. At the beginning of the month, the doctor introduced in the article “iOS
  7. webkit的编译(r76498)
  8. outlook 表格使用技巧
  9. windows系统vbs脚本 提取文件夹中的所有文件名
  10. html如何调整打印区域,怎么调整excel打印区域_教你调整excel打印区域的方法-系统城...
  11. Unity 之圆环算法
  12. 使用XMLHttpRequest
  13. 史上最详细JavaScript视频教程
  14. QCSPCChart SPC控制图工具软件是面向对象的工具包
  15. 空间数据平台SDP - 医疗药品门店数字化营销
  16. 微信支付接口详细步骤
  17. 清北复交人浙南 计算机交叉学科项目大盘点
  18. 除了搜岛国老师的作品,以图搜图还有什么骚操作?
  19. 标准nvmexpress控制器驱动下载_NVM Express控制器驱动程序
  20. 【Linux学习笔记】关于ubuntu开机菜单栏和任务栏不见了的有效解决方法

热门文章

  1. mysql中timeStamp转成yyyy-MM-dd hh:mm
  2. 您需要配置好的 Python 2 SDK 来渲染 Epydoc docstring的解决方案
  3. 高校浴室预约小程序的设计与实现
  4. Zabbix6.0使用教程 (一)—zabbix新增功能介绍2
  5. Android面试题--HashMap原理分析
  6. filter: grayscale(1); | 网页变灰
  7. 大数据项目 --- 数据采集项目
  8. 全国计算机等级考试二级c真题201903,计算机等级考试题库,二级C++试题
  9. 中国高校“产学研”模式探讨——迎接个性化产学研模式
  10. 【Carsim Simulink自动驾驶仿真】基于MPC的速度控制