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

108 阅读8分钟

142. 环形链表 II

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

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

不允许修改 链表。

示例1

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

示例2

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

解法

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func detectCycle(head *ListNode) *ListNode {
    node:=head
    index:=0
    hashMap:=map[*ListNode]int{}
    for node!=nil{
        if _,ok:=hashMap[node];ok{
            return node
        }else{
            hashMap[node]=index
            index++
            node=node.Next
        }
    }
    return nil
}

148. 排序链表

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

示例1

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

示例2

输入: head = [-1,5,3,4,0]
输出: [-1,0,3,4,5]

解法

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func sortList(head *ListNode) *ListNode {
    temp:=[]*ListNode{}
    node:=head
    for node!=nil{
        temp=append(temp,node)
        node=node.Next
    }
    sort.Slice(temp,func(i,j int)bool{
        return temp[i].Val<temp[j].Val
    })
    newHead:=&ListNode{}
    node=newHead
    for i:=0;i<=len(temp)-1;i++{
        curNode:=&ListNode{
            Val:temp[i].Val,
        }
        node.Next=curNode
        node=node.Next
    }
    return newHead.Next
}

152. 乘积最大子数组

给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。

测试用例的答案是一个 32-位 整数。

子数组 是数组的连续子序列。

示例1

输入: nums = [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。

示例2

输入: nums = [-2,0,-1]
输出: 0
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。

解法

func maxProduct(nums []int) int {
    res:=nums[0]
    maxValue:=nums[0]
    minValue:=nums[0]
    for i:=1;i<len(nums);i++{
        if nums[i]<0{
            minValue,maxValue=maxValue,minValue
        }
        minValue=min(minValue*nums[i],nums[i])
        maxValue=max(maxValue*nums[i],nums[i])
        res=max(res,maxValue)
    }
    return res
}

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
}

155. 最小栈

设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

实现 MinStack 类:

MinStack() 初始化堆栈对象。 void push(int val) 将元素val推入堆栈。 void pop() 删除堆栈顶部的元素。 int top() 获取堆栈顶部的元素。 int getMin() 获取堆栈中的最小元素。

示例1

输入:
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]

输出:
[null,null,null,null,-3,null,0,-2]

解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin();   --> 返回 -3.
minStack.pop();
minStack.top();      --> 返回 0.
minStack.getMin();   --> 返回 -2.

解法

type MinStack struct {
    numstack []int
    minstack []int
}


func Constructor() MinStack {
    m:=MinStack{}
    m.numstack=[]int{}
    m.minstack=[]int{}
    return m
}


func (this *MinStack) Push(val int)  {
    this.numstack=append(this.numstack,val)
    if len(this.minstack)==0{
        this.minstack=append(this.minstack,val)
    }else{
        if this.minstack[len(this.minstack)-1]>val{
            this.minstack=append(this.minstack,val)
        }else{
            this.minstack=append(this.minstack,this.minstack[len(this.minstack)-1])
        }
    }
}


func (this *MinStack) Pop()  {
    this.minstack=this.minstack[:len(this.minstack)-1]
    this.numstack=this.numstack[:len(this.numstack)-1]
}


func (this *MinStack) Top() int {
    return this.numstack[len(this.numstack)-1]
}


func (this *MinStack) GetMin() int {
    return this.minstack[len(this.minstack)-1]
}


/**
 * Your MinStack object will be instantiated and called as such:
 * obj := Constructor();
 * obj.Push(val);
 * obj.Pop();
 * param_3 := obj.Top();
 * param_4 := obj.GetMin();
 */

160. 相交链表

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。

图示两个链表在节点 c1 开始相交:

题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构 。

自定义评测:

评测系统 的输入如下(你设计的程序 不适用 此输入):

intersectVal - 相交的起始节点的值。如果不存在相交节点,这一值为 0 listA - 第一个链表 listB - 第二个链表 skipA - 在 listA 中(从头节点开始)跳到交叉节点的节点数 skipB - 在 listB 中(从头节点开始)跳到交叉节点的节点数 评测系统将根据这些输入创建链式数据结构,并将两个头节点 headA 和 headB 传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案 。

