力扣题解

41 阅读8分钟

1.两数之和

func twoSum(nums []int, target int) []int {
    m := make(map[int]int)
    for i:=0; i<len(nums); i++ {
        t := target - nums[i]
        if _, ok := m[t]; ok {
            return []int{i, m[t]}
        }
        m[nums[i]] = i
    }
    return nil
}

11.盛最多水的容器

双指针,从宽度最长开始,每次向内缩小时缩小的长度固定,所以肯定要缩小高度小的那个柱子

func maxArea(height []int) int {
    res := 0
    l := 0
    r := len(height) - 1
    for l < r {
        curWidth := getmin(height[l], height[r])
        curArea := curWidth * (r-l)
        if curArea > res{
            res = curArea
        }
        if height[l] < height[r]{
            l ++
        }else{
            r --
        }
    }
    return res
}
func getmin(a int, b int) int{
    if a < b{
        return a
    }else{
        return b
    }
}

26.删除有序数组中的重复项

遍历一次即可,因为是不严格递增有重复数组,所以可以把后面的某个数组直接覆盖前面已经扫描过的位置的值

func removeDuplicates(nums []int) int {
    pos := 0
    left, right := 0, 0
    for right < len(nums){
        nums[pos] = nums[right]
        pos += 1
        for right < len(nums) && nums[left] == nums[right]{
            right ++
        }
        left = right
    }
    return pos
}

27.移除元素

func removeElement(nums []int, val int) int {
    pos := 0
    for i:=0; i<len(nums); i++{
        if nums[i]!=val{
            nums[pos] = nums[i]
            pos ++
        }
    }
    return pos
}

35.搜索插入位置

使用左闭右闭区间,for left <= right,最后返回right+1,这个题是无重复元素的排序数组

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

28.找出字符串中第一个匹配项的下标

func strStr(haystack string, needle string) int {
    if len(needle) ==0{
        return 0
    }
    for i:=0; i<len(haystack)-len(needle)+1; i++{
        j := 0
        for ; j<len(needle); j++{
            if haystack[i+j]!=needle[j]{
                break
            }
        }
        if j==len(needle){
            return i
        }
    }
    return -1 
}

78.子集

func subsets(nums []int) [][]int {
    result := make([][]int, 0)
    curlist := make([]int, 0)
    dfs(nums, 0, curlist, &result)
    return result
}
​
func dfs(nums []int, pos int, curlist []int, result *[][]int){
    if pos == len(nums){
        *result = append(*result, append([]int(nil), curlist...))
        return
    }
    curlist = append(curlist, nums[pos])
    dfs(nums, pos+1, curlist, result)
    curlist = curlist[:len(curlist)-1]
    dfs(nums, pos+1, curlist, result)
}

155.最小栈

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

思路:用两个栈实现,一个最小栈始终保证最小值在顶部,两个栈大小永远一样

