🔥 LeetCode 热题 HOT 100---每日更新(前50)

402 阅读14分钟

1. 两数之和

给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。

数组中可能含有重复元素,如出现两个整数相等,也可以视作递增序列的一种特殊情况。

思路

  • 本题中寻找使得x+y=target的x和y,为了减少循环的次数和快速找到目标值,可以通过map解决。
  • 创建map,对于每一个x,查找map[target-x]是否存在。

示例1

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1]

示例2

输入: nums = [3,2,4], target = 6
输出: [1,2]

解法

func twoSum(nums []int, target int) []int {
    hashMap:=map[int]int{}
    for i:=0;i<len(nums);i++{
        if index,ok:=hashMap[target-nums[i]];ok{
            return []int{i,index}
        }
        hashMap[nums[i]]=i
    }
    return []int{}
}

2. 两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

思路

  • 逐位计算l1和l2的和,并与进位index相加,如n1+n2+index。则当前位的值为(n1+n2+index)%10,进位为(n1+n2+index)/10

示例1

输入: l1 = [2,4,3], l2 = [5,6,4]
输出: [7,0,8]
解释: 342 + 465 = 807.

示例2

输入: l1 = [0], l2 = [0]
输出: [0]

示例3

输入: l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出: [8,9,9,9,0,0,0,1]

解法

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
    p1,p2:=l1,l2
    newHead:=&ListNode{}
    index:=0
    node:=newHead
    for p1!=nil || p2!=nil || index!=0{
        temp:=&ListNode{}
        a:=0
        if p1!=nil{
            a=a+p1.Val
            p1=p1.Next
        }
        if p2!=nil{
            a=a+p2.Val
            p2=p2.Next
        }
        temp.Val=(a+index)%10
        index=(a+index)/10
        node.Next=temp
        node=temp
    }
    return newHead.Next
}

3. 无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

思路

  • “不含有重复”这个字眼想到使用map解决。
  • 使用左右指针,如果右指针的数字和左指针的相同,则删除左指针对象,左指针左移,注意的是此刻右指针不动,将右指针放入map。

示例1

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例2

输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例3

输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

解法

func lengthOfLongestSubstring(s string) int {
    hashMap:=map[byte]bool{}
    maxValue:=0
    left:=0
    for i:=0;i<len(s);{
        if _,ok:=hashMap[s[i]];!ok{
            hashMap[s[i]]=true
            maxValue=max(maxValue,i-left+1)
            i++
        }else {
            delete(hashMap,s[left])
            left++
        } 
    }
    return maxValue
}

func max(a,b int)int{
    if a>b{
        return a
    }
    return b
}

4. 寻找两个正序数组的中位数

给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。

算法的时间复杂度应该为 O(log (m+n)) 。

示例1

输入: nums1 = [1,3], nums2 = [2]
输出: 2.00000
解释: 合并数组 = [1,2,3] ,中位数 2

示例2

输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5

解法

func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
    nums1=append(nums1,nums2...)
    sort.Ints(nums1)
    if len(nums1)%2==0{
        return float64(nums1[len(nums1)/2-1]+nums1[len(nums1)/2])/2.0
    }
    return float64(nums1[len(nums1)/2])
}

5. 最长回文子串

给你一个字符串 s,找到 s 中最长的回文子串。

算法的时间复杂度应该为 O(log (m+n)) 。

思路

  • 暴力,双层循环解决,每次移动判断是否为回文子串。

示例1

输入: s = "babad"
输出: "bab"
解释: "aba" 同样是符合题意的答案。

示例2

输入: s = "cbbd"
输出: "bb"

解法

func longestPalindrome(s string) string {
    if len(s)<=1{
        return s
    }
    maxValue:=0
    res:=""
    for i:=0;i<len(s)-1;i++{
        for j:=i;j<len(s);j++{
            if check(s,i,j){
                if j-i+1>=maxValue{
                    maxValue=j-i+1
                    res=s[i:j+1]
                }
            }
        }
    }
    return res
}

func max(a,b int)int{
    if a>b{
        return a
    }
    return b
}

func check(s string,left int,right int)bool{
    for left<right{
        if s[left]!=s[right]{
            return false
        }
        left++
        right--
    }
    return true
}

6. Z 字形变换

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。

比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:

P   A   H   N
A P L S I I G
Y   I   R

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。

请你实现这个将字符串进行指定行数变换的函数:

string convert(string s, int numRows);

思路

示例1

输入: s = "PAYPALISHIRING", numRows = 3
输出: "PAHNAPLSIIGYIR"

示例2

输入:s = "PAYPALISHIRING", numRows = 4
输出:"PINALSIGYAHRPI"
解释:
P     I    N
A   L S  I G
Y A   H R
P     I

解法

func convert(s string, numRows int) string {
    if numRows==1 || len(s)<=numRows{
        return s
    }
    m:=numRows
    arr:=make([][]byte,m)
    x:=0
    r:=2*m-2
    for i:=0;i<len(s);i++{
        arr[x]=append(arr[x],s[i])
        if i%r<m-1{
            x++
        }else{
            x--
        }
    }
    return string(bytes.Join(arr, []byte{}))
}

7. 整数反转

给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。

如果反转后整数超过 32 位的有符号整数的范围 [−231,  231 − 1] ,就返回 0。