示例1

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A[4,1,8,4,5],链表 B[5,6,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

示例2

输入:intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Intersected at '2'
解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A[1,9,1,2,4],链表 B[3,2,4]。
在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。

解法

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func getIntersectionNode(headA, headB *ListNode) *ListNode {
    l1,l2:=0,0
    p1:=headA
    p2:=headB
    for p1!=nil{
        l1=l1+1
        p1=p1.Next
    }
    for p2!=nil{
        l2=l2+1
        p2=p2.Next
    }
    p1=headA
    p2=headB
    dis:=abs(l1,l2)
    if l1<l2{
        for i:=0;i<dis;i++{
            p2=p2.Next
        }
    }else{
        for i:=0;i<dis;i++{
            p1=p1.Next
        }
    }
    for p1!=nil && p2!=nil && p1!=p2{
        p1=p1.Next
        p2=p2.Next
    }
    return p1
}

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

169. 多数元素

给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例1

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

示例2

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

解法

func majorityElement(nums []int) int {
    sort.Ints(nums)
    return nums[len(nums)/2]
}

198. 打家劫舍

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

示例1

输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
     偷窃到的最高金额 = 1 + 3 = 4

示例2

输入:[2,7,9,3,1]
输出:12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。

解法

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

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

200. 岛屿数量

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

示例1

输入:grid = [  ["1","1","1","1","0"],
  ["1","1","0","1","0"],
  ["1","1","0","0","0"],
  ["0","0","0","0","0"]
]
输出:1

示例2

输入:grid = [  ["1","1","0","0","0"],
  ["1","1","0","0","0"],
  ["0","0","1","0","0"],
  ["0","0","0","1","1"]
]
输出:3

解法

func numIslands(grid [][]byte) int {
    res:=0
    visited:=make([][]bool,len(grid))
    for i:=0;i<len(grid);i++{
        visited[i]=make([]bool,len(grid[0]))
    }
    for i:=0;i<len(grid);i++{
        for j:=0;j<len(grid[0]);j++{
            if grid[i][j]=='1'{
                dfs(grid,i,j,visited)
                res=res+1
            }
        }
    }
    return res
}

func dfs(grid [][]byte,i int,j int,visited [][]bool){
    if i<0 || i>=len(grid) || j<0 || j>=len(grid[0])||visited[i][j]{
        return 
    }
    if grid[i][j]=='0'{
        return 
    }
    visited[i][j]=true
    grid[i][j]='0'
    dfs(grid,i+1,j,visited)
    dfs(grid,i-1,j,visited)
    dfs(grid,i,j+1,visited)
    dfs(grid,i,j-1,visited)
}

206. 反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例1

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

示例2

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

解法

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reverseList(head *ListNode) *ListNode {
    node:=head
    var pre *ListNode
    for node!=nil{
       next:=node.Next
       node.Next=pre
       pre=node
       node=next
    }
    return pre
}

215. 数组中的第K个最大元素

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

示例1

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

示例2

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

解法

func findKthLargest(nums []int, k int) int {
    sort.Slice(nums,func(i,j int)bool{
        return nums[i]>nums[j]
    })
    return nums[k-1]
}

226. 翻转二叉树

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

示例1

输入: root = [4,2,7,1,3,6,9]
输出: [4,7,2,9,6,3,1]

示例2

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

解法

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func invertTree(root *TreeNode) *TreeNode {
    if root==nil{
        return nil
    }
    temp:=root.Left
    root.Left=root.Right
    root.Right=temp
    invertTree(root.Left)
    invertTree(root.Right)
    return root
}

234. 回文链表

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。

示例1

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

示例2

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

解法

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func isPalindrome(head *ListNode) bool {
    node:=head
    temp:=[]int{}
    for node!=nil{
        temp=append(temp,node.Val)
        node=node.Next
    }
    left,right:=0,len(temp)-1
    for left<right{
        if temp[left]!=temp[right]{
            return false
        }
        left++
        right--
    }
    return true
}

236. 二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

示例1

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3

示例2

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出:5
解释:节点 5 和节点 4 的最近公共祖先是节点 5 。因为根据定义最近公共祖先节点可以为节点本身。

解法

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
    if root==nil || root==p || root==q{
        return root
    }
    left:=lowestCommonAncestor(root.Left,p,q)
    right:=lowestCommonAncestor(root.Right,p,q)
    if left!=nil && right!=nil{
        return root
    }
    if left!=nil{
        return left
    }
    if right!=nil{
        return right
    }
    return nil
}

238. 除自身以外数组的乘积

给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。

题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在  32 位 整数范围内。

请不要使用除法,且在 O(n) 时间复杂度内完成此题。

示例1

输入: nums = [1,2,3,4]
输出: [24,12,8,6]

示例2

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

解法

func productExceptSelf(nums []int) []int {
    leftdp:=make([]int,len(nums))
    rightdp:=make([]int,len(nums))
    leftdp[0]=1
    rightdp[len(nums)-1]=1
    for i:=1;i<len(nums);i++{
        leftdp[i]=leftdp[i-1]*nums[i-1]
    }
    for i:=len(nums)-2;i>=0;i--{
        rightdp[i]=rightdp[i+1]*nums[i+1]
    }
    for i:=0;i<len(nums);i++{
        leftdp[i]=leftdp[i]*rightdp[i]
    }
    return leftdp
}

240. 搜索二维矩阵 II

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:

每行的元素从左到右升序排列。 每列的元素从上到下升序排列。

示例1

输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5
输出:true

示例2

输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 20
输出:false

解法

