Skip to content

Leetcode algorithm solutions and analyses in Golang

Notifications You must be signed in to change notification settings

nolanzzz/go-algo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GoAlgo

本仓库包含用Golang解决的Leetcode算法题题解以及笔记,学习路线主要跟随代码随想录

题目以数据结构或算法类型来分类,目录如下:

  1. 数组
  2. 哈希
  3. 链表
  4. 栈与队列
  5. 字符串
  6. 二叉树
  7. 回溯算法
  8. 贪心算法
  9. 动态规划
  10. 排序
  11. 其他算法
    1. 进制转换

数组

哈希

链表

栈与队列

字符串

二叉树

二叉树的遍历方式

求二叉树的属性

二叉树的修改与改造

求二叉搜索树的属性

二叉树公共祖先问题

二叉搜索树的修改与改造

回溯算法

组合问题

  • 组合问题其实也是一种子集问题
  • 77.组合
    • 回溯模板,res,path,start递归
  • 216.组合总和III
    • 回溯模板,res,path,start递归
    • 还需要sum记录总和
  • 17.电话号码的字母组合
    • 回溯模板,res,path,index递归
    • 数组来储存数字与字母的映射
  • 39.组合总和
    • 回溯模板,res,path,index递归
    • 由于可重复,回溯时用i而不是i+1
    • 若先排序数组,可以剪枝
  • 40.组合总和II
    • 回溯模板,res,path,index递归
    • 不可重复,回溯时用i+1
    • 需要去重操作,首先要排序数组
    • 然后递归逻辑中每次要去重(candidates[i] == candidates[i-1])
    • 可以剪枝

分割问题

  • 分隔与组合相似,组合选择变成了切割点
  • 131.分割回文串
    • 回溯模板,res,path,start递归
    • 判断回文,不符合时continue
    • 终止条件为到达末尾
  • 93.复原IP地址
    • 回溯模板,res,path,start递归
    • 判断每段地址是否合法
    • 终止条件为1.到达末尾;2.path有四段地址

子集问题

  • 求取子集问题,不需要任何剪枝!因为子集就是要遍历整棵树
  • 78.子集
    • 回溯模板,res,path,start递归
    • 每次递归先保存当前path至res
    • 终止条件可以省略,因为for循环遍历至最后一个数字时自然结束
  • 90.子集II
    • 与78.子集一个套路
    • 需要去重操作,首先要排序数组
    • 然后递归逻辑中每次要去重
  • 491.递增子序列
    • 回溯模板,res,path,start递归
    • 根据题目条件,当path有两个元素时即可保存,保存后继续往后走
    • 需用used来记录本层用过的数字,以免重复搜索同样的数字开头的子序列

排列问题

  • 排列问题是有序的,所以每次循环都要从0开始,不需要start参数
  • 去重时需要用used来记录
  • 46.全排列
    • 回溯模板,res,path
    • used记录出现过的元素,同样要回溯
  • 47.全排列II
    • 回溯模板,res,path
    • used记录出现过的元素,同样要回溯
    • 需要去重:
      1. 已经搜索过以第i个数字开头的排列,跳过
      2. 重复的数字,规定按从左到右的顺序搜索,还没有搜索过第i-1个数时跳过

重新安排行程(图论额外拓展)

  • 332.重新安排行程
    • 回溯模板,res,不需要path了,因为此时res相当于path,找到一条符合要求的path时便结束了
    • 需要一个map来记录起点和终点的映射
    • map需要根据终点排序,这样最终的结果才是根据字典排序的
    • 终止条件:当res的路径数等于tickets数加一时结束

棋盘问题

  • 51.N皇后
    • 回溯模板,board来记录棋盘状态,row记录当前的行
    • 递归遍历行
    • 递归里的for遍历列
    • 终止条件:当row = n时,完成了所有行
    • 检查是否合法时,查看列、45度和135度上斜线即可
  • 37.解数独
    • 回溯模板,board记录棋盘状态
    • 需要遍历所有行所有列,以及1-9的值,找到当前cell合适的值直接返回true
    • 没有合适的值返回false
    • 检查是否合法时,查看行、列、以及九宫格

贪心算法