type MinStack struct {
    min []int
    stack []int
}
​
​
func Constructor() MinStack {
    return MinStack{
        min: make([]int, 0),
        stack: make([]int, 0),
    }
}
​
​
func (this *MinStack) Push(val int)  {
    this.stack = append(this.stack, val)
    curMin := this.GetMin()
    if curMin < val {
        this.min = append(this.min, curMin)
    }else{
        this.min = append(this.min, val)
    }
}
​
​
func (this *MinStack) Pop()  {
    if len(this.stack) == 0{
        return 
    }else{
        this.stack = this.stack[:len(this.stack)-1]
        this.min = this.min[:len(this.min)-1]
    }
}
​
​
func (this *MinStack) Top() int {
    if len(this.stack) == 0{
        return 0
    }else{
        return this.stack[len(this.stack)-1]
    }
}
​
​
func (this *MinStack) GetMin() int {
    if len(this.min) == 0{
        return 1<<31
    }else{
        return this.min[len(this.min)-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();
 */

150.逆波兰表达式求值

题目描述:

给你一个字符串数组 tokens ,表示一个根据逆波兰表示法表示的算术表达式。

请你计算该表达式。返回一个表示表达式值的整数。

思路:思路:通过栈保存原来的元素,遇到表达式弹出运算,再推入结果,重复这个过程

func evalRPN(tokens []string) int {
    if len(tokens) == 0{
        return 0
    }
    stack := make([]int, 0)
    for i:=0; i<len(tokens); i++{
        switch tokens[i]{
            case "+", "-", "*", "/":
                if len(tokens) < 2{
                    return -1
                }
                b := stack[len(stack)-1]
                a := stack[len(stack)-2]
                stack = stack[:len(stack)-2]
                var result int
                switch tokens[i]{
                    case "+":  
                        result = a + b
                    case "-":
                        result = a - b
                    case "*":
                        result = a * b
                    case "/":
                        result = a / b
                }
                stack = append(stack, result)
            default:
                val, _ := strconv.Atoi(tokens[i])
                stack = append(stack, val)
        }
    }
    return stack[0]
}

94.二叉树的中序遍历

栈方式模拟二叉树中序遍历

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func inorderTraversal(root *TreeNode) []int {
    result := make([]int, 0)
    if root == nil {
        return result
    }
    stack := make([]*TreeNode, 0)
    for {
        for root != nil{
            stack = append(stack, root)
            root = root.Left    //左
        }
        //弹出,根
        if len(stack) == 0 {
            break
        }
        curNode := stack[len(stack)-1]
        stack = stack[:len(stack)-1]
        result = append(result, curNode.Val)
        root = curNode.Right    //又
    }
    return result
}

133.克隆图

题目描述:给你无向连通图中一个节点的引用,请你返回该图的深拷贝(克隆)

思路:递归遍历,将遍历到的节点存入一个map中

func cloneGraph(node *Node) *Node {
    visited := map[*Node]*Node{}
    return deepClone(node, visited)
}
func deepClone(node *Node, visited map[*Node]*Node) *Node{
    if node == nil{
        return nil
    }
    if v, ok := visited[node]; ok{
        //已经访问过,直接返回
        return v
    }
    newNode := &Node{
        Val: node.Val,
        Neighbors: make([]*Node, len(node.Neighbors)),
    }
    visited[node] = newNode
    for i:= 0; i<len(node.Neighbors); i++{
        newNode.Neighbors[i] = deepClone(node.Neighbors[i], visited)
    }
    return newNode
}

200.岛屿数量

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

var next [][]int = [][]int{{1,0}, {0,1}, {-1,0}, {0,-1}}

func dfs(grid [][]byte, x int, y int){
    if x<0 || x>=len(grid) || y<0 || y>=len(grid[x]){
        return
    }
    if grid[x][y] == '0'{
        return
    }
    grid[x][y] = '0'
    for i:=0; i<4; i++{
        tx := x + next[i][0]
        ty := y + next[i][1]
        dfs(grid, tx, ty)
    }
}

095.最长公共子序列

https://leetcode.cn/problems/qJnOS7/

func longestCommonSubsequence(text1 string, text2 string) int {
    m, n := len(text1), len(text2)
    dp := make([][]int, m+1)
    for i:= range dp{
        dp[i] = make([]int, n+1)
    }
    for i, c1 := range text1{
        for j, c2 := range text2{
            if c1 == c2{
                dp[i+1][j+1] = dp[i][j]+1
            }else{
                dp[i+1][j+1] = getMax(dp[i][j+1], dp[i+1][j])
            }
        }
    }
    return dp[m][n]
}

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

优化到一维

dp[i]标识text2到i下标时,匹配的最大长度

    int longestCommonSubsequence(string text1, string text2) {
        int len1 = text1.size(), len2 = text2.size();
        vector<int> dp(len2 + 1);
        for (int i = 1; i <= len1; i++) {
            int pre = 0;
            for (int j = 1; j <= len2; j++) {
                int tmp = dp[j];
                if (text1[i - 1] == text2[j - 1]) dp[j] = pre + 1;
                else dp[j] = max(dp[j], dp[j - 1]);
                pre = tmp;
            }
        }
        return dp[len2];
    }

141.环形链表

leetcode.cn/problems/li…

func hasCycle(head *ListNode) bool {
    flag := map[*ListNode]struct{}{}
    curNodePtr := head
    for curNodePtr!=nil{
        if _, ok := flag[curNodePtr]; ok{
            return true
        }
        flag[curNodePtr] = struct{}{}
        curNodePtr = curNodePtr.Next
    }
    return false
}

435.无重叠区间

leetcode.cn/problems/no…

func eraseOverlapIntervals(intervals [][]int) int {
    n := len(intervals)
    if n==0{
        return 0
    }
    sort.Slice(intervals, func(i, j int)bool{
        return intervals[i][1] < intervals[j][1]
    })
    ans := 0
    curRight := intervals[0][1]
    for i:=1; i<n; i++{
        if intervals[i][0] < curRight{
            ans++
        }else{
            curRight = intervals[i][1]
        }
    }
    return ans
}

169.多数元素

leetcode.cn/problems/ma…

func majorityElement(nums []int) int {
    ans := nums[0]
    ansCnt := 1
    for i:=1; i<len(nums); i++{
        if nums[i] ==ans{
            ansCnt+=1
        }else{
            ansCnt -=1
            if ansCnt==0{
                ansCnt = 1
                ans = nums[i]
            }
        }
    }
    return ans
}

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

leetcode.cn/problems/co…

func buildTree(preorder []int, inorder []int) *TreeNode {
    if len(preorder)==0{
        return nil
    }
    root := &TreeNode{Val: preorder[0], Left: nil, Right: nil}
    i := 0
    for ; i<len(inorder); i++{
        if inorder[i] == preorder[0]{
            break
        }
    }
    root.Left = buildTree(preorder[1:len(inorder[:i])+1], inorder[:i])
    root.Right = buildTree(preorder[len(inorder[:i])+1:], inorder[i+1:])
    return root

}

106.从中序与后序遍历序列构造二叉树

leetcode.cn/problems/co…)

func buildTree(inorder []int, postorder []int) *TreeNode {
    if len(inorder)==0{
        return nil
    }
    root := &TreeNode{Val: postorder[len(postorder)-1], Left: nil, Right: nil}
    pos := 0
    for ; pos< len(inorder); pos++{
        if inorder[pos]==postorder[len(postorder)-1]{
            break
        }
    }
    root.Left = buildTree(inorder[:pos], postorder[:pos])
    root.Right = buildTree(inorder[pos+1:], postorder[pos:len(postorder)-1])
    return root
}

102.二叉树的层序遍历

leetcode.cn/problems/bi…)

func levelOrder(root *TreeNode) [][]int {
    if root==nil{
        return [][]int{}
    }
    ans := [][]int{}
    nodeStack := make([]*TreeNode, 0)
    nodeStack = append(nodeStack, root)
    for len(nodeStack) != 0{
        temp := []int{}
        nodeCnt := len(nodeStack)
        for i:=0; i<nodeCnt; i++{
            curNode := nodeStack[0]
            nodeStack = nodeStack[1:]
            temp = append(temp, curNode.Val)
            if curNode.Left != nil{
                nodeStack = append(nodeStack, curNode.Left)
            }
            if curNode.Right != nil{
                nodeStack = append(nodeStack, curNode.Right)
            }
        }
        ans = append(ans, temp)
    }
    return ans
}

146.LRU缓存

leetcode.cn/problems/lr…

type LRUCache struct {
    curSize int
    capacity int
    head, tail *LinkNode
    cache map[int]*LinkNode
}
type LinkNode struct{
    key, val int
    prev, next *LinkNode
}

func Constructor(capacity int) LRUCache {
    lruCache := LRUCache{
        curSize: 0,
        capacity: capacity,
        head: &LinkNode{},
        tail: &LinkNode{},
        cache: map[int]*LinkNode{},
    }
    lruCache.head.next = lruCache.tail
    lruCache.tail.prev = lruCache.head
    return lruCache
}
func (this *LRUCache) addToHead(node *LinkNode){
    node.prev = this.head
    node.next = this.head.next
    this.head.next.prev = node
    this.head.next = node
}
func (this *LRUCache) removeNode(node *LinkNode){
    node.prev.next = node.next
    node.next.prev = node.prev
}
func (this *LRUCache) moveToHead(node *LinkNode){
    this.removeNode(node)
    this.addToHead(node)
}
func (this *LRUCache) removeTail() *LinkNode{
    node := this.tail.prev
    this.removeNode(node)
    return node
}

func (this *LRUCache) Get(key int) int {
    if _, ok := this.cache[key]; !ok{
        return -1
    }
    node := this.cache[key]
    this.moveToHead(node)
    return node.val
}


func (this *LRUCache) Put(key int, value int)  {
    if _, ok := this.cache[key]; ok{
        node := this.cache[key]
        node.val = value
        this.moveToHead(node)
    }else{
        node := &LinkNode{
            key: key,
            val: value,
            prev: nil,
            next: nil,
        }
        if this.curSize < this.capacity{
            this.addToHead(node)
            this.curSize += 1
            this.cache[key] = node
        }else{
            removedNode := this.removeTail()
            delete(this.cache, removedNode.key)
            this.addToHead(node)
            this.cache[key] = node
        }
    }
}


/**
 * Your LRUCache object will be instantiated and called as such:
 * obj := Constructor(capacity);
 * param_1 := obj.Get(key);
 * obj.Put(key,value);
 */

49.字母异位词分组

leetcode.cn/problems/gr…

func groupAnagrams(strs []string) [][]string {
    mp := map[string][]string{}
    for _, str := range strs{
        s := []byte(str)
        sort.Slice(s, func(i, j int)bool{return s[i]<s[j]})
        sortedStr := string(s)
        mp[sortedStr] = append(mp[sortedStr], str)
    }
    ans := make([][]string, 0)
    for _, v := range mp{
        ans = append(ans, v)
    }
    return ans
}

128.最长连续序列

func longestConsecutive(nums []int) int {
    keyCount := map[int]int{}
    numsLen := len(nums)
    for i:=0; i<numsLen; i++{
        keyCount[nums[i]]++
    }

    longestLen := 0
    for num := range keyCount{
        if keyCount[num-1]==0{
            curNum := num
            curLen := 1
            for keyCount[curNum+1]!=0{
                curNum++
                curLen++
            }
            if curLen > longestLen{
                longestLen = curLen
            }
        }
    }
    return longestLen
}

15.三数之和

func threeSum(nums []int) [][]int {
    sort.Ints(nums)
    
    numMap := map[int]int{}
    numsLen := len(nums)
    for i:=0; i<numsLen; i++{
        numMap[nums[i]]++
    }

    type tuple struct{
        x, y, z int
    }
    tupleMap := map[tuple]bool{}

    for i:=0; i<numsLen-2; i++{
        for j:=i+1; j<numsLen-1; j++{
            thirdNum := 0-nums[i]-nums[j]
            if thirdNum < nums[j]{
                continue
            }
            if thirdNum == nums[j]{
                if thirdNum == nums[i] {
                    if numMap[thirdNum]>=3{
                        curTuple := tuple{nums[i], nums[j], thirdNum}
                        tupleMap[curTuple] = true
                    }
                }else if numMap[thirdNum]>=2{
                    curTuple := tuple{nums[i], nums[j], thirdNum}
                    tupleMap[curTuple] = true
                }
            }else if numMap[thirdNum] !=0 {
                curTuple := tuple{nums[i], nums[j], thirdNum}
                tupleMap[curTuple] = true
            }
        }
    }

    ans := [][]int{}
    for t := range tupleMap{
        curAnsNode := []int{}
        curAnsNode = append(curAnsNode, t.x)
        curAnsNode = append(curAnsNode, t.y)
        curAnsNode = append(curAnsNode, t.z)
        ans = append(ans, curAnsNode)
    }
    return ans
}

189.轮转数组

func rotate(nums []int, k int) {
    newNums := make([]int, len(nums))
    for i, v := range nums {
        newNums[(i+k)%len(nums)] = v
    }
    copy(nums, newNums)
}
func rotate(nums []int, k int) {
    k %= len(nums) // 轮转 k 次等于轮转 k%n 次
    slices.Reverse(nums)
    slices.Reverse(nums[:k])
    slices.Reverse(nums[k:])
}

56. 合并区间

func merge(intervals [][]int) [][]int {
	sort.Slice(intervals, func(i, j int) bool {
		return intervals[i][0] < intervals[j][0]
	})
	ans := [][]int{}
    start, end := intervals[0][0], intervals[0][1]
	for i := 1; i < len(intervals); i++ {
		if intervals[i][0] > end{
            ans = append(ans, []int{start, end})
            start = intervals[i][0]
            end = intervals[i][1]
        }else{
            end = getMax(end, intervals[i][1])
        }
	}
    ans = append(ans, []int{start, end})
	return ans
}
func getMin(a, b int) int {
	if a < b {
		return a
	}
	return b
}
func getMax(a, b int) int{
    if a < b{
        return b
    }
    return a
}