从现在开始,争取每天写一道题目,再将题目的解答思路分析出来,将每一类型的题归纳到一起去,这一篇主要写动态规划,将不断进行更新,欢迎一起探讨思路。
total
38
https://leetcode-cn.com/problems/ba-shu-zu-pai-cheng-zui-xiao-de-shu-lcof/
输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
在这里插入代码片
https://leetcode-cn.com/problems/bu-ke-pai-zhong-de-shun-zi-lcof/
从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。
func isStraight(nums []int) bool {
sort.Ints(nums)
var zero int
for i:=0;i<=len(nums)-2;i++{
if nums[i]==0{
zero++
}else{
cap:=nums[i+1]-nums[i] - 1
if cap > 0{
zero = zero - cap
if zero<0{
return false
}
}else if cap<0{
return false
}
}
}
return true
}
https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/
地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?
func getSUmForK(i,j int)int{
var sum int
for i>0{
sum = sum + i%10
i = i/10
}
for j>0{
sum = sum + j%10
j = j/10
}
return sum
}
//考虑矩阵的特性,右下角的值是矩阵的最大
//由于采用的是位数相加,所以无法找出数学规律,需要进行搜索
func innerMove(res *int,i,j,m,n,k int,path[][]bool){
//上可达,满足小于k,没有走到过
if i-1>=0&&getSUmForK(i-1,j)<=k&&path[i-1][j]==false{
*res = *res + 1
path[i-1][j] = true
innerMove(res,i-1,j,m,n,k,path)
}
//下
if i+1<m&&getSUmForK(i+1,j)<=k&&path[i+1][j]==false{
*res = *res + 1
path[i+1][j] = true
innerMove(res,i+1,j,m,n,k,path)
}
//左
if j-1>=0&&getSUmForK(i,j-1)<=k&&path[i][j-1]==false{
*res = *res + 1
path[i][j-1] = true
innerMove(res,i,j-1,m,n,k,path)
}
//右
if j+1<n&&getSUmForK(i,j+1)<=k&&path[i][j+1]==false{
*res = *res + 1
path[i][j+1] = true
innerMove(res,i,j+1,m,n,k,path)
}
}
func movingCount(m int, n int, k int) int {
path:=make([][]bool,m)
for i:=0;i<m;i++{
path[i] = make([]bool,n)
}
var res int
path[0][0] = true
res = 1
innerMove(&res,0,0,m,n,k,path)
return res
}
//采用暴力解决方法,遍历数组查看是否有符合的内容
func exist(board [][]byte, word string) bool {
if len(word) < 1 || len(board)==0{
return false
}
m:=len(board)
n:=len(board[0])
for i:=0;i<len(board);i++{
for j:=0;j<len(board[i]);j++{
if word[0] == board[i][j]{
if len(word)==1{
return true
}
path:=make([][]bool,m)
for i:=0;i<m;i++{
path[i] = make([]bool,n)
}
path[i][j] = true
if innerExist(board,word[1:],i,j,m,n,path){
return true
}
}
}
}
return false
}
func innerExist(board [][]byte,word string,i,j,m,n int,path [][]bool)bool{
//上边可以走,上面没有走过,且相等
if i-1>=0 && path[i-1][j]==false && word[0]==board[i-1][j]{
//满足条件
if len(word)==1{
return true
}else{
path[i-1][j] = true
if innerExist(board,word[1:],i-1,j,m,n,path){
return true
}
path[i-1][j] = false
}
}
//下边可以走
if i+1<m && path[i+1][j]==false && word[0]==board[i+1][j]{
//满足条件
if len(word)==1{
return true
}else{
path[i+1][j] = true
if innerExist(board,word[1:],i+1,j,m,n,path){
return true
}
path[i+1][j] = false
}
}
//左边
if j-1>=0 && path[i][j-1]==false && word[0]==board[i][j-1]{
//满足条件
if len(word)==1{
return true
}else{
path[i][j-1] = true
if innerExist(board,word[1:],i,j-1,m,n,path){
return true
}
path[i][j-1] = false
}
}
//右边
if j+1<n && path[i][j+1]==false && word[0]==board[i][j+1]{
//满足条件
if len(word)==1{
return true
}else{
path[i][j+1] = true
if innerExist(board,word[1:],i,j+1,m,n,path){
return true
}
path[i][j+1] = false
}
}
return false
}
https://leetcode-cn.com/problems/er-cha-shu-zhong-he-wei-mou-yi-zhi-de-lu-jing-lcof/
func innerPathSum(root *TreeNode, now,target int,arr []int,res *[][]int){
if root==nil{
return
}
if root.Val + now ==target&& root.Left==nil&&root.Right==nil{
arr = append(arr,root.Val)
result:=make([]int,0,len(arr))
for i:=0;i<len(arr);i++{
result = append(result,arr[i])
}
*res = append(*res,result)
return
}
if root.Left!=nil||root.Right!=nil {
arr = append(arr,root.Val)
innerPathSum(root.Left,now+root.Val,target,arr,res)
innerPathSum(root.Right,now+root.Val,target,arr,res)
}
}
func pathSum(root *TreeNode, target int) [][]int {
if root==nil{
return nil
}
nowtarget:=root.Val
if nowtarget==target&& root.Left==nil&&root.Right==nil{
return [][]int{{target}}
}
var res [][]int
innerPathSum(root.Left,nowtarget,target,[]int{nowtarget},&res)
innerPathSum(root.Right,nowtarget,target,[]int{nowtarget},&res)
return res
}
https://leetcode-cn.com/problems/wildcard-matching/submissions/
给定一个字符串 (s) 和一个字符模式 § ,实现一个支持 ‘?’ 和 ‘’ 的通配符匹配。
‘?’ 可以匹配任何单个字符。
'’ 可以匹配任意字符串(包括空字符串)。
两个字符串完全匹配才算匹配成功。
说明:
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *。
一开始想的是递归
1.针对p的p1位?符号一定可以匹配一个s的坐标s1,isMatch(s[s1:],p[p1:]) = isMatch(s[s1+1:],p[p1+1:])
2.针对p的p1位符号可以匹配多个任意值或者是不匹配,所以isMatch(s[s1:],p[p1:]) = isMatch(s[s1+1:],p[p1:]) ||isMatch(s[s1:],p[p1+1:])
但是这样做有一个问题是时间复杂度的问题,递归的时间复杂度等于递归的层数递归的操作次数
如果遇到过个的字符串,很容易超时
转换思路,使用动态规划
涉及dp[i][j]为长度i的s与长度j的p的匹配结果
如果s[i]p[j]或者p[j]‘?’,那么dp[i][j] = dp[i-1][j-1]
如果p[j]==’’
那么p[j]不起作用dp[i][j] = dp[i][j-1]
那么p[j]起作用,dp[i][j] = dp[i-1][j]
匹配结果dp[i][j] = dp[i][j-1] || dp[i-1][j]
再根据原则初始化我们的原本dp数组,最终可以得到代码如下
通配符匹配,针对’?'的场景,
func isMatch(s string, p string) bool {
slength,plength:=len(s),len(p)
dp:=make([][]bool,slength+1,slength+1)
for i:=0;i<=slength;i++{
dp[i] = make([]bool,plength+1,plength+1)
}
//如果s为空,p为空,那么可以匹配
dp[0][0] = true
//如果s为空,p只有全是*才可以匹配,注意p的坐标从0开始,而我们的dp是从1开始,所以需要i+1,下面为了防止越界也需要i-1
for i:=0;i<plength;i++{
if p[i]=='*'{
dp[0][i+1] = true
}else{
break
}
}
for i:=1;i<=slength;i++{
for j:=1;j<=plength;j++{
if s[i-1]==p[j-1]||p[j-1]=='?'{
//i,j相等,则结果与i-1,j-1保持一致
dp[i][j] = dp[i-1][j-1]
}else if p[j-1]=='*'{
//p[j]==*,有两个可能性,1用上了dp[i-1][j],2没用上dp[i][j-1]
dp[i][j] = dp[i-1][j]||dp[i][j-1]
}
}
}
return dp[slength][plength]
}
https://leetcode-cn.com/problems/unique-paths/
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?
//思路:机器人每次只能向右,或者向下走
//得出公式 dp[i][j] = dp[i-1][j] + dp[i][j-1]
//i,j表达用户走到i行,j列的地方有多少方式
//最终能走的步数就是dp[m][n]
func uniquePaths(m int, n int) int {
dp:=make([][]int,m+1)
for i:=0;i<m+1;i++{
dp[i] = make([]int,n+1)
}
//初始化机器人走路方式,机器人往右边直走,和往下面直走,都只有一种方式
for i:=1;i<=m; i++{
dp[i][1] = 1
}
for j:=1;j<=n;j++{
dp[1][j] = 1
}
for i:=2;i<=m;i++{
for j:=2;j<=n;j++{
dp[i][j] = dp[i-1][j] + dp[i][j-1]
}
}
return dp[m][n]
}
//时间复杂度 O(mxn)
//空间复杂度 O(mxn)
https://leetcode-cn.com/problems/unique-paths-ii/
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
//思路:机器人每次只能向右,或者向下走
//得出公式 dp[i][j] = dp[i-1][j] + dp[i][j-1]
//i,j表达用户走到i行,j列的地方有多少方式
//最终能走的步数就是dp[m][n]
//由于数组中有障碍物,障碍物的坐标不可到达 dp[i][j] = 0
func uniquePathsWithObstacles(obstacleGrid [][]int) int {
if len(obstacleGrid) == 0 {
return 0
}
m := len(obstacleGrid)
n := len(obstacleGrid[0])
dp := make([][]int, m)
for i := 0; i < m; i++ {
dp[i] = make([]int, n)
}
//初始化路径
for i:=0;i<m;i++{
if obstacleGrid[i][0]==0{
dp[i][0] = 1
}else{
break
}
}
for j:=0;j<n;j++{
if obstacleGrid[0][j]==0{
dp[0][j] = 1
}else{
break
}
}
for i := 1; i < m; i++ {
for j := 1; j < n; j++ {
if obstacleGrid[i][j] == 1 {
dp[i][j] = 0
} else {
dp[i][j] = dp[i-1][j] + dp[i][j-1]
}
}
}
return dp[m-1][n-1]
}
给你一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
//动态规划
//dp[i]表示i坐标下最长连续有效括号的数目
//当s[i]==')'有如下情况
//1.s[i-1]=='(',那么dp[i] = dp[i-2] +2
//2.s[i-1]==')',那么要回溯进行查找
//上一个连续有效括号最大数 可能与上上一个连续有效括号数连起来 加上本次数目
//dp[i] = dp[i-1] + dp[i-dp[i-1]-2] + 2
func max(a, b int) int {
if a > b {
return a
}
return b
}
func longestValidParentheses(s string) int {
maxAns := 0
dp := make([]int, len(s))
for i := 1; i < len(s); i++ {
if s[i] == ')' {
if s[i-1] == '(' {
if i >= 2 {
dp[i] = dp[i - 2] + 2
} else {
dp[i] = 2
}
} else if i - dp[i - 1] > 0 && s[i - dp[i - 1] - 1] == '(' {
if i - dp[i - 1] >= 2 {
dp[i] = dp[i - 1] + dp[i - dp[i - 1] - 2] + 2
} else {
dp[i] = dp[i - 1] + 2
}
}
maxAns = max(maxAns, dp[i])
}
}
return maxAns
}
https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/
func fib(n int) int {
if n<=1{
return n
}
dp:=[]int64{0,1}
for i:=2;i<=n;i++{
dp = append(dp,(dp[i-1] + dp[i-2])%1000000007)
}
return int(dp[n])
}
https://leetcode-cn.com/problems/qing-wa-tiao-tai-jie-wen-ti-lcof/submissions/
// 青蛙跳 1 1
// 2 [1 1] [2]
// 3 [1][1 1] [1][1] [2][1]
//青蛙跳到n级台阶的次数等于 跳到n-1级再加n-2级
func numWays(n int) int {
dp:=[]int {1,1,2}
for i:=3;i<=n;i++{
dp = append(dp,(dp[i-1] + dp[i-2])%1000000007)
}
return dp[n]
}
时间复杂度O(N)空间复杂度O(1)
//买卖股票一次能获得的最大利润
func maxProfit(prices []int) int {
if len(prices) < 1 {
return 0
}
in := prices[0] //买入价格
var maxpro int
for i := 1; i < len(prices); i++ {
if prices[i] > in && prices[i]-in > maxpro {
maxpro = prices[i] - in
} else if prices[i] < in{
in = prices[i]
}
}
return maxpro
}
时间复杂度O(N)空间复杂度O(1)
func maxSubArray(nums []int) int {
if len(nums)<1{
return 0
}
max:=nums[0]
var now int
for i:=0;i<len(nums);i++{
now = now + nums[i]
if now>max{
max = now
}
if now<0{
now = 0
}
}
return max
}
https://leetcode-cn.com/problems/li-wu-de-zui-da-jie-zhi-lcof/
func max(a, b int) int {
if a > b {
return a
}
return b
}
//连续最大子数组和
//dp[i][j] 到达i,j位置的礼物最大值
//dp[i][j] = max(dp[i-1][j] + grid[i][j],dp[i][j-1]+grid[i][j])
func maxValue(grid [][]int) int {
if len(grid)<1{
return 0
}
m:=len(grid)
n:=len(grid[0])
dp:=make([][]int,m)
for i:=0;i<m;i++{
dp[i] = make([]int,n)
}
dp[0][0] = grid[0][0]
//初始化第一行
for i:=1;i<n;i++{
dp[0][i] = grid[0][i] + dp[0][i-1]
}
//初始化第一列
for j:=1;j<m;j++{
dp[j][0] = grid[j][0] + dp[j-1][0]
}
for i:=1;i<m;i++{
for j:=1;j<n;j++{
dp[i][j] = max(dp[i-1][j],dp[i][j-1]) + grid[i][j]
}
}
return dp[m-1][n-1]
}
https://leetcode-cn.com/problems/ba-shu-zi-fan-yi-cheng-zi-fu-chuan-lcof/
//翻译数字到英文
//dp[i] 表示到达数字i位最多有几种翻译
//如果 num的i-1到i 可以组成单词
//dp[i] = dp[i-1] + dp[i-2]
//否则
//dp[i] = dp[i-1]
func translateNum(num int) int {
dp:=make([]int,0,0)
dp = append(dp,1)
str:=strconv.Itoa(num)
if len(str)<=1{
return dp[0]
}
sed,_:=strconv.Atoi(str[:2])
if sed<26{
dp = append(dp,2)
}else{
dp = append(dp,1)
}
for i:=2;i<len(str);i++{
sed,_:=strconv.Atoi(str[i-1:i+1])
if sed<26&&str[i-1]!='0'{
dp = append(dp,dp[i-1]+dp[i-2])
}else{
dp = append(dp,dp[i-1])
}
}
return dp[len(str)-1]
}
https://leetcode-cn.com/problems/zui-chang-bu-han-zhong-fu-zi-fu-de-zi-zi-fu-chuan-lcof/
//最长不重复子字符串
//dp[i]表示到i位置为止最大不重复
//lastindex为一个map[uint8]int,表示值在上一个的index+1(避免0值)
//需要构造等式
//若是原先没有遇见这个值lastmap[s[i]]==0 dp[i] = dp[i-1] + 1 lastmap[s[i]] = i+1
//否则说明这个值出现过 lastmap[s[i]]!=0
//从lastindex获取上一个出现的坐标index=lastmap[s[i]]-1,从dp[i-1]获取上一个值的最长子序列长度length
//如果i - length >index 说明中间有断开的,那么这个新出现的值就是新值 那么dp[i] = dp[i-1] + 1
//否则i-length<=index-1 说明中间没有断开的或者中间的中场子序列中已经包含了s[i],此时对i点最长 dp[i] = i-index
func lengthOfLongestSubstring(s string) int {
if len(s)<1{
return 0
}
var max int
dp:=make([]int,len(s))
lastindex:=make(map[uint8]int)
dp[0] = 1
lastindex[s[0]] = 1
max = 1
for i:=1;i<len(s);i++ {
if lastindex[s[i]] == 0 {
dp[i] = dp[i-1] + 1
lastindex[s[i]] = i + 1
}else{
length:=dp[i-1]
index:=lastindex[s[i]] - 1
if i-length>index{
dp[i] = dp[i-1] + 1
}else{
dp[i] = i - index
}
lastindex[s[i]] = i + 1
}
if max <dp[i]{
max = dp[i]
}
}
return max
}
https://leetcode-cn.com/problems/permutations/
给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
示例 1:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
//给定的数组是不重复的要求返回所有可能的全排列
//此时脑子里第一反应是多岔树,以1,2,3,4为例子
// 1
// 2 3 4
// 4 3 4 2 2 3
// 3 4 2 4 3 2
//以此类推使用递归
//时间复杂度是O(N)*O(N!)
func innerpermute(surnums []int,nums []int,res *[][]int){
if len(nums)==1{
surnums = append(surnums,nums[0])
*res = append(*res,surnums)
return
}else{
for i:=0;i<len(nums);i++{
tmp:=surnums
arr:=make([]int,len(nums))
copy(arr,nums)//这样做的目的是append操作再做合并的时候会修改元数据造成数据不一致
tmp = append(tmp,arr[i])
tmpnums := append(arr[0:i],arr[i+1:]...)
innerpermute(tmp,tmpnums,res)
}
}
}
func permute(nums []int) [][]int {
res:=make([][]int,0,0)
innerpermute(nil,nums,&res)
return res
}
数字 n代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且
有效的 括号组合。
func innergenerate(str string, left, right int, resmap map[string]bool) {
if left == 0 {
for i := 0; i < right; i++ {
str = str + ")"
}
resmap[str] = true
return
}
if left > 0 {
tmpleft := left - 1
tmpstr := str + "("
innergenerate(tmpstr, tmpleft, right, resmap)
}
if right > 0 && left < right {
tmpright := right - 1
tmpstr := str + ")"
innergenerate(tmpstr, left, tmpright, resmap)
}
}
//括号生成
func generateParenthesis(n int) []string {
resmap := make(map[string]bool)
var res []string
innergenerate("", n, n, resmap)
for k, _ := range resmap {
res = append(res, k)
}
return res
}
给定一个正整数数组 A,如果 A 的某个子数组中不同整数的个数恰好为 K,则称 A 的这个连续、不一定不同的子数组为好子数组。
(例如,[1,2,3,1,2] 中有 3 个不同的整数:1,2,以及 3。)
返回 A 中好子数组的数目。
https://leetcode-cn.com/problems/subarrays-with-k-different-integers/solution/cong-zui-jian-dan-de-wen-ti-yi-bu-bu-tuo-7f4v/
//如果问 A 中由最多 K 个不同整数组成的子数组的个数
func distinctMaxNum(nums []int, k int) int {
n := len(nums)
left := 0
right := 0
counter := make(map[int]int)
distinct := 0
res := 0
for right < n {
if counter[nums[right]] == 0 {
distinct++
}
counter[nums[right]] = counter[nums[right]] + 1
for distinct > k {
counter[nums[left]] = counter[nums[left]] - 1
if counter[nums[left]] == 0 {
distinct = distinct - 1
}
left = left + 1
}
res += right - left + 1
right = right + 1
}
return res
}
//同样的思想,使用双指针,原本双指针只求最大区间,现在的双指针要求满足条件的所有区间
//已经知道最多k个不同整数组成子数组个数的详细解释
//恰好由 K 个不同整数的子数组的个数 = 最多由 K 个不同整数的子数组的个数 - 最多由 K - 1 个不同整数的子数组的个数
func subarraysWithKDistinct(nums []int, k int) int {
return distinctMaxNum(nums,k)-distinctMaxNum(nums,k-1)
}
https://leetcode-cn.com/problems/find-the-duplicate-number/submissions/
func findDuplicate(nums []int) int {
n := len(nums)
ans := 0
bit_max := 31
for ((n-1) >> bit_max) == 0 {
bit_max--
}
for bit := 0; bit <= bit_max; bit++ {
x, y := 0, 0
for i := 0; i < n; i++ {
if (nums[i] & (1 << bit)) > 0 {
x++
}
if i >= 1 && (i & (1 << bit)) > 0 {
y++
}
}
if x > y {
ans |= 1 << bit
}
}
return ans
}
func diffWaysToCompute(input string) []int {
// 如果是数字,直接返回
if isDigit(input) {
tmp, _ := strconv.Atoi(input)
return []int{tmp}
}
// 空切片
var res []int
// 遍历字符串
for index, c := range input {
tmpC := string(c)
if tmpC == "+" || tmpC == "-" || tmpC == "*" {
// 如果是运算符,则计算左右两边的算式
left := diffWaysToCompute(input[:index])
right := diffWaysToCompute(input[index+1:])
for _, leftNum := range left {
for _, rightNum := range right {
var addNum int
if tmpC == "+" {
addNum = leftNum + rightNum
} else if tmpC == "-" {
addNum = leftNum - rightNum
} else {
addNum = leftNum * rightNum
}
res = append(res, addNum)
}
}
}
}
return res
}
// 判断是否为全数字
func isDigit(input string) bool {
_, err := strconv.Atoi(input)
if err != nil {
return false
}
return true
}
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func getKthFromEnd(head *ListNode, k int) *ListNode {
tmp:=head
var res *ListNode
z:=1
for tmp!=nil{
if z==k{
res = head
z++
}else if z<k{
z++
} else{
res = res.Next
}
tmp = tmp.Next
}
return res
}
https://leetcode-cn.com/problems/diao-zheng-shu-zu-shun-xu-shi-qi-shu-wei-yu-ou-shu-qian-mian-lcof/
func exchange(nums []int) []int {
ouindex:=-1
for i:=0;i<len(nums);i++{
if nums[i]%2==0&&ouindex==-1{
//偶数,要获取第一个偶数出现的坐标
ouindex = i
}else if nums[i]%2!=0{
if ouindex>-1{
//第一个奇数出来以后偶数已经在前面了
//将奇数与偶数呼唤
tmp:=nums[ouindex]
nums[ouindex] = nums[i]
nums[i] = tmp
ouindex = ouindex+1
}
}
}
return nums
}
https://leetcode-cn.com/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/submissions/
type CQueue struct {
stack1, stack2 *list.List
}
func Constructor() CQueue {
return CQueue{
stack1: list.New(),
stack2: list.New(),
}
}
func (this *CQueue) AppendTail(value int) {
this.stack1.PushBack(value)
}
func (this *CQueue) DeleteHead() int {
// 如果第二个栈为空
if this.stack2.Len() == 0 {
for this.stack1.Len() > 0 {
this.stack2.PushBack(this.stack1.Remove(this.stack1.Back()))
}
}
if this.stack2.Len() != 0 {
e := this.stack2.Back()
this.stack2.Remove(e)
return e.Value.(int)
}
return -1
}
type MinStack struct {
arr []int
minarr []int
}
/** initialize your data structure here. */
func Constructor() MinStack {
return MinStack{
}
}
func (this *MinStack) Push(x int) {
this.arr = append(this.arr,x)
if len(this.minarr) == 0{
this.minarr = append(this.minarr,x)
}else if x<=this.minarr[len(this.minarr)-1]{
this.minarr = append(this.minarr,x)
}
}
func (this *MinStack) Pop() {
pnum:=this.arr[len(this.arr)-1]
this.arr = this.arr[:len(this.arr)-1]
if this.minarr[len(this.minarr)-1]==pnum{
this.minarr = this.minarr[:len(this.minarr)-1]
}
}
func (this *MinStack) Top() int {
return this.arr[len(this.arr)-1]
}
func (this *MinStack) Min() int {
return this.minarr[len(this.minarr)-1]
}
从头到尾打印
https://leetcode-cn.com/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof/
反转链表
https://leetcode-cn.com/problems/fan-zhuan-lian-biao-lcof/
复杂链表复制
https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/
引申思考
1.回溯算法
2.go语言的append原理
3.分治算法
美团的技术博客我经常有看,所以对他们技术映像很好,今天刚好有一道比较有意思的题
小美是美团仓库的管理员,她会根据单据的要求按顺序取出仓库中的货物,每取出一件货物后会把剩余货物重新堆放,使得自己方便查找。已知货物入库的时候是按顺序堆放在一起的。如果小美取出其中一件货物,则会把货物所在的一堆物品以取出的货物为界分成两堆,这样可以保证货物局部的顺序不变。
已知货物最初是按 1~n 的顺序堆放的,每件货物的重量为 w[i] ,小美会根据单据依次不放回的取出货物。请问根据上述操作,小美每取出一件货物之后,重量和最大的一堆货物重量是多少?
https://leetcode-cn.com/problems/TJZLyC/
思路:使用逆转思维,把拿东西的次序倒过来看成是放东西,查看放入的左右是否有合并集,如果有,就合并得出值,记得顺序要倒叙,且最后一次拿出的值是0
func Warehouse(length int,arr []int,put []int){
sumarr:=make([]int,length)
var resarr []int
resarr = append(resarr,0)
for i:=length-1;i>=1;i--{
index:=put[i]-1
var res int
if index>0&&sumarr[index-1]!=0{
res = res + sumarr[index-1]
}
if index<length-1&&sumarr[index+1]!=0{
res = res + sumarr[index+1]
}
res = res + arr[index]
tmp:=index-1
tmp2:=index+1
for tmp>=0&&sumarr[tmp]!=0{
sumarr[tmp] = res
tmp--
}
for tmp2<length&&sumarr[tmp2]!=0{
sumarr[tmp2] = res
tmp2++
}
sumarr[index] = res
resarr = append([]int{res},resarr...)
}
fmt.Println(resarr)
}
https://leetcode-cn.com/problems/zai-pai-xu-shu-zu-zhong-cha-zhao-shu-zi-lcof/
//1 2 3 3 4 5 6
func searchLeft(nums []int,target int)int{
start:=0
end:=len(nums)-1
for start<=end{
mid:=(start+end)/2
if nums[mid]<target{
//左边界在右边
start = mid + 1
}else if nums[mid]>=target{
//左边界在左边
end = mid - 1
}
}
return end
}
func searchRight(nums []int,target int)int{
start:=0
end:=len(nums)-1
for start<=end{
mid:=(start+end)/2
if nums[mid]>target{
//右边界在左边
end = mid -1
}else if nums[mid]<=target{
//右边界在右边
start = mid+1
}
}
return start
}
//统计目标在排序数组中出现的次数
//已知排序数组查询,第一个想到二分,需要找到左边界和右边界
func search(nums []int, target int) int {
return searchRight(nums,target) - searchLeft(nums,target) -1
}
//排序数组中的搜索问题,首先想到 二分法
//mid:=(start+end)/2
//当nums[i]==i说明 i以前全部都符合没有空缺 start = mid+1
//当nums[i]!=i说明左边有空缺,end = mid -1
func missingNumber(nums []int) int {
start := 0
end:=len(nums)-1
for start<=end{
mid:=(start+end)/2
if nums[mid]==mid{
start = mid+1
}else{
end = mid - 1
}
}
return start
}
https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/
//首先数组是有序的,第一个想到二分查找,需要找到旋转的点的特征
//左边一定大于右边,直到左边小于右边
func minArray(numbers []int) int {
start:=0
end:=len(numbers)-1
for start < end{
mid := (start+end)/2
if numbers[mid]>numbers[end]{
// 4 0 1 1 1
//说明临界点在右边
start = mid + 1
}else if numbers[mid]<numbers[end]{
// 2 3 4 0 1
//临界点在左边
end = mid
}else {
end = end - 1
}
}
return numbers[end]
}
https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
func findNumberIn2DArray(matrix [][]int, target int) bool {
var n,m int
n = len(matrix)
if n>=1{
m = len(matrix[0])
}
var i,j int
i = 0
j = m-1
for i<n&&j>=0{
if matrix[i][j]<target{
i++
}else if matrix[i][j]>target{
j--
}else{
return true
}
}
return false
}
从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。
https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-lcof/
func levelOrder(root *TreeNode) []int {
if root==nil{
return nil
}
var arr []int
treeNodes:=make([]*TreeNode,0,0)
treeNodes = append(treeNodes,root)
for len(treeNodes)>0{
var tmpTreeNodes []*TreeNode
for i:=0;i<len(treeNodes);i++{
arr = append(arr,treeNodes[i].Val)
if treeNodes[i].Left!=nil{
tmpTreeNodes = append(tmpTreeNodes,treeNodes[i].Left)
}
if treeNodes[i].Right!=nil{
tmpTreeNodes = append(tmpTreeNodes,treeNodes[i].Right)
}
}
treeNodes = tmpTreeNodes
}
return arr
}
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-ii-lcof/
func levelOrderV2(root *TreeNode) [][]int {
if root==nil{
return nil
}
var arr [][]int
treeNodes:=make([]*TreeNode,0,0)
treeNodes = append(treeNodes,root)
for len(treeNodes)>0{
var tmpTreeNodes []*TreeNode
var tmparr []int
for i:=0;i<len(treeNodes);i++{
tmparr = append(tmparr,treeNodes[i].Val)
if treeNodes[i].Left!=nil{
tmpTreeNodes = append(tmpTreeNodes,treeNodes[i].Left)
}
if treeNodes[i].Right!=nil{
tmpTreeNodes = append(tmpTreeNodes,treeNodes[i].Right)
}
arr = append(arr,tmparr)
}
treeNodes = tmpTreeNodes
}
return arr
}
请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。
https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-iii-lcof/
func levelOrder(root *TreeNode) [][]int {
if root==nil{
return nil
}
var arr [][]int
treeNodes:=make([]*TreeNode,0,0)
treeNodes = append(treeNodes,root)
level:=1
for len(treeNodes)>0{
var tmpTreeNodes []*TreeNode
var tmparr []int
for i:=0;i<len(treeNodes);i++{
if level%2!=0{
tmparr = append(tmparr,treeNodes[i].Val)
}else{
tmparr = append([]int{treeNodes[i].Val},tmparr...)
}
if treeNodes[i].Left!=nil{
tmpTreeNodes = append(tmpTreeNodes,treeNodes[i].Left)
}
if treeNodes[i].Right!=nil{
tmpTreeNodes = append(tmpTreeNodes,treeNodes[i].Right)
}
}
level++
arr = append(arr,tmparr)
treeNodes = tmpTreeNodes
}
return arr
}
输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)
B是A的子结构, 即 A中有出现和B相同的结构和节点值。
https://leetcode-cn.com/problems/shu-de-zi-jie-gou-lcof/
func isInnerEqual(node *TreeNode,subnode *TreeNode)bool{
if subnode==nil{
return true
}
if node==nil{
return false
}
if subnode.Val == node.Val{
return isInnerEqual(node.Left,subnode.Left)&&isInnerEqual(node.Right,subnode.Right)
}
return false
}
func isSubStructure(A *TreeNode, B *TreeNode) bool {
if A==nil||B==nil{
return false
}
var issub bool
treeNodes:=make([]*TreeNode,0,0)
treeNodes = append(treeNodes,A)
for len(treeNodes)>0&&issub==false{
var tmpTreeNodes []*TreeNode
for _,v:=range treeNodes{
if v.Val==B.Val{
issub = isInnerEqual(v.Left,B.Left)&&isInnerEqual(v.Right,B.Right)
if issub{
return issub
}
}
if v.Left!=nil{
tmpTreeNodes = append(tmpTreeNodes,v.Left)
}
if v.Right!=nil{
t. mpTreeNodes = append(tmpTreeNodes,v.Right)
}
}
treeNodes = tmpTreeNodes
}
return issub
}
func exchangeNode(node *TreeNode){
left:=node.Left
right:=node.Right
node.Right = left
node.Left = right
}
func mirrorTree(root *TreeNode) *TreeNode {
if root==nil{
return nil
}
treeNodes:=make([]*TreeNode,0,0)
treeNodes = append(treeNodes,root)
for len(treeNodes)!=0{
tmpTreeNodes:=make([]*TreeNode,0,0)
for i:=0;i<len(treeNodes);i++{
if treeNodes[i]==nil{
continue
}
tmpTreeNodes = append(tmpTreeNodes,treeNodes[i].Left)
tmpTreeNodes = append(tmpTreeNodes,treeNodes[i].Right)
exchangeNode(treeNodes[i])
}
treeNodes = tmpTreeNodes
}
return root
}
func isDuichengArr(arr []string)bool{
if len(arr)%2!=0{
return false
}
start:=0
end:=len(arr)-1
for start<end{
if arr[start]!=arr[end]{
return false
}
start++
end--
}
return true
}
func levelOrderv3(root *TreeNode) [][]string {
if root==nil{
return nil
}
var arr [][]string
treeNodes:=make([]*TreeNode,0,0)
treeNodes = append(treeNodes,root)
for len(treeNodes)>0{
var tmpTreeNodes []*TreeNode
var tmparr []string
for i:=0;i<len(treeNodes);i++{
if treeNodes[i]==nil{
tmparr = append(tmparr,"")
continue
}
sval:=strconv.Itoa(treeNodes[i].Val)
tmparr = append(tmparr,sval)
tmpTreeNodes = append(tmpTreeNodes,treeNodes[i].Left)
tmpTreeNodes = append(tmpTreeNodes,treeNodes[i].Right)
}
arr = append(arr,tmparr)
treeNodes = tmpTreeNodes
}
return arr
}
//遍历left
//遍历right
//两个数组相等则相等
func isSymmetric(root *TreeNode) bool {
arr:=levelOrderv3(root)
for i:=1;i<len(arr);i++{
if !isDuichengArr(arr[i]){
return false
}
}
return true
}