简单题

  • 455.分发饼干
    • 局部最优:大饼干喂给胃口大的孩子,不造成饼干尺寸的浪费
    • 全局最优:喂饱尽可能多的孩子
    • 排序饼干和孩子胃口
    • 双指针
  • 1005.K次取反后最大化的数组和
    • 局部最优:将绝对值最大的负数变为正,从而最大化当前数值
    • 整体最优:将尽可能多的负数取反为正,或将最小的正数取反,最大化总和
    • 第一步 按绝对值从大到小排序
    • 第二步 从头开始遍历,遇到负数便取反操作,k--
    • 第三步 如k还大于0,则继续操作取反绝对值最小的那个数
    • 第四部 求和
  • 860.柠檬水找零
    • 局部最优:碰到20的账单,优先消耗10元面值,再消耗5元,因为5元能用来找零的场景更多
    • 全局最优:完成全部找零

中等题

  • 376.摆动序列
    • 无需删除操作,只用记录符合条件的节点数,也就是数组的峰值数量
    • 记录currDiff和preDiff用来比较
  • 738.单调递增的数字
    • 需从后往前遍历,然后一个flag记录从哪里开始赋值为9,例:987 -> flag为1 -> 899
    • 局部最优:当遇到num[i-1] > num[i]的情况,将num[i-1]减1,num[i]赋值为9,可以保证这两位变成最大的单调递增整数
    • 全局最优:得到小于等于N的最大单增整数
  • 908.最小差值I
    • 找出nums中的最小值和最大值
    • 它们最多可以分别增加和减少k
    • 最小差值则是(max-k)-(min+k),若得负数则返回0
  • 910.最小差值II
    • 排序数组
    • 在排序后的数组中i下标处切一刀,左边小的这部分集体+k,右边大的部分集体-k
    • 初始化也覆盖了一种情况,就是不切,所有数增加或减少k,diff不变
    • 遍历寻找i点,使得新的max-min最小

贪心解决股票问题

  • 122.买卖股票的最佳时机II
    • 把利润分解为每天为单位的维度,而不是从0天到第n天整体去考虑
    • 局部最优:收集每天的正利润,也就是只收集当利润为正时
    • 全局最优:求得最大利润
  • 714.买卖股票的最佳时机含手续费
    • 局部最优:最低值买,最高值卖(算上手续费后依然盈利)
    • 全局最优:利润最大
    • 股票问题常规解法是用动态规划

两个维度权衡问题

在出现两个维度相互影响时,不要一起考虑,先确定一个维度,再确定另一个维度

  • 135.分发糖果
    • 两次贪心
      • 第一次:从左到右遍历,确保评分高的右孩子比左孩子的糖多
      • 第二次:从右到左遍历,确保评分高的左孩子比右孩子的糖多(贪心:既比左边多也比右边多)
    • 全局最优:中间的孩子比两边的孩子糖多
  • 406.根据身高重建队列
    • 先身高h从高到矮排序
    • 局部最优:优先按身高高的people的k来插入,插入后的people满足队列属性
    • 全局最优:全部插入,并符合属性

贪心难题

贪心解决区间问题

各种覆盖各种去重

  • 55.跳跃游戏
    • 判断最大的跳跃范围是否能大于等于数组最后一位
    • 局部最优:每次取最大的跳跃范围
    • 全局最优:最后得到整体能跳到的最大范围
  • 45.跳跃游戏II
    • 需要统计两个覆盖范围:当前这一步的最大覆盖 和 下一步的最大覆盖
    • 局部最优:当前可移动距离尽量多走,如果还没到终点,步数再加一
    • 整体最优:每一步都尽可能多走,达到最小步数
  • 452.用最少数量的箭引爆气球
    • 按左边界(起点)排序,从左向右遍历
    • 局部最优:当气球重叠时,一起射,所用弓箭最少
    • 全局最优:把所有气球射爆所用的箭最少
  • 435.无重叠区间
    • 按右边界(终点)排序,从左向右遍历
    • 局部最优:优先选右边界小的区间,所以从左向右遍历,留给下一个区间的空间更大,从而尽量避免交叉
    • 全局最优:选取最多的非交叉区间
  • 763.划分字母区间
    • 统计每个字母的最远边界
    • 从头遍历,更新当前遍历到的字母的最远边界,如果最远边界与当前坐标重合,则为切割点
    • 不算是严格的贪心,因为不存在局部最优
  • 56.合并区间
    • 按左边界排序,从左向右遍历
    • 局部最优:每次合并都取最大的右边界,可以合并更多的区间
    • 整体最优:合并所有重叠的区间