假设环境不允许存储 64 位整数(有符号或无符号)。

示例1

输入: x = 123
输出: 321

示例2

输入: x = -123
输出: -321

解法

func reverse(x int) int {
    res:=0
    for x!=0{
        if res>math.MaxInt32/10 || res<math.MinInt32/10{
            return 0
        }
        res=res*10+x%10
        x=x/10
    }
    return res
}

8. 字符串转换整数 (atoi)

请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。

函数 myAtoi(string s) 的算法如下:

读入字符串并丢弃无用的前导空格 检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。 读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。 将前面步骤读入的这些数字转换为整数(即,"123" -> 123, "0032" -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。 如果整数数超过 32 位有符号整数范围 [−231,  231 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231 的整数应该被固定为 −231 ,大于 231 − 1 的整数应该被固定为 231 − 1 。 返回整数作为最终结果。 注意:

本题中的空白字符只包括空格字符 ' ' 。 除前导空格或数字后的其余字符串外,请勿忽略 任何其他字符。

示例1

输入:s = "42"
输出:42
解释:加粗的字符串为已经读入的字符,插入符号是当前读取的字符。
第 1 步:"42"(当前没有读入字符,因为没有前导空格)
         ^
第 2 步:"42"(当前没有读入字符,因为这里不存在 '-' 或者 '+')
         ^
第 3 步:"42"(读入 "42")
           ^
解析得到整数 42 。
由于 "42" 在范围 [-231, 231 - 1] 内,最终结果为 42

示例2

输入:s = "   -42"
输出:-42
解释:
第 1 步:"   -42"(读入前导空格,但忽视掉)
            ^
第 2 步:"   -42"(读入 '-' 字符,所以结果应该是负数)
             ^
第 3 步:"   -42"(读入 "42")
               ^
解析得到整数 -42 。
由于 "-42" 在范围 [-231, 231 - 1] 内,最终结果为 -42

示例3

输入:s = "4193 with words"
输出:4193
解释:
第 1 步:"4193 with words"(当前没有读入字符,因为没有前导空格)
         ^
第 2 步:"4193 with words"(当前没有读入字符,因为这里不存在 '-' 或者 '+')
         ^
第 3 步:"4193 with words"(读入 "4193";由于下一个字符不是一个数字,所以读入停止)
             ^
解析得到整数 4193 。
由于 "4193" 在范围 [-231, 231 - 1] 内,最终结果为 4193

解法

func myAtoi(s string) int {
    return covrtStrToInt(chean(s))   
}
func covrtStrToInt(flag int,s string)int{
    fmt.Println(s)
    value:=0
    for i:=0;i<len(s);i++{
        value=value*10+int(s[i]-'0')
        if flag==1 && value>math.MaxInt32{
            return math.MaxInt32
        }
        if flag==-1 && value*flag<math.MinInt32{
            return math.MinInt32
        }
    }
    return flag*value
}

func chean(s string)(flag int, abs string){
    s=strings.TrimSpace(s)
    if len(s)==0{
        return 
    }
    switch s[0]{
        case '0','1','2','3','4','5','6','7','8','9':
            flag=1
            abs=s
        case '+':
            flag=1
            abs=s[1:]
        case '-':
            flag=-1
            abs=s[1:]
    }
    for i:=0;i<len(abs);i++{
        if abs[i]<'0' || abs[i]>'9'{
            abs=abs[:i]
            break
        }
    }
    return
}

9. 回文数

给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。

回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

例如,121 是回文,而 123 不是。

示例1

输入: x = 121
输出: true

示例2

输入: x = -121
输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。

示例3

输入: x = 10
输出: false
解释: 从右向左读, 为 01 。因此它不是一个回文数。

解法

func isPalindrome(x int) bool {
    str:=strconv.Itoa(x)
    return check(str)
}

func check(s string)bool{
    left,right:=0,len(s)-1
    for left<right{
        if s[left]!=s[right]{
            return false
        }
        left++
        right--
    }
    return true
}

11. 盛最多水的容器

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

示例1

输入:[1,8,6,2,5,4,8,3,7]
输出:49 
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49

示例2

输入: height = [1,1]
输出: 1

解法

func maxArea(height []int) int {
    maxValue:=0
    left,right:=0,len(height)-1
    for left<right{
        temp:=min(height[left],height[right])
        maxValue=max(maxValue,temp*(right-left))
        if height[left]<height[right]{
            left++
        }else{
            right--
        }
    }
    return maxValue
}

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
}

12. 整数转罗马数字

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符          数值
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做  XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。 X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。  C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。 给你一个整数,将其转为罗马数字。

示例1

输入: num = 3
输出: "III"

示例2

输入: num = 4
输出: "IV"

示例3

输入: num = 9
输出: "IX"

示例4

输入: num = 58
输出: "LVIII"
解释: L = 50, V = 5, III = 3.

示例5

输入: num = 1994
输出: "MCMXCIV"
解释: M = 1000, CM = 900, XC = 90, IV = 4.

解法

func intToRoman(num int) string {
    hashMap:=map[int]string{
        1:"I",
        4:"IV",
        5:"V",
        9:"IX",
        10:"X",
        40:"XL",
        50:"L",
        90:"XC",
        100:"C",
        400:"CD",
        500:"D",
        900:"CM",
        1000:"M",
    }
    res:=""
    arr:=[]int{1,4,5,9,10,40,50,90,100,400,500,900,1000}
    for i:=len(arr)-1;i>=0;i--{
        count:=num/arr[i]
        for count!=0{
            res=res+hashMap[arr[i]]
            num=num-arr[i]
            count=count-1
        }
    }
    return res
}

13. 罗马数字转整数

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符          数值
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

例如, 罗马数字 2 写做 II ,即为两个并列的 1 。12 写做 XII ,即为 X + II 。 27 写做  XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。 X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。  C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。 给定一个罗马数字,将其转换成整数。

示例1

输入: s = "III"
输出: 3

示例2

输入: s = "IV"
输出: 4

示例3

输入: s = "IX"
输出: 9

示例4

输入: s = "LVIII"
输出: 58
解释: L = 50, V= 5, III = 3.

示例5

输入: s = "MCMXCIV"
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.

解法

func romanToInt(s string) int {
    hashMap:=map[byte]int{
        'I':1,
        'V':5,
        'X':10,
        'L':50,
        'C':100,
        'D':500,
        'M':1000,
    }
    sum:=0
    for i:=0;i<len(s);i++{
        if i<len(s)-1 && hashMap[s[i]]<hashMap[s[i+1]]{
            sum=sum-hashMap[s[i]]
        }else{
            sum=sum+hashMap[s[i]]
        }
    }
    return sum
}

14. 最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 ""

示例1

输入: strs = ["flower","flow","flight"]
输出: "fl"

示例2

输入: strs = ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。

示例3

输入: s = "IX"
输出: 9

解法

func longestCommonPrefix(strs []string) string {
    if len(strs)==0{
        return " "
    }
    target:=strs[0]
    for i:=1;i<len(strs);i++{
        for strings.Index(strs[i],target)!=0{
            if len(strs)==0{
                return ""
            }
            target=target[:len(target)-1]
        }
    }
    return target
}

15. 三数之和

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例1

输入: nums = [-1,0,1,2,-1,-4]
输出: [[-1,-1,2],[-1,0,1]]

示例2

输入: nums = []
输出: []

示例3

输入: nums = [0]
输出: []

解法

func threeSum(nums []int) [][]int {
    sort.Ints(nums)
    res:=[][]int{}
    if len(nums)<3{
        return res
    }
    for i:=0;i<len(nums)-2;i++{
        left,right:=i+1,len(nums)-1
        if i>=1 && nums[i]==nums[i-1]{
            continue
        }
        for left<right{
            if nums[left]+nums[right]+nums[i]==0{
                res=append(res,[]int{nums[left],nums[right],nums[i]})
                left++
                right--
                for left<right && nums[left]==nums[left-1]{
                    left++
                }
                for left<right && nums[right]==nums[right+1]{
                    right--
                }
            }else if nums[left]+nums[right]+nums[i]>0{
                right--
            }else{
                left++
            }
        }
    }
    return res
}

17. 电话号码的字母组合

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

image.png

示例1

输入: digits = "23"
输出: ["ad","ae","af","bd","be","bf","cd","ce","cf"]

示例2

输入: digits = ""
输出: []

示例3

输入: digits = "2"
输出: ["a","b","c"]

解法

func letterCombinations(digits string) []string {
    if len(digits)==0{
		return []string{}
	}
	hashMap:=map[byte]string{
		'2':"abc",'3':"def",'4':"ghi",'5':"jkl",'6':"mno",'7':"pqrs",'8':"tuv",'9':"wxyz",
	}
	res:=[]string{}
	dfs17(digits,0,"",&res,hashMap)
	return res
}

func dfs17(digits string,index int,temp string,res *[]string,hashMap map[byte]string){
	if index==len(digits){
		*res=append(*res,temp)
		return
	}
	a:=hashMap[digits[index]]
	for i:=0;i<len(a);i++{
		dfs17(digits,index+1,temp+string(a[i]),res,hashMap)
	}
}

19. 删除链表的倒数第 N 个结点

给你一个链表,删除链表的倒数第 n **个结点,并且返回链表的头结点。

示例1

输入: head = [1,2,3,4,5], n = 2
输出: [1,2,3,5]

示例2

输入: head = [1], n = 1
输出: []

示例3

输入: head = [1,2], n = 1
输出: [1]

解法

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func removeNthFromEnd(head *ListNode, n int) *ListNode {
	newList:=&ListNode{Next: head}
	fast,slow:=newList,newList
	for i:=0;i<=n;i++{
		fast=fast.Next
	}
	for fast!=nil{
		fast=fast.Next
		slow=slow.Next
	}
	slow.Next=slow.Next.Next
	return newList.Next
}

20. 有效的括号

给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。

示例1

输入: s = "()"
输出: true

示例2

输入: s = "()[]{}"
输出: true

示例3

输入: s = "(]"
输出: false

解法

func isValid(s string) bool {
    stack:=[]byte{}
    for i:=0;i<len(s);i++{
        if s[i]=='(' || s[i]=='['|| s[i]=='{'{
            stack=append(stack,s[i])
        }else{
            if len(stack)==0{
                return false
            }else{
                a:=stack[len(stack)-1]
                if s[i]==')' && a=='('{
                    stack=stack[:len(stack)-1]
                    continue
                }else if s[i]==']' && a=='['{
                    stack=stack[:len(stack)-1]
                    continue
                }else if s[i]=='}' && a=='{'{
                    stack=stack[:len(stack)-1]
                    continue
                }else{
                    return false
                }
            }
        }
    }
    return len(stack)==0
}

21. 合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例1

输入: l1 = [1,2,4], l2 = [1,3,4]
输出: [1,1,2,3,4,4]

示例2

输入: l1 = [], l2 = []
输出: []

示例3

输入: l1 = [], l2 = [0]
输出: [0]

解法

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode {
	newNode:=&ListNode{0,nil}
	node:=newNode
	for list1!=nil && list2!=nil{
		if list1.Val<list2.Val{
			node.Next=list1
			list1=list1.Next
		}else{
			node.Next=list2
			list2=list2.Next
		}
		node=node.Next
	}
	if list1!=nil{
		node.Next=list1
	}
	if list2!=nil{
		node.Next=list2
	}
	return newNode.Next
}

22. 括号生成

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例1

输入: n = 3
输出: ["((()))","(()())","(())()","()(())","()()()"]

示例2

输入: n = 1
输出: ["()"]

解法

func generateParenthesis(n int) []string {
	left,right:=n,n
	res:=[]string{}
	dfs(left,right,n,"",&res)
	return res
}

func dfs(left int,right int,n int,temp string,res *[]string){
	if len(temp)==2*n{
		*res=append(*res,temp)
		return
	}
	if left>0 {
		dfs(left-1,right,n,temp+"(",res)
	}
	if left<right{
		dfs(left,right-1,n,temp+")",res)
	}
}

23. 合并K个升序链表

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

示例1

输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
  1->4->5,
  1->3->4,
  2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6

示例2

输入: lists = []
输出: []

示例3

输入: lists = [[]]
输出: []

解法

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func mergeKLists(lists []*ListNode) *ListNode {
    if len(lists)==0{
        return nil
    }
    target:=lists[0]
    for i:=1;i<len(lists);i++{
        target=mergeCore(target,lists[i])
    }
    return target
}

func mergeCore(p1 *ListNode,p2 *ListNode)*ListNode{
    if p1==nil{
        return p2
    }
    if p2==nil{
        return p1
    }
    if p1.Val<p2.Val{
        p1.Next=mergeCore(p1.Next,p2)
        return p1
    }
    p2.Next=mergeCore(p1,p2.Next)
    return p2
}

31. 下一个排列

整数数组的一个 排列  就是将其所有成员以序列或线性顺序排列。

例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。 整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。

例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。 类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。 而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。 给你一个整数数组 nums ,找出 nums 的下一个排列。

必须 原地 修改,只允许使用额外常数空间。

示例1

输入: nums = [1,2,3]
输出: [1,3,2]

示例2

输入: nums = [3,2,1]
输出: [1,2,3]

示例3

输入: nums = [1,1,5]
输出: [1,5,1]
``
## 解法
```golang
func nextPermutation(nums []int)  {
    index:=-1
    target:=nums[len(nums)-1]
    for i:=len(nums)-2;i>=0;i--{
		if nums[i]<target{
			index =i
			break
		}else{
			target=nums[i]
		}
	}
    if index!=-1{
        left:=index+1
        minValue:=math.MaxInt32
        for i:=index+1;i<len(nums);i++{
            if nums[i]>nums[index] && nums[i]< minValue{
                minValue=nums[i]
                left=i
            }
        }
        nums[index],nums[left]=nums[left],nums[index]
        sort.Ints(nums[index+1:])
    }else{
        sort.Ints(nums)
    }
}

32. 最长有效括号

给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

示例1

输入: s = "(()"
输出: 2
解释: 最长有效括号子串是 "()"

示例2

输入: s = ")()())"
输出: 4
解释: 最长有效括号子串是 "()()"

示例3

输入: s = ""
输出: 0

解法

func longestValidParentheses(s string) int {
    stack:=[]int{}
    stack=append(stack,-1)
    maxValue:=0
    for i:=0;i<len(s);i++{
        if s[i]=='('{
            stack=append(stack,i)
        }else{
            stack=stack[:len(stack)-1]
            if len(stack)==0{
                stack=append(stack,i)
            }else{
                maxValue=max(maxValue,i-stack[len(stack)-1])
            }
        }
    }
    return maxValue
}

func max(a,b int)int{
    if a>b{
        return a
    }
    return b
}

33. 搜索旋转排序数组

整数数组 nums 按升序排列,数组中的值 互不相同 。

在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。

给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。

示例1

输入: nums = [4,5,6,7,0,1,2], target = 0
输出: 4

示例2

输入: nums = [4,5,6,7,0,1,2], target = 3
输出: -1

示例3

输入: nums = [1], target = 0
输出: -1

解法

func search(nums []int, target int) int {
    left,right:=0,len(nums)-1
    for left<=right{
        middle:=left+(right-left)/2
        if nums[middle]==target{
            return middle
        }
        if nums[middle]>=nums[left]{
            if nums[middle]>target && target>=nums[left]{
                    right=middle-1
            }else{
                    left=middle+1
            }
        }else{
            if nums[middle]<target && target<=nums[right]{
                    left=middle+1
            }else{
                    right=middle-1
            }
        }
    }
	return -1
}

34. 在排序数组中查找元素的第一个和最后一个位置

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]。

进阶:

你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?

示例1

输入: nums = [5,7,7,8,8,10], target = 8
输出: [3,4]

示例2

输入: nums = [5,7,7,8,8,10], target = 6
输出: [-1,-1]

示例3

输入: nums = [], target = 0
输出: [-1,-1]

解法

func searchRange(nums []int, target int) []int {
    left:=searchLeft(nums,target)
    right:=searchRight(nums,target)
    return []int{left,right}
}

func searchLeft(nums []int,target int)int{
    left,right:=0,len(nums)-1
    for left<=right{
            middle:=left+(right-left)/2
            if nums[middle]>=target{
                    right=middle-1
            }else{
                    left=middle+1
            }
    }
    if left>=len(nums) || nums[left]!=target{
            return -1
    }
    return left
}

func searchRight(nums []int,target int)int{
	left,right:=0,len(nums)-1
	for left<=right{
		middle:=left+(right-left)/2
		if nums[middle]<=target{
			left=middle+1
		}else{
			right=middle-1
		}
	}
	if right<0 || nums[right]!=target{
		return -1
	}
	return right
}

39. 组合总和

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。 

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

示例1

输入:candidates = [2,3,6,7], target = 7
输出:[[2,2,3],[7]]
解释:
2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。
7 也是一个候选, 7 = 7 。
仅有这两种组合。

示例2

输入: candidates = [2,3,5], target = 8
输出: [[2,2,2,2],[2,3,3],[3,5]]

示例3

输入: candidates = [2], target = 1
输出: []

解法

func combinationSum(candidates []int, target int) [][]int {
    res:=[][]int{}
    sort.Ints(candidates)
    dfs(candidates,target,0,nil,&res)
    return res
}

func dfs(candidates []int,target int,index int,temp []int,res *[][]int){
    if target==0{
            copyTemp:=make([]int,len(temp))
            copy(copyTemp,temp)
            *res=append(*res,copyTemp)
            return
    }
    for i:=index;i<len(candidates);i++{
            if candidates[i]>target{
                    continue
            }
            dfs(candidates,target-candidates[i],i,append(temp,candidates[i]),res)
	}
}

42. 接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

示例1

示例 1:

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 

示例2

输入: height = [4,2,0,3,2,5]
输出: 9

示例3

输入: candidates = [2], target = 1
输出: []

解法

func trap(height []int) int {
    sum:=0
    for i:=0;i<len(height);i++{
        if i==0 || i==len(height)-1{
                continue
        }
        leftHeight:=height[i]
        rightHeight:=height[i]
        for j:=i+1;j<len(height);j++{
                if height[j]>rightHeight{
                        rightHeight=height[j]
                }
        }
        for j:=0;j<i;j++{
                if height[j]>leftHeight{
                        leftHeight=height[j]
                }
        }
        if min(leftHeight,rightHeight)-height[i]>0{
    sum=sum+(min(leftHeight,rightHeight)-height[i])*1
    }
    }
    return sum
}

func min(a,b int)int{
    if a<b{
            return a
    }
    return b
}

46. 全排列

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例1

示例 1:

输入: nums = [1,2,3]
输出: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

示例2

输入: nums = [0,1]
输出: [[0,1],[1,0]]

示例3

输入: nums = [1]
输出: [[1]]

解法

func permute(nums []int) [][]int {
    res:=[][]int{}
    visited:=make([]bool,len(nums))
    dfs(nums,0,visited,nil,&res)
    return res
}

func dfs(nums []int,index int,visited []bool,temp []int,res *[][]int){
    if len(temp)==len(nums){
        copyTemp:=make([]int,len(nums))
        copy(copyTemp,temp)
        *res=append(*res,copyTemp)
        return 
    }
    for i:=0;i<len(nums);i++{
        if visited[i]{
            continue
        }
        visited[i]=true
        dfs(nums,index+1,visited,append(temp,nums[i]),res)
        visited[i]=false
    }
}

48. 旋转图像

给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。

你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

示例1

示例 1:

输入: matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出: [[7,4,1],[8,5,2],[9,6,3]]

示例2

输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]

解法

func rotate(matrix [][]int)  {
    temp:=make([][]int,len(matrix))
    for i:=0;i<len(matrix);i++{
        temp[i]=make([]int,len(matrix[0]))
    }
    n:=len(matrix[0])
    for i:=0;i<len(matrix);i++{
        for j:=0;j<len(matrix[0]);j++{
            temp[j][n-1-i]=matrix[i][j]
        }
    }
    copy(matrix,temp)
}

#### 49. 字母异位词分组

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母通常恰好只用一次。

示例1

示例 1:

输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]

示例2

输入: strs = [""]
输出: [[""]]

示例3

输入: strs = ["a"]
输出: [["a"]]

解法

func groupAnagrams(strs []string) [][]string {
    hashMap:=map[string][]string{}
    for i:=0;i<len(strs);i++{
        temp:=[]byte(strs[i])
        sort.Slice(temp,func(i,j int)bool{
            return temp[i]<temp[j]
        })
        str:=string(temp)
        hashMap[str]=append(hashMap[str],strs[i])
    }
    res:=[][]string{}
    for _,v:=range hashMap{
        res=append(res,v)
    }
    return res
}

53. 最大子数组和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组 是数组中的一个连续部分。

示例1

输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6 。

示例2

输入: nums = [1]
输出: 1

示例3

输入: nums = [5,4,-1,7,8]
输出: 23

解法

func maxSubArray(nums []int) int {
    n:=len(nums)
    dp:=make([]int,n)
    dp[0]=nums[0]
    maxValue:=nums[0]
    for i:=1;i<n;i++{
        dp[i]=max(dp[i-1]+nums[i],nums[i])
        if dp[i]>=maxValue{
            maxValue=dp[i]
        }
    }
    return maxValue
}

func max(a,b int)int{
    if a>b{
        return a
    }
    return b
}

62. 不同路径

一个机器人位于一个 m x n **网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

问总共有多少条不同的路径?

示例1

输入: m = 3, n = 7
输出: 28

示例2

输入:m = 3, n = 2
输出:3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右
3. 向下 -> 向右 -> 向下

示例3

输入: m = 7, n = 3
输出: 28

解法

func uniquePaths(m int, n int) int {
    dp:=make([][]int,m)
    for i:=0;i<m;i++{
        dp[i]=make([]int,n)
    }
    for j:=0;j<n;j++{
        dp[0][j]=1
    }
    for i:=0;i<m;i++{
        dp[i][0]=1
    }
    for i:=1;i<m;i++{
        for j:=1;j<n;j++{
            dp[i][j]=dp[i-1][j]+dp[i][j-1]
        }
    }
    return dp[m-1][n-1]
}

64. 最小路径和

给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明:每次只能向下或者向右移动一步。

示例1

输入: grid = [[1,3,1],[1,5,1],[4,2,1]]
输出: 7
解释: 因为路径 13111 的总和最小。

示例2

输入: grid = [[1,2,3],[4,5,6]]
输出: 12

解法

func minPathSum(grid [][]int) int {
    m,n:=len(grid),len(grid[0])
    dp:=make([][]int,m)
    for i:=0;i<m;i++{
        dp[i]=make([]int,n)
    }
    for i:=0;i<m;i++{
        if i==0{
            dp[0][0]=grid[0][0]
        }else{
            dp[i][0]=dp[i-1][0]+grid[i][0]
        } 
    }
    for j:=0;j<n;j++{
        if j==0{
            dp[0][0]=grid[0][0]
        }else{
            dp[0][j]=dp[0][j-1]+grid[0][j]
        }
    }
    for i:=1;i<m;i++{
        for j:=1;j<n;j++{
            dp[i][j]=min(dp[i-1][j],dp[i][j-1])+grid[i][j]
        }
    }
    return dp[m-1][n-1]
}

func min(a,b int)int{
    if a<b{
        return a
    }
    return b
}

70. 爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

示例1

输入: n = 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶

示例2

输入: n = 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶

解法

func climbStairs(n int) int {
    if n<=2{
        return n
    }
    dp:=make([]int,n+1)
    dp[1]=1
    dp[2]=2
    for i:=3;i<=n;i++{
        dp[i]=dp[i-1]+dp[i-2]
    }
    return dp[n]
}

76. 最小覆盖子串

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。

 

注意:

对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。 如果 s 中存在这样的子串,我们保证它是唯一的答案。

示例1

输入: s = "ADOBECODEBANC", t = "ABC"
输出: "BANC"

示例2

输入: s = "a", t = "a"
输出: "a"

示例3

输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。

解法

func minWindow(s string, t string) string {
    hashMapForS:=map[byte]int{}
    hashMapForT:=map[byte]int{}
    for i:=0;i<len(t);i++{
        hashMapForT[t[i]]++
    }
    left:=0
    match:=0
    minValue:=math.MaxInt32
    start,end:=-1,-1
    for i:=0;i<len(s);{
        temp := s[i]
		i++
		if _, ok := hashMapForT[temp]; ok {
			hashMapForS[temp]++
			if hashMapForS[temp] == hashMapForT[temp] {
				match++
			}
		}
        for  match==len(hashMapForT){
            curLen:=i-left+1
            fmt.Println(curLen)
            if curLen<=minValue{
                start=left
                end=i
                minValue=curLen
            }
            temp:=s[left]
            left++
            if _,ok:=hashMapForT[temp];ok{
                if hashMapForS[temp]==hashMapForT[temp]{
                    match--
                }
                hashMapForS[temp]--
            }
        }

    }
    if minValue==math.MaxInt32{
        return ""
    }
    return s[start:end]
}

78. 子集

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

示例1

输入: nums = [1,2,3]
输出: [[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

示例2

输入: nums = [0]
输出: [[],[0]]

解法

func subsets(nums []int) [][]int {
    res:=[][]int{}
    dfs(nums,0,nil,&res)
    return res
}

func dfs(nums []int,index int,temp []int,res *[][]int){
    copyTemp:=make([]int,len(temp))
    copy(copyTemp,temp)
    *res=append(*res,copyTemp)
    for i:=index;i<len(nums);i++{
        dfs(nums,i+1,append(temp,nums[i]),res)
    }
}

79. 单词搜索

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例1

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true

示例2

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE"
输出:true

示例3

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCB"
输出:false

解法

func exist(board [][]byte, word string) bool {
    m:=len(board)
    n:=len(board[0])
    visited:=make([][]bool,m)
    for i:=0;i<m;i++{
        visited[i]=make([]bool,n)
    }
    for i:=0;i<m;i++{
        for j:=0;j<n;j++{
            if board[i][j]==word[0]{
                if dfs(board,word,i,j,0,visited){
                    return true
                }
            }
        }
    }
    return false
}

func dfs(board [][]byte,word string,i int,j int,index int,visited [][]bool)bool{
    if i<0 || i>=len(board) || j<0 || j>=len(board[0]) || visited[i][j] || board[i][j]!=word[index]{
        return false
    }
    if index==len(word)-1{
        return true
    }
    visited[i][j]=true
    a:=dfs(board,word,i+1,j,index+1,visited)
    b:=dfs(board,word,i-1,j,index+1,visited)
    c:=dfs(board,word,i,j+1,index+1,visited)
    d:=dfs(board,word,i,j-1,index+1,visited)
    if a || b|| c|| d{
        return true
    }
    visited[i][j]=false
    return false
}

94. 二叉树的中序遍历

给定一个二叉树的根节点 root ,返回它的 中序 遍历。

示例1

输入: root = [1,null,2,3]
输出: [1,3,2]

示例2

输入: root = []
输出: []

示例3

输入: root = [1]
输出: [1]

解法

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func inorderTraversal(root *TreeNode) []int {
    stack:=[]*TreeNode{}
    res:=[]int{}
    for root!=nil ||len(stack)>0{
        for root!=nil{
            stack=append(stack,root)
            root=root.Left
        }
        root=stack[len(stack)-1]
        res=append(res,root.Val)
        stack=stack[:len(stack)-1]
        root=root.Right
    }
    return res
}

96. 不同的二叉搜索树

给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。

示例1

输入: n = 3
输出: 5

示例2

输入: n = 1
输出: 1

解法

func numTrees(n int) int {
    dp:=make([]int,n+1)
    dp[0]=1
    for i:=1;i<=n;i++{
        for j:=1;j<=i;j++{
            dp[i]=dp[i]+dp[i-j]*dp[j-1]
        }
    }
    return dp[n]
}

98. 验证二叉搜索树

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

节点的左子树只包含 小于 当前节点的数。 节点的右子树只包含 大于 当前节点的数。 所有左子树和右子树自身必须也是二叉搜索树。

示例1

输入: root = [2,1,3]
输出: true

示例2

输入: root = [5,1,4,null,null,3,6]
输出: false
解释: 根节点的值是 5 ,但是右子节点的值是 4

解法

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isValidBST(root *TreeNode) bool { 
    return dfs(root,math.MinInt64,math.MaxInt64)
}

func dfs(root *TreeNode,min int64, max int64)bool{
    if root==nil{
        return true
    }
    if int64(root.Val)<=min || int64(root.Val)>=max{
        return false
    }
    return dfs(root.Left,min,int64(root.Val)) && dfs(root.Right,int64(root.Val),max)
}

102. 二叉树的层序遍历

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

示例1

输入: root = [3,9,20,null,null,15,7]
输出: [[3],[9,20],[15,7]]

示例2

输入: root = [1]
输出: [[1]]

解法

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isSymmetric(root *TreeNode) bool {
    return dfs(root.Left,root.Right)
}

func dfs(left *TreeNode,right *TreeNode)bool{
    if left==nil && right==nil{
        return true
    }
    if left==nil || right==nil{
        return false
    }
    if left.Val!=right.Val{
        return false
    }
    return dfs(left.Left,right.Right) && dfs(left.Right,right.Left)
}

101. 对称二叉树

给你一个二叉树的根节点 root , 检查它是否轴对称。

示例1

输入: root = [1,2,2,3,4,4,3]
输出: true

示例2

输入: root = [1,2,2,null,3,null,3]
输出: false

解法

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func levelOrder(root *TreeNode) [][]int {
    if root==nil{
        return [][]int{}
    }
    queue:=[]*TreeNode{}
    queue=append(queue,root)
    res:=[][]int{}
    for len(queue)!=0{
        curLen:=len(queue)
        temp:=[]int{}
        for i:=0;i<curLen;i++{
            node:=queue[0]
            temp=append(temp,node.Val)
            if node.Left!=nil{
                queue=append(queue,node.Left)
            }
            if node.Right!=nil{
                queue=append(queue,node.Right)
            }
            queue=queue[1:] 
        }
        res=append(res,temp)
    }
    return res
}

104. 二叉树的最大深度

给定一个二叉树,找出其最大深度。 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 说明: 叶子节点是指没有子节点的节点。

示例1

    3
   / \
  9  20
    /  \
   15   7
给定二叉树 [3,9,20,null,null,15,7]
返回它的最大深度 3

解法

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func maxDepth(root *TreeNode) int {
    if root==nil{
        return 0
    }
    return max(maxDepth(root.Left),maxDepth(root.Right))+1
}


func max(a,b int)int{
    if a>b{
        return a
    }
    return b
}

105. 从前序与中序遍历序列构造二叉树

给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

示例1

输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]

示例2

输入: preorder = [-1], inorder = [-1]
输出: [-1]

解法

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func buildTree(preorder []int, inorder []int) *TreeNode {
    if len(preorder)==0 || len(inorder)==0{
        return nil
    }
    root:=&TreeNode{}
    root.Val=preorder[0]
    i:=0
    for ;i<len(inorder);i++{
        if inorder[i]==root.Val{
            break
        }
    }
    root.Left=buildTree(preorder[1:i+1],inorder[:i])
    root.Right=buildTree(preorder[i+1:],inorder[i+1:])
    return root
}

114. 二叉树展开为链表

给你二叉树的根结点 root ,请你将它展开为一个单链表:

展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。 展开后的单链表应该与二叉树 先序遍历 顺序相同。

示例1

输入: root = [1,2,5,3,4,null,6]
输出: [1,null,2,null,3,null,4,null,5,null,6]

示例2

输入: root = []
输出: []

解法

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func flatten(root *TreeNode)  {
    temp:=[]*TreeNode{}
    var dfs func(*TreeNode)
    dfs=func(root *TreeNode){
        if root==nil{
            return
        }
        temp=append(temp,root)
        dfs(root.Left)
        dfs(root.Right)
    }
    dfs(root)
    for i:=0;i<len(temp)-1;i++{
        cur:=temp[i]
        next:=temp[i+1]
        cur.Left=nil
        cur.Right=next
    }
}

121. 买卖股票的最佳时机

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

示例1

输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

示例2

输入: prices = [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

解法

func maxProfit(prices []int) int {
    maxValue:=0
    minValue:=prices[0]
    for i:=0;i<len(prices);i++{
        maxValue=max(maxValue,prices[i]-minValue)
        minValue=min(minValue,prices[i])
    }
    return maxValue
}

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
}

124. 二叉树中的最大路径和

路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。

路径和 是路径中各节点值的总和。

给你一个二叉树的根节点 root ,返回其 最大路径和 。

示例1

输入: root = [1,2,3]
输出: 6
解释: 最优路径是 2 -> 1 -> 3 ,路径和为 2 + 1 + 3 = 6

示例2

输入:root = [-10,9,20,null,null,15,7]
输出:42
解释:最优路径是 15 -> 20 -> 7 ,路径和为 15 + 20 + 7 = 42

解法

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func maxPathSum(root *TreeNode) int {
    maxValue:=math.MinInt64
    var maxCore func (*TreeNode)int
    maxCore=func(root *TreeNode)int{
        if root==nil{
            return 0
        }
        left:=max(0,maxCore(root.Left))
        right:=max(0,maxCore(root.Right))
        temp:=root.Val+left+right
        maxValue=max(maxValue,temp)
        return root.Val+max(left,right)
    }
    maxCore(root)
    return maxValue
}


func max(a,b int)int{
    if a>b{
        return a
    }
    return b
}

128. 最长连续序列

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例1

输入: nums = [100,4,200,1,3,2]
输出: 4
解释: 最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。

示例2

输入: nums = [0,3,7,2,5,8,4,6,0,1]
输出: 9

解法

func longestConsecutive(nums []int) int {
    maxValue:=0
    hashMap:=map[int]bool{}
    for i:=0;i<len(nums);i++{
        hashMap[nums[i]]=true
    }
    sort.Ints(nums)
    for i:=0;i<len(nums);i++{
        count:=0
        for hashMap[nums[i]]{
            count++
            hashMap[nums[i]]=false
            nums[i]++
        }
        maxValue=max(maxValue,count)
    }
    return maxValue
}

func max(a,b int)int{
    if a>b{
        return a
    }
    return b
}

136. 只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例1

输入: [2,2,1]
输出: 1

示例2

输入: [4,1,2,1,2]
输出: 4

解法

func singleNumber(nums []int) int {
    hashMap:=map[int]int{}
    for i:=0;i<len(nums);i++{
        hashMap[nums[i]]++
    }
    for k,v:=range hashMap{
        if v==1{
            return k
        }
    }
    return -1
}

139. 单词拆分路径和](leetcode-cn.com/problems/bi…)

给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。

注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。

示例1

输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以由 "leet""code" 拼接成。

示例2

输入: s = "applepenapple", wordDict = ["apple", "pen"]
输出: true
解释: 返回 true 因为 "applepenapple" 可以由 "apple" "pen" "apple" 拼接成。
     注意,你可以重复使用字典中的单词。

解法

func wordBreak(s string, wordDict []string) bool {
    dp:=make([]bool,len(s)+1)
    dp[0]=true
    hashMap:=make(map[string]bool)
    for i:=0;i<len(wordDict);i++{
        hashMap[wordDict[i]]=true
    }
    for i:=1;i<=len(s);i++{
        for j:=0;j<i;j++{
            if dp[j]&&hashMap[s[j:i]]{
                dp[i]=true
                break
            }
        }
    }
    return dp[len(s)]
}

141. 环形链表

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

示例1

输入: head = [3,2,0,-4], pos = 1
输出: true
解释: 链表中有一个环,其尾部连接到第二个节点。

示例2

输入: head = [1,2], pos = 0
输出: true
解释: 链表中有一个环,其尾部连接到第一个节点。

解法

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func hasCycle(head *ListNode) bool {
    fast:=head
    slow:=head
    for fast!=nil && slow!=nil && fast.Next!=nil{
        fast=fast.Next.Next
        slow=slow.Next
        if slow==fast{
            return true
        }
    }
    return false
}