挑选了一些比较经典的算法题,做完多巩固。
算法
- 动态规划
- 贪心算法
目录
Array
- 11 中等 盛最多水的容器 2022-02-21
- 26 简单 删除排序数组中重复项 2022-02-22
- 66 简单 加一
- 70 简单 爬楼梯 2022-02-24
- 88 简单 合并两个有序数组
- 189 中等 旋转数组 2022-02-28
- 283 简单 移动零 2022-02-28
Linked List
- 21 中等 合并两个有序链表
- 24 中等 两两交换链表中的节点
- 25 困难 K 个一组翻转链表
- 141 简单 环形链表
- 142 中等 环形链表II
- 206 简单 反转链表
其他
- 1 简单 两数之和 2022-02-22
- 15 中等 三数之和
- 20 简单 有效的括号
- 42 困难 接雨水
- 49 中等 字母异位词分组
- 84 困难 柱状图中最大的矩形
- 155 简单 最小栈
- 239 困难 滑动窗口最大值
- 242 简单 有效的字母异位词
- 641 中等 设计循环双端队列
Binary Tree
- 22 中等 括号生成
- 94 中等 二叉树的中序遍历
- 98 中等 验证二叉搜索树
- 104 简单 二叉树的最大深度
- 105 中等 从前序与中序遍历序列构造二叉树
- 111 简单 二叉树的最小深度
- 144 中等 二叉树的前序遍历
- 226 简单 翻转二叉树
- 230 中等 二叉搜索树中第K小的元素
- 236 中等 二叉树的最近公共祖先
- 297 困难 二叉树的序列化与反序列化
- 429 简单 N叉树的层序遍历
- 589 简单 N叉树的前序遍历
- 590 简单 N叉树的后序遍历
分治
- 17 中等 电话号码的字母组合
- 50 中等 Pow(x, n)
- 78 中等 子集
- 169 简单 求众数
遍历和搜索
- 102 中等 二叉树的层次遍历
- 126 困难 单词接龙 II
- 127 中等 单词接龙
- 200 中等 岛屿数量
- 433 中等 最小基因变化
- 515 中等 在每个树行中找最大值
- 529 中等 扫雷游戏
剪枝
- 36 中等 有效的数独
- 37 困难 解数独
- 51 困难 N皇后
二分查找
- 33 中等 搜索旋转排序数组
- 69 简单 x 的平方根
- 367 简单 有效的完全平方数
贪心
- 122 简单 买卖股票的最佳时机 II
- 455 简单 分发饼干
- 860 简单 柠檬水找零
- 874 简单 模拟行走机器人
动态规划
- 32 困难 最长有效括号
- 45 困难 跳跃游戏 II
- 55 困难 跳跃游戏
- 62 中等 不同路径
- 63 中等 不同路径 II
- 64 中等 最小路径和
- 72 困难 编辑距离
- 76 困难 最小覆盖子串
- 91 中等 解码方法
- 120 中等 三角形最小路径和
- 121 简单 买卖股票的最佳时机
- 122 简单 买卖股票的最佳时机 II
- 123 困难 买卖股票的最佳时机 III
- 152 中等 乘积最大子序列
- 188 困难 买卖股票的最佳时机 IV
- 198 简单 打家劫舍
- 213 中等 打家劫舍 II
- 221 中等 最大正方形
- 279 中等 完全平方数
- 322 中等 零钱兑换
- 518 中等 零钱兑换 II
- 309 中等 最佳买卖股票时机含冷冻期
- 312 困难 戳气球
- 363 困难 矩形区域不超过 K 的最大数值和
- 403 困难 青蛙过河
- 410 困难 分割数组的最大值
- 552 困难 学生出勤记录 II
- 621 中等 任务调度器
- 647 中等 回文子串
- 714 中等 买卖股票的最佳时机含手续费
- 980 困难 不同路径 III
树
- 208 中等 实现 Trie (前缀树)
- 212 困难 单词搜索 II
位运算
- 52 困难 N皇后 II
- 136 简单 只出现一次的数字
- 190 简单 颠倒二进制位
- 191 简单 位1的个数
- 231 简单 2的幂
- 338 中等 比特位计数
并查集
- 130 中等 被围绕的区域
- 200 中等 岛屿数量
- 547 中等 朋友圈
解法
盛最多水的容器
可以使用两个 for 循环处理,但是当数据量达到某个成都的时候就会溢出。
比较好的方法就是使用双指针,时间复杂度:O(n),空间复杂度:O(1)
1 | // 双指针 |
两数之和
提示:可以使用暴力循环,也可以使用hash表。
使用暴力循环可能会超时,属于时间换空间。时间复杂度:O(n^2),空间复杂度:O(1)。
使用hash表属于空间换时间。时间复杂度:O(n),空间复杂度:O(n)。
1 | /* |
删除排序数组中重复项
题目的要求是返回不重复的长度,所以可以使用双指针(如果数组不是排序的,可以先排序之后使用这个方法)。
1 | function removeDuplicates(nums: number[]): number { |
加一
1 | function plusOne(digits: number[]): number[] { |
爬楼梯
这是一道动态规划的问题,看了教程无数次都没有很好的理解,😭。
它可以像斐波那契数列一样解决,即从上至下,f(n) = f(n-1) + f(n-2)
。
一般情况下这样的解决方式是没有问题的,但是会造成大量无用计算。
而动态规划是一种自下而上的算法。
1 | function climbStairs(n: number): number { |
只出现一次的数字
不需要额外空间的方法,就往位运算上想。
异或运算有以下三个性质。
- 任何数和
0
做异或运算,结果仍然是原来的数,即a⊕0=a
。 - 任何数和其自身做异或运算,结果是 0,即
a⊕a=0
。 - 异或运算满足交换律和结合律,即
a⊕b⊕a= b⊕a⊕a= b⊕(a⊕a)= b⊕0= b
。
1 | function singleNumber(nums: number[]): number { |
旋转数组
给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
解法有三:
- 额外数组
- 环状替换
- 翻转
1 | // 翻转 |
1 | // 一位一位的替换(类似于环状替换,但不是) |
移动零
使用双指针,当前指针遇到 0 的时候停下来,与后指针进行替换;
当两个指针都是 非0 时,各前进一步
当后指针遇到边界(即数组长度时)跳出循环
1 | function moveZeroes(nums: number[]): void { |