其他难题

  • 53.最大子数组和
    • 遍历每次将nums[i]更新为当前子数组的最大和,并判断是否大于max
    • 局部最优:当前连续和为负数的时候立刻放弃(不跟新nums[i]),从下一个元素重新计算连续和,因为负数加上下一个元素只会越来越小
    • 全局最优:选取最大连续和
  • 134.加油站
    • curSum记录当前起始点start的累加,totalSum记录全部的累加
    • 遍历,curSum小于0时起始点start加1
    • 若totalSum小于0,则不可能跑完一圈
    • 局部最优:curSum小于0时探索下一个起始点
    • 全局最优:找到可以跑一圈的起始点
  • 968.监控二叉树
    • 交叉类难题
    • DFS,从叶节点向根节点递归遍历
    • 每次递归返回状态码:0:没有覆盖,1:有摄像头,2:已覆盖
    • 局部最优:让叶节点的父节点安装摄像头,每隔两个节点放一个摄像头
    • 全局最优:摄像头最少

动态规划

  • 动态规划理论基础

  • 509.斐波那契数

    • dp[i]:第i个斐波那契数
    • 递推公式:dp[i] = dp[i-1] + dp[i-2]
    • 初始化:dp[0] = 1, dp[1] = 1
    • 遍历顺序:从前往后
  • 70.爬楼梯

    • dp[i]:爬到第i阶有几种方法
    • 递推公式:dp[i] = dp[i-1] + dp[i-2]
    • 初始化:dp[0]不用考虑,dp[1] = 1, dp[2] = 2
    • 遍历顺序:从前往后
  • 746.使用最小花费爬楼梯

    • dp[i]:爬到第i阶的最小花费
    • dp[0] = cost[0], dp[1] = cost[1]
  • 62.不同路径

    • dp[i][j]:到达ixj网格有多少条不同的路径
    • 初始化:所有行的第一列 和 所有列的第一行 都为1
    • 两层遍历
  • 63.不同路径II

    • dp[i][j]:到达ixj网格有多少条不同的路径
    • 初始化:所有行的第一列 和 所有列的第一行 (没有障碍的) 都为1
    • 两层遍历
  • 343.整数拆分

    • dp[i]:整数i的最大拆分乘积
    • dp[2]=1
    • 两层遍历,每次用j * (i-j) 和 j * dp[i-j]的较大值与已经dp[i]比较取最大值
  • 96.不同的二叉搜索树

    • dp[i]:1到i为节点组成的二叉搜索树的个数为dp[i]
    • dp[0] = 1
    • 两层遍历,每次要累加j从1到i作为根节点的树数量

背包问题

0-1背包

  • 0-1背包理论基础
  • 416.分割等和子集
    • 一维数组
      • dp[j]:容量为j的背包能放的最大数值和
      • 初始化:全部为0
      • 两层遍历(j要倒序)
      • dp[j] = max(dp[j], dp[j-nums[i]]+nums[i])
    • 二维数组
      • dp[i][j]:从0-i下标的数值里任选放入容量为j的书包的最大数值和
      • 初始化:dp[i][0]=0; 当j>=nums[0]时dp[0][j]=nums[0]
      • 两层遍历
      • dp[i][j] = max(dp[i-1][j], dp[i-1][j-nums[i]]+nums[i])
    • 1049.最后一块石头的重量II
      • 一维数组
        • dp[j]:容量为j的背包能放的最大数值和
        • dp[j] = max(dp[j], dp[j-stones[i]]+stones[i])
      • 二维数组
        • dp[i][j]:0-i下标的石头范围内,能装入容量为j的最大重量
        • dp[i][j] = max(dp[i-1][j], dp[i-1][j-stones[i]]+stones[i])

排序

其他算法

进制转换问题

数学问题

About

Leetcode algorithm solutions and analyses in Golang

Topics

Resources

Stars

Watchers

Forks

Languages