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 不对应任何字母。
示例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
解释: 因为路径 1→3→1→1→1 的总和最小。
示例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
}