-
Notifications
You must be signed in to change notification settings - Fork 11
Home
创作不易,感觉有帮助到你,可以顺手star
用产品思维帮助更多的人学习算法 更多的为用户考虑而写的一个仓库
用老罗的话 彪悍的人生不需要解释 挑一点恶心的干干 先开始写算法,像打造产品一样写一个算法仓库, 帮助更多的人学习算法,同样也是自我学习的过程
Java写的算法仓库 算法最重要的是心得
准备做一个长期的算法仓库 ,像阿甘一样做个傻子,不停奔跑,每天学习一个算法,复利思维
日拱一卒,功不唐捐
把人生比作公司或者游戏的话 , 我准备长期做的事情,一个是跑步锻炼身体,一个阅读书籍(技术类,非技术类书籍),一个就是这个算法仓库了
纸上得来终觉浅 ,绝知此事要躬行
三部曲: 模仿,学习, 超越
高筑墙 , 广积粮 , 缓称王
天道酬勤,勤能补拙。博观而约取,厚积而薄发
算法: 先把一个大问题拆解成一个个小问题 , 再解决小问题 , 小问题解决了拼接起来解决大问题
磨刀不误砍柴工, 磨石不误磨刀工
坚持下去,会有突然间成长的一天
自顶向下 ,逐步求精
费曼算法: 1.将问题写下来 2. 好好思考 3.将答案写下来
最笨的学习方法 就是把抄袭一遍也是最聪明的办法,遇到晦涩难懂的知识,大脑一下子接受不了,抄袭一遍之后,大脑慢慢接受
- 冒泡排序 :BubbleSort
- 插入排序 : InsertSort 思路: 1. 每次碰到元素小的值 就往后面挪动一位 2.insertValue的值插入适当的位置
- 选择排序 SelectSort 1.选择排序每次从未排序区间中最小的元素 2.首先找出数组中最小的哪个元素 ,其次,将它和数组的第一个元素交换位置 以此类推
- 快速排序 1. 递归 2 。 二分 3. 双指针的思路
- 计数排序
- 归并排序 mergeSort 主要思想是递归 2. 主要是两个小的有序的数组合并成一个大的数组
- 希尔排序 : ShellSort 思路 : 先分组 再使用插入排序 ,再缩小间隔d
- 堆排序 :HeapSort 题解: 1. 堆存储结构是个数组 2. 先构建一个大顶堆 3 , 遍历取大顶堆 取最大值 == 牛客题解
-
二叉树问题大多使用递归解决 递归几大要素: 1.基线条件(终止条件) 2.子问题 3.递归参数 4. 递归返回值 、
-
二叉树前序遍历 // 力扣 二叉树前序遍历题解 :Solution 1. 根结点 ---> 左子树 ---> 右子树 2. 单层条件是先根节点,左节点 右节点 后使用递归 ,递归的基线条件是:root节点==null 终止
-
二叉树中序遍历 // 力扣 二叉树中序遍历:MiddleSolution : 题解: 左子树——根节点——右子树 迭代解法 :1. while 2 .入栈 3. 出栈
-
平衡二叉搜索树 : AVLTree 关键字1. LL 右旋 2.RR 左旋 3.LR 先左旋 再右旋 4 RL 先右旋 再左旋
-
二叉堆:BinaryHeap 数学要好 1. 父节点的下标是P 他的左孩子下标就是 2P+1 2P+2 2. 最大堆上浮,跟自己的父节点对比 , 比父节点大上浮, 不断对比
-
优先队列: PriorityQueue 题解:插入进行上浮操作 删除进行:最后一个替换到堆顶 , 然后进行下沉操作
-
二叉树层序遍历 // 力扣 二叉树层序遍历:LevelOrder 题解 : 先把父节点放入队列 , 然后遍历队列 , 遍历子节点 加入数值
-
二叉树的锯齿形层序遍历 // 力扣 二叉树的锯齿形层序遍历: zigzagLevelOrder 题解 : 利用双端队列锯齿形层次遍历
-
平衡二叉树 思路: 左右子树 深度差超过 1 它就不是平衡二叉树
-
翻转二叉树 思路: 左右子树 深度差超过 1 它就不是平衡二叉树
-
二叉树中的最大路径和 // 力扣 // 牛客
- 用栈实现队列 // 力扣 // 手绘图解
- 用队列实现栈 // 力扣 // 手绘图解
- 最小栈 // 力扣
- 用栈实现括号匹配 // 力扣
- 数组中元素与下一个比它大的元素之间的距离 // 力扣
- 循环数组中比当前元素大的下一个元素 // 力扣
- 删除有序数组中的重复项 : removeDuplicates 题解使用快慢指针
- 把数组中的 0 移到末尾 // 力扣 // 手绘图解
- 改变矩阵维度 // 力扣
- 最大连续 1 的个数 // 力扣
- 有序矩阵查找 // 力扣 // 手绘图解
- 有序矩阵的 Kth Element // 力扣
- 错误的集合 // 力扣 // 手绘图解
- 寻找重复数 // 力扣 // 手绘图解
- 对角元素相等的矩阵 // 力扣 // 手绘图解
- 无重复字符的最长子串:LengthOfLongestSubstring 滑动窗口
- 反转字符串
- 有序数组的 Two Sum // 力扣
- 两数平方和 // 力扣
- 反转字符串中的元音字符 // 力扣
- 回文字符串 // 力扣
- 归并两个有序数组 // 力扣
- 判断链表是否存在环 // 力扣
- 最长子序列 // 力扣
- 数组中的第K个最大元素 // 力扣
- 出现频率最多的 k 个元素 // 力扣
- 按照字符出现次数对字符串排序 // 力扣
- 颜色分类 // 力扣
- 分发饼干 // 力扣
- 不重叠的区间个数 // 力扣
- 投飞镖刺破气球 // 力扣
- 根据身高和序号重组队列 // 力扣
- 买卖股票的最佳时机 // 力扣
- 买卖股票的最佳时机2 多时段购买 // 力扣
- 判断子序列 // 力扣
- 修改一个数成为非递减数组 // 力扣
- 子数组最大的和 // 力扣
- 分隔字符串使同种字符出现在一起 // 力扣
- 二分查找 // 力扣
- 求开方 // 力扣
- 大于给定元素的最小元素 // 力扣
- 有序数组的 Single Element // 力扣
- 第一个错误的版本 // 力扣
- 旋转数组的最小数字 // 力扣
- 查找区间 // 力扣
- 计算在网格中从原点到特定点的最短路径长度 // 力扣
- 组成整数的最小平方数数量 // 力扣
- 数组区间和 // 力扣
- 数组中等差递增子区间的个数 // 力扣
- 零钱兑换322 // 力扣 : 题解: 动态规划 求F(11)最优解 ,求出F(10)+1 求出F(9)+1
- 0-1背包
- 划分数组为和相等的两部分 // 力扣
- 改变一组数的正负号使得它们的和为一给定数 // 力扣
- 01 字符构成最多的字符串 // 力扣
- 找零钱的最少硬币数 // 力扣
- 找零钱的硬币数组合 // 力扣
- 字符串按单词列表分割 // 力扣
- 组合总和 // 力扣
- 需要冷却期的股票交易 // 力扣
- 需要交易费用的股票交易 // 力扣
- 只能进行两次的股票交易 // 力扣
- 只能进行 k 次的股票交易 // 力扣
- 删除两个字符串的字符使它们相等 // 力扣
- 删除两个字符串的字符使它们相等 // 力扣
-
三数之和:ThreeNum 主要思路: 1.先排序 2.遍历每一个元素 3. 使用双指针
-
股票问题:StockProfit 如何获得最大收益 思路: 记录最小值 ,差值较大的覆盖之前的
-
缓存淘汰算法: LruCache 维护一个双向链表 ,一个hashMap 核心使用双链表记录最近使用和最久未使用的元素 ,若容量已满,淘汰最久未使用的key
-
最小栈的实现 : MinStack 加一个辅助栈记录最小值 辅助很重要
-
寻找两个数之和: FindSumNumbers 先构建map 然后再遍历
-
数组中的第k个最大元素:KthlargestNumber 题解: 1. 把数组的前K个元素构建成最小堆 2.下沉操作保持堆的有效性
-
用栈实现队列 :MyQuene 解题: 将一个栈当作输入栈,用于压入 \texttt{push}push 传入的数据;另一个栈当作输出栈
-
寻找全排列的下一个数子: DictOrderAlgo 1. 从后向前查看逆序区域 ,找到逆序区域的前一位, 也就是数字置换的边界 2. 让逆序区域的前一位和逆序区域中大于他的最小的数字交换位置 3. 把原来的逆序区域转为顺序状态
-
删除K个数字的最小值: RemoveKDigits 题解: 简化问题:如果只删除一个数字 ,如何让新整数的值最小 找出降序数字删除
-
字符串匹配算法(RK算法):RabinKarp 题解: 比较两个字符串的hash
-
KMP算法: Kmp 题解: KMP算法的整体思路:在已匹配的前缀当中寻找最长可匹配后缀子串和最长可匹配前缀子串 ,在下一轮直接把两者对齐,从而实现模式串的快速移动
-
迪杰斯特拉 : Dijkstra 思路: 维护一个距离表, 标记是否最短距离 ,动态规划更新最短距离表
- 面试题3 数组中重复的数字03:FindRepeatNumber
- 面试题4 二维数组中的查找 : TwoVeidooArrayFind 其实就是矩阵 ,以及坐标 i,j看成坐标, 用坐标系求解
- 面试题5 替换空格 ReplaceSpace
- 面试题06. 从尾到头打印链表 ReversePrint
- 面试题18. 删除链表的节点:DeleteNode 题解: 双指针解法
- 面试题22. 链表中倒数第K节点:KthFromEnd 题解: 双指针解法
- 面试题24. 单链表反转 ReverseList
- 面试题25:合并两个排序的链表 MergeTwoLists
- 设计一个有getMin功能的栈 // 力扣
- 由两个栈组成队列 // 力扣
- 如何仅用递归函数和栈操作逆序一个栈 //
- 用一个栈实现另一个栈的排序-栈排序 // 力扣
- 生成窗口最大值数组 // 力扣
- 两个链表的第一个公共节点 // 力扣
- 链表中倒数第k个节点 // 力扣
- 回文链表 // 力扣
- 移除重复节点 // 力扣
- 在单链表中删除指定值的节点 // 力扣
- 将搜索二叉树转换成双向链表 // 力扣
- 排序链表 // 力扣
- 向有序的环形单链表中插入新节点 //
- 删除链表的倒数第 n 个结点 // 力扣
- 合并两个排序的链表 // 力扣
-
二叉树中和为某一值的路径 // 力扣 // 牛客
-
二叉搜索树中两个节点之和 // 力扣
-
二叉树的锯齿形层序遍历 // 力扣
-
二叉搜索树的后序遍历序列 // 力扣 // 牛客
-
将有序数组转换为二叉搜索树 // 力扣
-
二叉搜索树的后序遍历序列 // 力扣 // 牛客
-
二叉树的最近公共祖先 // 力扣 // 牛客
-
按之字形顺序打印二叉树 // 力扣 // 牛客
-
二叉树的层序遍历 II // 力扣
####递推三部曲
递推三部曲
* 1. 边界条件
* 2. 递推公式
* 3. dp数组取值
* 套路 ; dp[i][j] 往往依赖 dp[i][i-1] dp[i-1][j] dp[i-1][j-1] 只要是动态规划就依赖这三个
- 斐波那契数列 // 力扣
- 最小路径之和 // 力扣
- 换钱的最少货币数 // 力扣
- 不同路径 II 有障碍物 // 力扣
- 零钱兑换 II // 力扣 请你计算并返回可以凑成总金额的硬币组合数
- 最长递增子序列 // 力扣
- 最长公共子序列 // 力扣
- 最长公共子串问题 // 牛客
- 最小编辑代价 // 牛客
- 字符串的交错组成 // 力扣
- 龙与地下城游戏问题 // 力扣
- 把数字翻译成字符串 // 力扣
- 跳跃游戏 // 力扣
- 最长连续序列 // 力扣
- 判断两个字符串是否互为变形词
- 判断两个字符串是否互为旋转词 // 力扣
- 字符串转换成整数 // 力扣
- 比较版本号 // 力扣
- 判断字符数组中是否所有的字符都只出现过一次 // 力扣
- 翻转字符串里的单词 // 力扣
- 最长不重复子字符串 // 力扣 // 牛客
- 最长公共前缀 // 力扣
- 最长回文子串 // 力扣
- 数组中两个字符串的最小距离 // 力扣
- 编辑距离 // 力扣
- 字典树(前缀树)的实现 // 力扣
- 转圈打印矩阵 // 力扣
- 旋转图像 // 力扣
- Z字形变化 // 力扣
- 最短无序连续子数组 // 力扣
- 二维数组中的查找 // 力扣
- 长度最小的子数组 // 力扣
- 删除排序数组中的重复项 // 力扣
- 按奇偶排序数组 II // 力扣
- 在数组中找到一个局部最小的位置 // 力扣
- 乘积最大子数组 // 力扣
- 盛最多水的容器 // 力扣
发现规律 算法核心 有什么条件 要达到什么目的 例如:回文字符串要求是正读反读结果都是一样的句子 隐含条件 偶数个字符的话 每个字符都是成对出现的 奇数字符的话 只有一个字符是单独一个的 , 其他字符都是成对出现的
- 409.最长回文串 // 力扣
- 234.回文链表 // 力扣
- 680.验证回文字符串-ⅱ.java // 力扣
- 5.最长回文子串.java // 力扣-中心扩散法 // 力扣-动态规划法
- 516.最长回文子序列.java // 力扣-动态规划法
- 647.回文子串.java // 力扣-动态规划法
- 38.外观数列.java // 力扣
- 70.爬楼梯.java
- 198.打家劫舍.java
- 213.打家劫舍-ii.java // 力扣题解-动态规划
- 337.打家劫舍-iii.java // 力扣题解-动态规划
- 322.零钱兑换.java // 力扣题解-动态规划
- 239.滑动窗口最大值.java // 力扣题解 // 题解-双指针
- 76.最小覆盖子串.java // 力扣题解 // 牛客题解
- 424.替换后的最长重复字符.java // 力扣题解
- 567.字符串的排列.java // 力扣题解
- 121.买卖股票的最佳时机.java // 力扣题解
- 122.买卖股票的最佳时机-ii.java // 力扣题解
- 714.买卖股票的最佳时机含手续费.java // 力扣题解
- 309.最佳买卖股票时机含冷冻期.java // 力扣题解
回溯法是一种复杂度很高的暴力算法 ,实现简单且有固定模板 。 不同于普通的暴力搜索 ,回溯法会在每一步判断状态是否合法,而不是等到状态全部生成后再进行确认
- 46.全排列.java // 力扣题解 // 牛客题解
- 39.组合总和.java // 力扣题解
- 40.组合总和-ii.java // 力扣题解
- 78.子集.java // 力扣题解
- 90.子集-ii.java // 力扣题解
单调栈 单调栈牛客题解
-
42.接雨水.java // 力扣题解
-
25.k-个一组翻转链表.java // 力扣题解 // 力扣题解-递归解法
数据结构的底层存储方式只有两种:数组(顺序存储)和链表(链式存储)。 数据结构是工具 ,算法是通过合适的工具解决特定问题的方法 计算机解决问题其实没有任何特殊技巧,它唯一的解决办法就是穷举
回溯算法框架:解决一个回溯问题,实际上就是一个决策树的遍历过程
- 路径:也就是已经做出的选择
- 选择列表:也就是你当前可以做的选择
- 结束条件:也就是到达决策树底层,无法再做选择的条件
- 写backtrack函数时,需要维护走过的"路径" 和当前可以做的"选择列表",当触发""结束条件"时,将"路劲"加入结果集
动态规划分为一下几步 *找到"状态"和"选择" *明确dp数组/函数的定义
- 寻找状态之间的关系 *动态规划的通用技巧:数学归纳思想
- 动态规划最优子结构以及dp遍历方向
- 反向思考问题
前面多次强调过,很显然只要涉及求最值,没有任何技巧,一定是穷举所有可能的结果,然后对比得出最值
关于"状态"的穷举,最重要的一点就是:状态转移所依赖的状态必须被提前计算出来
经典动态规划 0-1背包问题 416.分割等和子集.java 完全背包问题 518.零钱兑换-ii.java 力扣题解
二叉树算法的设计总路线:明确一个节点要做的事情,然后剩下的事抛给递归框架 ####二叉搜索树操作集锦 98.验证二叉搜索树.java 700.二叉搜索树中的搜索.java 701.二叉搜索树中的插入操作.java 450.删除二叉搜索树中的节点.java
遇到任何递归型的问题 ,无非就是"灵魂三问"" 这个函数是干什么的 这个函数参数中的变量是什么 得到函数的递归结果,你应该干什么
通过经典问题来阐明一些常用的算法技巧,比如前缀和技巧,回溯思想,暴力穷举技巧
回溯模板
result = []
def backtrack(路径,选择列表):
if 满足结束条件:
result.add(路径)
return
for 选择 in 选择列表 :
做选择
backtrack(路径,选择列表):
撤销选择
-
78.子集.java // 力扣题解
-
77.组合.java // 力扣题解
-
46.全排列.java // 力扣题解
-
22.括号生成.java // 力扣题解
// 求二进制数中1的个数
拿不准的内容绝对写在简历上, 面试过程中,面试官一定是拿着你的简历开始问问题
- 快速学习的能力
程序的性能分析离不开两个维度 一个是时间复杂度 一个是空间复杂度
- 栈区 : 由编译器自动编译释放,存放函数的参数值 局部变量的值等,其操作方式类似于数据结构中的栈
- 堆区:一般由程序员分配释放 ,若程序员不释放,则程序结束时可能由系统收回
- 为初始化数据区: 存放未初始化的全部变量和静态变量
- 初始化数据区: 存放已经初始化的全部变量 和静态变量
- 程序代码区域: 存放函数体的二进制代码
数组是存储在连续内存空间上相同类型数据的集合,在数组中,可以方便地通过下标索引的方式获取相应的数据
链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成 ,一个是数据域,另一个是指针域(存放指向下一个节点的指针) 最后一个节点的指针域指向NULL
哈希表是根据关键码的值访问数据的数据结构
- 有效的字母异位词:数组解法
- 有效的字母异位词:【哈希解法
- 两个数组的交集
- 两数之和
- 四数相加 II
- 三数之和之哈希解法 HashMap 解法不是很高效,主要是写一下解题思路吧
- 三数之和 :排序加双指针
- 四数之和
递归三部曲
- (1)确定递归函数的参数和返回值
- (2)确定终止条件
- (3)确定单层的递归逻辑
- 前序遍历之迭代解法
- 二叉树的层序遍历
- 反转二叉树
- 对称二叉树
- 二叉树的最大深度
- 二叉树的最小深度
- 平衡二叉树
- 二叉树的所有路径
- 路径总和
- 路径总和 II
- 从中序与后序遍历序列构造二叉树
- 从前序与中序遍历序列构造二叉树
- 合并二叉树
- 二叉搜索树中的搜索
- 验证二叉搜索树
- 二叉搜索树的最小绝对差
- 二叉搜索树中的众数
- 二叉树的最近公共祖先
- 二叉搜索树的最近公共祖先
- 二叉搜索树中的插入操作
- 删除二叉搜索树中的节点
- 修剪二叉搜索树
- 将有序数组转换为二叉搜索树
- 回溯法解决的问题都可以抽象为树形结构,因为回溯解决的问题都是在集合中递归查找子集,集合的大小就构成树的宽度,递归的 深度构成了树的深度
- 组合
- 组合总和 III
- 电话号码的字母组合
- 组合总和
- 组合总和 II
- 分割回文串
- 复原 IP 地址
- 子集
- 子集 II
- 递增子序列
- 全排列
- 全排列 II
- N 皇后
- 解数独
- 单词搜索
- 贪心的本质是选择每一个阶段的局部最优,从而实现全局最优
- 将问题分解为若干个子问题
- 找出适合的贪心策略
- 求解每个子问题
- 分发饼干
- 状态转移公式(递推公式)
动态规划五部曲
- (1)确定dp数组及下标的含义
- (2)确定递推公式
- (3)初始化dp数组
- (4)确定遍历顺序
- (5)举例推导dp数组
- 斐波那契数
- 爬楼梯
- 使用最小花费爬楼梯
- 不同路径
- 不同路径 II
- 整数拆分
- 不同的二叉搜索树
- 分割等和子集
- 目标和-回溯
- 目标和-动态规划
- 零钱兑换 II
- 零钱兑换
- 买卖股票的最佳时机
- 买卖股票的最佳时机 II
- 买卖股票的最佳时机 III
##算法图书
学习最笨的办法就是看书拉,也是最聪明的办法 , 博览群书总会有不一样的收获。
-
数据结构与算法分析:C语言描述_原书第2版_高清版
-
算法图解.PDF
-
数据结构 C++ .3rd_edn. 邓俊辉
-
算法4
-
算法新解
-
我的第一本算法书
-
阿里P8霜神的letCode刷题手册
-
剑指OFFER 名企面试官精讲典型编程题 第2版
-
算法设计 经典算法教材 豆瓣9.4评分
-
200349 算法笔记.胡凡
-
漫画算法 小灰的算法之旅
-
2021最新版数据结构与算法面试题手册 1
-
程序员代码面试指南 IT名企算法与数据结构题目最优解
-
程序员面试金典第六版pdf
-
对白的数据结构与算法笔记
-
对白的LeetCode笔记
-
西法的刷题秘籍-2021-04-20
- 仲尼厄而作《春秋》;屈原放逐,乃赋《离骚》;
- 左丘失明,厥有《国语》;孙子膑脚,《兵法》修列;
- 不韦迁蜀,世传《吕览》;韩非囚秦,《说难》《孤愤》;《诗》三百篇,
- 大底圣贤发愤之所为作也。此人皆意有所郁结,不得通其道,故述往事、思来者。乃如左丘无1. 目,孙子断足,终不可用,退而论书策,以舒其愤,思垂空文以自见。