func searchMatrix(matrix [][]int, target int) bool {
    i,j:=0,len(matrix[0])-1
    for i<len(matrix) && j>=0{
        if matrix[i][j]==target{
            return true
        }else if matrix[i][j]<target{
            i++
        }else{
            j--
        }
    }
    return false
}

283. 移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例1

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

示例2

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

解法

func moveZeroes(nums []int)  {
    left,right:=0,0
    for right<len(nums){
        if nums[right]!=0{
            nums[left],nums[right]=nums[right],nums[left]
            left++
        }
        right++
    }
}

437. 路径总和 III

给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。

路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。

示例1

输入:root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
输出:3
解释:和等于 8 的路径有 3 条,如图所示。

示例2

输入: root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出: 3

解法

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func pathSum(root *TreeNode, targetSum int) int {
    if root==nil{
        return 0
    }
    res:=rootSum(root,targetSum)
    res=res+pathSum(root.Left,targetSum)
    res=res+pathSum(root.Right,targetSum)
    return res
}

func rootSum(root *TreeNode,targetSum int)(res int){
    if root==nil{
        return 
    }
    if root.Val==targetSum{
        res++
    }
    res=res+rootSum(root.Left,targetSum-root.Val)
    res=res+rootSum(root.Right,targetSum-root.Val)
    return
}

494. 目标和

给你一个整数数组 nums 和一个整数 target 。

向数组中的每个整数前添加 '+' 或 '-' ,然后串联起所有整数,可以构造一个 表达式 :

例如,nums = [2, 1] ,可以在 2 之前添加 '+' ,在 1 之前添加 '-' ,然后串联起来得到表达式 "+2-1" 。 返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。

示例1

输入:nums = [1,1,1,1,1], target = 3
输出:5
解释:一共有 5 种方法让最终目标和为 3 。
-1 + 1 + 1 + 1 + 1 = 3
+1 - 1 + 1 + 1 + 1 = 3
+1 + 1 - 1 + 1 + 1 = 3
+1 + 1 + 1 - 1 + 1 = 3
+1 + 1 + 1 + 1 - 1 = 3

示例2

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

解法

func findTargetSumWays(nums []int, target int) int {
    res:=0
    var dfs func([]int,int,int)
    dfs=func(nums []int,index int,sum int){
        if index==len(nums){
            if sum==target{
                res=res+1
            }
            return
        }
        dfs(nums,index+1,sum-nums[index])
        dfs(nums,index+1,sum+nums[index])
    }
    dfs(nums,0,0)
    return res
}

647. 回文子串

给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。

回文字符串 是正着读和倒过来读一样的字符串。

子字符串 是字符串中的由连续字符组成的一个序列。

具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。

示例1

输入: s = "abc"
输出: 3
解释: 三个回文子串: "a", "b", "c"

示例2

输入: s = "aaa"
输出: 6
解释: 6个回文子串: "a", "a", "a", "aa", "aa", "aaa"

解法

func countSubstrings(s string) int {
    count:=0
    for i:=0;i<len(s);i++{
        for j:=i;j<len(s);j++{
            if check(s[i:j+1]){
                count++
            }
        }
    }
    return count
}

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
}

739. 每日温度

给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指在第 i 天之后,才会有更高的温度。如果气温在这之后都不会升高,请在该位置用 0 来代替。

示例1

输入: temperatures = [73,74,75,71,69,72,76,73]
输出: [1,1,4,2,1,1,0,0]

示例2

输入: temperatures = [30,40,50,60]
输出: [1,1,1,0]

示例3

输入: temperatures = [30,60,90]
输出: [1,1,0]

解法

func dailyTemperatures(temperatures []int) []int {
    res:=make([]int,len(temperatures))
    stack:=[]int{}
    for i:=0;i<len(temperatures);i++{
        if len(stack)==0{
            stack=append(stack,i)
            continue
        }
        for len(stack)>0 && temperatures[i]>temperatures[stack[len(stack)-1]]{
            temp:=stack[len(stack)-1]
            res[temp]=i-temp
            stack=stack[:len(stack)-1]
        }
        stack=append(stack,i)
    }
    return res
}

#### 617. 合并二叉树

给你两棵二叉树: root1 和 root2 。

想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。

返回合并后的二叉树。

注意: 合并过程必须从两个树的根节点开始。

示例1

输入: root1 = [1,3,2,5], root2 = [2,1,3,null,4,null,7]
输出: [3,4,5,5,4,null,7]

示例2

输入: temperatures = [30,40,50,60]
输出: [1,1,1,0]

示例3

输入: root1 = [1], root2 = [1,2]
输出: [2,2]

解法

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode {
    if root1==nil && root2==nil{
        return nil
    }
    if root1==nil {
        return root2
    }
    if root2==nil{
        return root1
    }
    root:=&TreeNode{}
    root.Val=root1.Val+root2.Val
    root.Left=mergeTrees(root1.Left,root2.Left)
    root.Right=mergeTrees(root1.Right,root2.Right)
    return root
}