12 2020 档案
摘要:思路: 参考左神P187 1. 状态的定义:dp[i][j]表示从左上角即(0,0)位置走到(i,j)位置的最小路径和。 2. 特殊情况: 对于矩阵第一行的所有位置,从(0,0)走到(0,j)只能一直往右走。同理, 对于矩阵第一列的所有位置,从(0,0)走到(i,0)只能一直往下走。 3. 除了第一
阅读全文
摘要:【举一反三】:最大路径和——数字三角形问题(动态规划) ☆☆☆思路:动态规划 ——> 空间优化(使用一维数组而不是二维数组,这样只使用了O(n)的额外空间。) class Solution { public int minimumTotal(List<List<Integer>> triangle)
阅读全文
摘要:☆☆☆☆☆思路:与N皇后问题类似。 class Solution { public void solveSudoku(char[][] board) { if (board == null || board.length == 0) return; dfs(board); } private boo
阅读全文
摘要:☆☆☆☆思路:如果在(i,j)处放置了一个皇后,那么 1. 整个第 i 行的位置都不能放置; 2. 整个第 j 列的位置都不能放置。 3. 如果位置(a,b)满足|a-i|==|b-j|,说明(a,b)和(i,j)处在同一条斜线上,也不能放置。 代码1(参考左神书,耗时2ms): class Sol
阅读全文
摘要:N皇后问题也可以转化为树形问题,每一层代表格子的一行,每一个节点都有N种选择。 思路1:以52题的解法为基础,当递归到底时,根据record[]数组的状态信息,还原出皇后的位置。 判断斜线的方法(参考左神):如果(a,b)满足|a-i|==|b-j|,说明(a,b)和(i,j)处在同一条斜线上。 思
阅读全文
摘要:☆☆☆思路:类似于130题。从边界开始扩展。 建立两个矩阵Atlantic和Pacific, 当Atlantic[i][j]和Pacific[i][j]同时为true时表示该位置可以同时到达Atlantic和Pacific 遍历时的技巧为: 只需要从四个边界开始遍历即可(类似Flood Fill的思
阅读全文
摘要:思路1:DFS 如果把X看作海水,O看作陆地,被海水包围的就是岛屿。没有被海水包围的陆地,与边界有连通,就不是岛屿。判断是否是岛屿比较困难,问题转化为先找出非岛屿(凡是与边界有联系的O),即对边界上的 O 特殊处理。根据题意,四个边的 0 以及与其相邻的 0 都不能被替换为X,因此从边界向里面扩展。
阅读全文
摘要:思路:本题是经典的Flood Fill(泛洪)问题,即染色问题 或 颜色填充问题。 这类问题需要把与(i,j)相连接的岛屿都标记上,而不是在其中找到某个序列或者某个值,所以只标记true,不需要进行状态重置。 代码1(修改输入数据): class Solution { public int numI
阅读全文
摘要:☆☆☆☆思路:二维平面上的回溯法。 先将问题转化为树形问题,每一个点都有四个方向可以走,若规定顺时针即为“上->右->下->左”。 注意:关于标记某个格子是否被访问过有两个思路,一是设置visited[][]布尔数组,二是直接修改输入数据,回溯时再改回来。 在具体面试中,需要询问面试官是否可以修改输
阅读全文
摘要:class Solution { private List<String> res = new LinkedList<>(); public List<String> readBinaryWatch(int num) { dfs(num, 0, 0, 1, 1, new LinkedList<Int
阅读全文
摘要:☆☆思路:做完1 和 2之后,直接套模板就完了。刚开始可以把1到9放入数组中,然后回溯搜索。 AC后再去掉数组进行优化。 class Solution { public List<List<Integer>> combinationSum3(int k, int n) { List<List<Int
阅读全文
摘要:思路:回溯搜索 + 剪枝。 注意,回溯做选择的方法,不适用于有 “有重复元素的数组”。因此,重点掌握 常规回溯算法的写法。 class Solution { public List<List<Integer>> combinationSum2(int[] candidates, int target
阅读全文
摘要:☆☆☆代码: 排序剪枝后效率更高 ~ class Solution { public List<List<Integer>> combinationSum(int[] candidates, int target) { List<List<Integer>> res = new ArrayList<
阅读全文
摘要:☆☆☆☆思路:回溯 + 剪枝。 如果使用Set去重,不能AC class Solution { public List<List<Integer>> subsetsWithDup(int[] nums) { List<List<Integer>> res = new ArrayList<>(); A
阅读全文
摘要:☆☆☆思路:回溯算法。注意对比区分这三道题:求排列、求组合、求子集。 求组合 和 求子集 方法的对比: 更新res的位置不同:求组合时,res 的更新是当树到达底端时;而求子集,res的更新是树上每一个节点,走过的路径都是子集的一部分。 求组合 和 求排列 方法的对比: 树的形状不同:排列问题的树比
阅读全文
摘要:☆☆☆思路:与排列问题不同,组合问题只需要从当前位置往后搜索。而排列问题每次都需要从头寻找,需要用vis数组记录访问过的元素。 class Solution { public List<List<Integer>> combine(int n, int k) { List<List<Integer>
阅读全文
摘要:思路1:回溯搜索全排列,使用Set暴力去重。 ☆☆☆思路2:回溯搜索 + 剪枝。 对原数组排序,保证相同的数字都相邻,然后每次填入的数一定是这个数所在重复数集合中「从左往右第一个未被填过的数字」 代码1:回溯搜索 + Set去重 代码1.1 ——交换位置确定数字(耗时:30ms) class Sol
阅读全文
摘要:【举一反三】: 剑指27.字符串的排列 ☆☆回溯算法入门级经典题目,理论讲解及分类习题:回溯算法入门级详解 + 练习(持续更新) 思路1:标记数组 思路2:交换位置。相比思路1,空间复杂度低。 class Solution { public List<List<Integer>> permute(i
阅读全文
摘要:☆☆☆思路1:递归+回溯 思路2:动态规划。 M class Solution { public List<List<String>> partition(String s) { List<List<String>> res = new ArrayList<>(); dfs(s, 0, new Ar
阅读全文
摘要:☆☆☆☆思路:回溯算法. 回溯算法事实上就是在一个树形问题上做DFS。因此,需要先将原问题转化为树形问题 每一个节点可以选择截取的方法有三种:截1位、截2位、截3位。因此每一个结点可以生长出的分支最多只有 3 条分支; 由于 ip 段最多就 4 个段,因此这棵三叉树最多 4 层,这个条件作为递归终止
阅读全文
摘要:☆☆☆思路:递归。本题是典型的树形问题 使用StringBuilder要比拼接String效率高,但注意需要回溯操作。 class Solution { List<String> res; // 作为类的一个成员变量 String[] map = new String[]{ "", "", "abc
阅读全文
摘要:☆☆☆思路:二叉搜索树的删除操作是最难的。。。 class Solution { public TreeNode deleteNode(TreeNode root, int key) { /** * 知识点: * 1. BST的递归模板 * 2. BST删除某个节点,可以将其替换为左子树的最右节点
阅读全文
摘要:思路:中序遍历 递归 / 非递归 class Solution { int count = 0; int res = 0; public int kthSmallest(TreeNode root, int k) { inOrder(root, k); return res; } private v
阅读全文
摘要:思路:和108题类似,链表需要通过双指针寻找中间节点。 class Solution { public TreeNode sortedListToBST(ListNode head) { if (head == null) return null; if (head.next == null) re
阅读全文
摘要:☆☆思路:BST的中序遍历时升序的,因此本题等同于根据中序遍历的序列恢复二叉搜索树。 可以选择中间数字作为二叉搜索树的根节点,这样分给左右子树的数字个数相同或只相差 1,可以使得树保持平衡。 class Solution { public TreeNode sortedArrayToBST(int[
阅读全文
摘要:☆☆☆思路:经典的LCA问题 class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if (root == null) return null; if (p ==
阅读全文
摘要:☆☆思路:中序遍历时,判断当前节点是否大于中序遍历的前一个节点,如果大于,满足BST,继续遍历;否则返回false。 技巧点:保存前一个节点 + 中序遍历 class Solution { TreeNode pre = null; public boolean isValidBST(TreeNode
阅读全文
摘要:class Solution { int min = Integer.MAX_VALUE; TreeNode pre = null; public int getMinimumDifference(TreeNode root) { inOrder(root); return min; } priva
阅读全文
摘要:二分搜索树: 1. 每个节点的键值大于左孩子; 2. 每个节点的键值小于右孩子; 3. 以左右孩子为根的子树仍为二分搜索树。 ☆☆思路:中序遍历,计算相邻数的差值 class Solution { int min = Integer.MAX_VALUE; TreeNode pre = null; /
阅读全文
摘要:☆☆ class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { /** * 方法1:递归 */ if (p.val < root.val && q.val < root
阅读全文
摘要:【举一反三】:在二叉树中找到累加和为指定值的最长路径长度 左神P115 ☆☆☆☆思路1:双重递归,第一个递归用来遍历这些节点,这二个递归用来处理这些节点,进行dfs。 思路1的缺点是存在大量重复计算,时间效率差 ☆☆☆☆☆思路2:前缀和 递归回溯。 时间复杂度为O(n),空间复杂度为O(n) 代码1
阅读全文
摘要:最笨的方法可以先求出所有的路径,然后转换成对应的数字,最后求和。但是时间效率很差(耗时3ms) ☆☆☆方法1:DFS 方法2:BFS 代码1:DFS(耗时0ms) class Solution { public int sumNumbers(TreeNode root) { return dfs(r
阅读全文
摘要:本题同剑指24.二叉树中和为某一值的路径 本题相似题目:LeetCode257. 二叉树的所有路径 ☆☆☆☆☆方法1:DFS前序遍历 + 回溯 ☆☆方法2:BFS层序遍历。 ☆☆☆方法3:递归 代码1:DFS前序遍历 + 回溯(耗时1ms) class Solution { public List<
阅读全文
摘要:一看就会一写就废(╯﹏╰) ☆☆☆方法1:DFS前序遍历。路径是从根开始的, 于是想到前序遍历 ☆☆☆方法2:BFS层序遍历。 ☆☆☆☆方法3:递归。 代码1: class Solution { public List<String> binaryTreePaths(TreeNode root) {
阅读全文
摘要:背景知识: 完全二叉树:除了最后一层,所有层的节点数达到最大,与此同时,最后一层的所有节点都在最左侧。(堆使用完全二叉树) 满二叉树:所有层的节点数达到最大。一棵层数为 h 的满二叉树,其节点数为2^h - 1个。 思路1:层序遍历 或 递归 遍历整棵树。 但没用到 完全二叉树 的性质。。不可取 思
阅读全文
摘要:☆方法1:递归 方法2:BFS class Solution { public int sumOfLeftLeaves(TreeNode root) { /** * 方法1:递归 */ if (root == null) return 0; // 对当前节点进行处理 int count = 0; i
阅读全文
摘要:平衡二叉树:每一个节点的左右子树的高度差不超过1. 对于一颗树,它是一个平衡二叉树需要满足三个条件:它的左子树是平衡二叉树,它的右子树是平衡二叉树,它的左右子树的高度差不大于1。 本题同:剑指39.平衡二叉树 本题的递归关键是找好递归的返回值。 ☆☆☆思路1:自顶向下的递归,类似于前序遍历。借助一个
阅读全文
摘要:相同题目:剑指58.对称的二叉树 ☆☆☆☆方法1:递归。总体思路是判断两个子树相反位置上的值是否相等。 ☆☆☆☆方法2:迭代。 需要注意:如果二叉树所有节点值都相等,但结构不同仍然不对称,因此需要把节点是 null 的情况考虑进来。 class Solution { public boolean i
阅读全文
摘要:class Solution { public boolean isSameTree(TreeNode p, TreeNode q) { if (p == null && q == null) return true; if (p == null || q == null) return false
阅读全文
摘要:☆☆☆方法1:递归 ☆☆☆方法2:BFS。使用两个队列,分别存储将要遍历的节点,以及根节点到这些节点的路径和。 拓展练习:打印路径 >LeetCode113. 路径总和 II、 剑指24.二叉树中和为某一值的路径 class Solution { public boolean hasPathSum(
阅读全文
摘要:☆☆☆思路:剑指18.二叉树的镜像 方法1:递归。二叉树此类递归问题,要以根节点为目标点进行分析。 思路1:首先分别翻转根节点的左右子树,然后交换左右子树的位置即可。 思路2:也可以先交换左右子树的位置,然后再分别翻转根节点的左右子树。 方法2:BFS层序遍历 层序遍历树的所有节点,然后交换其左右节
阅读全文
摘要:☆☆☆方法1:递归,需要注意二叉树退化成链表的情况,要单独处理没有左子树或没有右子树的特殊情况 方法2:BFS。二叉树层序遍历 ☆☆☆方法3:DFS class Solution { int min = Integer.MAX_VALUE; public int minDepth(TreeNode
阅读全文
摘要:class Solution { public int maxDepth(TreeNode root) { /** * 方法1:递归 */ if (root == null) return 0; int left = maxDepth(root.left); int right = maxDepth
阅读全文
摘要:方法1:使用优先队列合并 方法2:分治法,两两合并 代码1:优先队列 class Solution { public ListNode mergeKLists(ListNode[] lists) { /** * 方法1:使用优先队列 * 把链表的头结点都放进去,然后出队当前优先队列中最小的,接上链表
阅读全文
摘要:☆☆☆☆☆思路:本题是127题的进阶版,需要将找到的最短路径存储下来。 方法1:BFS。在到达最短路径所在的层时,记录并输出所有符合条件的路径。 1. 127题的队列只存储每一层的元素,本题中队列需要存储每层添加元素之后的结果。 2. 如果该层添加的某一个单词符合目标单词,则该路径为最短路径,该层为
阅读全文
摘要:为什么要用BFS? 无向图求最短路,广搜最为合适,广搜只要搜到了终点,那么一定是最短的路径。因为广搜就是以起点中心向四周扩散的搜索。 本题是一个无向图,需要用标记位,标记着节点是否走过,否则就会死循环! ☆☆☆方法1:BFS ☆☆☆☆方法2:双向BFS,减少搜索空间大小。 BFS的搜索空间大小依赖于
阅读全文
摘要:首先不能使用贪心算法,以12为例,如果用贪心则为 12 = 9 + 1 + 1 + 1, 与实际情况12 = 4 + 4 + 4不符。 ☆☆☆☆思路1: BFS。 一层一层的算,第一层依次减去一个平方数得到第二层,第二层依次减去一个平方数得到第三层。直到某一层出现了 0,此时的层数就是我们要找到平方
阅读全文
摘要:class Solution { public List<Integer> rightSideView(TreeNode root) { List<Integer> res = new ArrayList<>(); if (root == null) return res; Queue<TreeNo
阅读全文
摘要:class Solution { public List<List<Integer>> zigzagLevelOrder(TreeNode root) { List<List<Integer>> res = new ArrayList<>(); if (root == null) return re
阅读全文
摘要:class Solution { public List<List<Integer>> levelOrderBottom(TreeNode root) { List<List<Integer>> res = new ArrayList<>(); if (root == null) return re
阅读全文
摘要:思路:队列的基本使用 - > 广度优先遍历 class Solution { public List<List<Integer>> levelOrder(TreeNode root) { List<List<Integer>> res = new ArrayList<>(); if (root ==
阅读全文
摘要:☆☆☆ public class NestedIterator implements Iterator<Integer> { /** * // 如果其中存的是一个整数,则返回 true,否则返回 false * public boolean isInteger(); * // 如果其中存的是一个整数
阅读全文
摘要:一、前中后序递归 1. 前序递归( 时间复杂度O(n)、空间复杂度O(n) ) class Solution { public List<Integer> preorderTraversal(TreeNode root) { List<Integer> res = new ArrayList<>()
阅读全文
摘要:class Solution { public List<Integer> postorderTraversal(TreeNode root) { /** * 方法1:递归 */ /* List<Integer> res = new ArrayList<>(); dfs(root, res); re
阅读全文
摘要:class Solution { public List<Integer> inorderTraversal(TreeNode root) { /** * 方法1: 递归 * 时间复杂度:O(n) 空间复杂度:O(n) */ /* List<Integer> res = new ArrayList<
阅读全文
摘要:思路1:递归。 思路2:非递归。使用栈模拟递归。 class Solution { public List<Integer> preorderTraversal(TreeNode root) { /** *方法1:递归 * 时间复杂度O(n) * 空间复杂度O(n)为递归中栈的开销,平均情况为 O(
阅读全文
摘要:☆☆思路:使用字符串的split方法,以'/'为分隔符区分字符,然后逐步识别符号'..'与字母,'.'可以直接忽略,还需要注意空的情况。 class Solution { public String simplifyPath(String path) { // 需要注意连着的// 分出来是空 Str
阅读全文
摘要:class Solution { public int evalRPN(String[] tokens) { // 遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中。 Stack<Integer> stack = new Stack<>(); int num; for (Stri
阅读全文
摘要:class Solution { public boolean isValid(String s) { if (s == null || s.length() == 0) return true; /** * 解法1: */ /*Stack<Character> stack = new Stack<
阅读全文
摘要:链表的归并操作不需要额外空间,因而使用归并排序符合本题常数级空间复杂度的要求。最适合单链表的排序算法是归并排序。 ☆☆☆思路1:自顶向下的归并排序(递归) 时间复杂度O(nlogn), 空间复杂度O(logn),其中空间复杂度主要取决于递归调用的栈空间。 主要考察:1)归并排序思想;2)寻找链表中间
阅读全文
摘要:☆☆☆思路:关键点是每次从前往后寻找插入位置。 class Solution { /** * 每次拿出未排序的节点,先和前驱比较,如果大于或者等于前驱,就不用排序了,直接进入下一次循环 * 如果前驱小,则进入内层循环,每次从头开始比较,插入对应位置即可。 */ public ListNode ins
阅读全文
摘要:思路:【快慢指针 + 反转链表】通过快慢指针找到中间节点 > 切成两个链表 > 对后半部分进行reverse操作 > 依次比较前部分和后部分的值 与LeetCode143. 重排链表解法类似。 class Solution { public boolean isPalindrome(ListNode
阅读全文
摘要:自己想的方法是: 1. 求出链表长度 2. 找出倒数第K个节点的前一个节点 3. 断开链表,寻找后半部分链表的末尾节点,然后接上前半部分 上述方法的缺点是:寻找后半部分链表的末尾节点又需要遍历一次。 改进思路1:通过快慢指针寻找倒数第k个节点的前一个节点,最后快指针指向后半部分链表的末尾节点 改进思
阅读全文
摘要:思路: 快慢指针找到中间节点,切成两半。(注意链表长度的奇偶性) 后半部分 reverse 操作。 归并操作,即后半部分 塞到 前半部分的“缝隙”里,组成新的链表。 class Solution { public void reorderList(ListNode head) { if (head
阅读全文
摘要:思路:同剑指14.链表中倒数第k个结点 class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { /** * 方法1:计算链表长度,相当于两次遍历链表 */ /* ListNode dummyHead = ne
阅读全文
摘要:☆☆思路:改变链表节点的值。首先将下一个节点的值赋给node,然后直接跳过下一个节点(删除下一个节点)。 class Solution { public void deleteNode(ListNode node) { node.val = node.next.val; node.next = no
阅读全文
摘要:☆☆☆☆【字节】 很综合的一道题目,用到 [LeetCode206. 反转链表] class Solution { public ListNode reverseKGroup(ListNode head, int k) { if (head == null || head.next == null)
阅读全文
摘要:方法1: class Solution { public ListNode swapPairs(ListNode head) { if (head == null || head.next == null) return head; ListNode dummyHead = new ListNode
阅读全文
摘要:解法:本题同剑指16.合并两个排序的链表 class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { /** * 解法1: 非递归 */ ListNode dummyHead = new ListNode(-1
阅读全文
摘要:☆☆☆☆解法:本题同剑指56.删除链表中重复的结点 class Solution { public ListNode deleteDuplicates(ListNode head) { if (head == null || head.next == null) return head; ListN
阅读全文
摘要:class Solution { public ListNode removeElements(ListNode head, int val) { if (head == null) return null; ListNode dummyHead = new ListNode(-1); dummyH
阅读全文
摘要:☆☆思路:栈 + 头插法。本题要求不能对节点进行翻转,那么对于逆序处理,首先应该想到数据结构【栈】。 class Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { // 不能对节点进行翻转,故用到数据结构【栈】
阅读全文
摘要:☆☆☆解法:考虑进位值 以及 较短的链表补0 class Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { ListNode dummyHead = new ListNode(0); ListNode cur =
阅读全文
摘要:思路1:类似LeetCode86. 分隔链表,设置两个虚拟头节点,最后拼接即可。 ☆☆思路2:分离节点后合并,不需要设置虚拟头节点 class Solution { public ListNode oddEvenList(ListNode head) { if (head == null || he
阅读全文
摘要:☆☆思路:要设置两个虚拟头节点 class Solution { public ListNode partition(ListNode head, int x) { if (head == null || head.next == null) return head; ListNode smallD
阅读全文
摘要:☆☆解法 class Solution { public ListNode deleteDuplicates(ListNode head) { if (head == null || head.next == null) return head; ListNode cur = head; while
阅读全文
摘要:☆☆☆思路:虚拟头节点 + 反转链表 class Solution { public ListNode reverseBetween(ListNode head, int m, int n) { if (head == null || head.next == null || m == n) ret
阅读全文
摘要:方法1:迭代反转链表。 ☆☆☆方法2:递归反转链表。 class Solution { // ListNode pre = null, next = null; // 方法3全局变量 public ListNode reverseList(ListNode head) { /** * 方法1:迭代法
阅读全文
摘要:class Solution { public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) { /** * 本题与219题仅在判断部分有改动 * 时间复杂度O(nlogn) 空间复杂度O(k) */ TreeSet<
阅读全文
摘要:☆☆☆☆☆(不是很理解....太绕了 T_T) 思路:二分 + 双指针。题目要求第K个最小距离,所以如果我们有一个有序数组记录着所有可能的最小距离,那么问题就可以变成一个最简单的二分法求解了 本题的难点在于二分查找的不是某个数,而是两个数的差值(即距离)。需要使用双指针来计算出所有小于等于mid的距
阅读全文
摘要:思路:查找表 + 滑动窗口(窗口大小固定) class Solution { public boolean containsNearbyDuplicate(int[] nums, int k) { /** * 方法1:哈希 */ /* Map<Integer,Integer> map = new H
阅读全文
摘要:首先想到的思路是:利用N皇后问题解法中,通过|a-i| == |b-j| 判断 (a,b)和(i,j)是否在同一条斜线上。但是很多测试用例过不了。。。(例如[[0,0],[1,1],[1,-1]] 输出2) 本题思路:固定一点, 找其他点和这个点组成直线, 统计他们的斜率! class Soluti
阅读全文
摘要:一、题目描述 ☆☆☆☆☆二、解法 思路:暴力解法是O(n^3) 观察到 i 是一个“枢纽”,对于每个点 i ,遍历其余的点到 i 的距离。 时间复杂度O(n^2),空间复杂度O(n) 使用Map,其键是距离,值是距离出现的频次。 例如,如果距离值 dis 对应的频次为1,那就无法找到两个点与 i 距
阅读全文
摘要:一、题目描述 ☆☆☆☆二、解法 方法1:先排序,再判断。 “当且仅当它们的排序字符串相等时,两个字符串是字母异位词。” 方法2:按计数分类。 “当且仅当它们的字符计数(每个字符的出现次数)相同时,两个字符串是字母异位词。” class Solution { public List<List<Stri
阅读全文
摘要:一、题目描述 ☆☆☆☆二、解法 思路:将C+D的每一种可能放入查找表中,时间复杂度为O(n^2)。 由于可能有多组C+D的和相等,用Map记录每一个和出现了多少次。 举一反三:不是直接把数据放入查找表中,而是组合逻辑把特定的内容放入查找表中。还可以把A+B和C+D的每一种可能放入两个查找表中,时间复
阅读全文
摘要:一、题目描述 ☆☆☆二、解法 思路:与15题三数之和类似, 排序+双指针。 class Solution { public int threeSumClosest(int[] nums, int target) { /** * 方法1: 排序 + 暴力法, 时间复杂度O(n^3) */ /*Arra
阅读全文
摘要:一、题目描述 ☆☆☆☆二、解法 思路:与三数之和思想一样,排序+对撞指针。 时间复杂度 O(n^3)+O(nlogn) -> O(n^3) 需要注意去重以及剪枝,小细节非常多。 class Solution { public List<List<Integer>> fourSum(int[] num
阅读全文
摘要:一、题目描述 ☆☆☆☆二、解法 思路:排序+对撞指针,注意需要去重。 class Solution { public List<List<Integer>> threeSum(int[] nums) { /** * 思路:排序 + 对撞指针 * 时间复杂度 O(n^2) */ List<List<I
阅读全文
摘要:小说: √《平凡的时间》——路遥 传记: 《曾国藩传》——张宏杰
阅读全文
摘要:一、题目描述 二、解法 class Solution { public int[] twoSum(int[] nums, int target) { /** * 方法1:暴力枚举。 * 时间复杂度O(n^2),空间复杂度O(1) */ /*for (int i = 0; i < nums.lengt
阅读全文
摘要:一、题目描述 二、解法 class Solution { public String frequencySort(String s) { if (s == null || s.length() <= 2) return s; Map<Character,Integer> map = new Hash
阅读全文
摘要:一、题目描述 二、解法 class Solution { public boolean isIsomorphic(String s, String t) { if (s.length() != t.length()) return false; /** * 方法1:使用HashMap,与LeetCo
阅读全文
摘要:一、题目描述 二、解法 class Solution { public boolean wordPattern(String pattern, String s) { /** * 使用Map * 失败有两种情况: 1.key存在,经过查找字母对应的单词和这个单词不匹配; * 2.key不存在,但是这
阅读全文
摘要:一、题目描述 二、解法 class Solution { public boolean isHappy(int n) { /** * 方法1:用Set检测循环 */ /*Set<Integer> set = new HashSet<>(); while (n != 1) { if (set.cont
阅读全文
摘要:一、题目描述 二、解法 class Solution { public boolean isAnagram(String s, String t) { if (s.length() != t.length()) return false; int[] dict = new int[26]; /**
阅读全文
摘要:一、题目描述 二、解法 class Solution { public int singleNumber(int[] nums) { /*Map<Integer,Integer> map = new HashMap<>(); for (int num : nums) { map.put(num, m
阅读全文
摘要:一、题目描述 ☆☆☆☆二、解法 思路:滑动窗口。 时间复杂度O(n) 和LeetCode438. 找到字符串中所有字母异位词属于同一类型的题,滑动窗口的套路就是 扩张->满足条件->收缩 class Solution { public String minWindow(String s, Strin
阅读全文
摘要:一、题目描述 ☆☆☆二、解法 思路:滑动窗口法。用字母字典法判断两个词是否为字母异位词。 代码1:截取法。(时间效率9.25% (ㄒoㄒ)~~) class Solution { public List<Integer> findAnagrams(String s, String p) { List
阅读全文
摘要:一、题目描述 二、解法 思路:滑动窗口 class Solution { public int lengthOfLongestSubstring(String s) { if (s == null || s.length() == 0) return 0; /*int l = 0, r = 0; i
阅读全文
摘要:一、题目描述 ☆☆二、解法 方法1:滑动窗口. 时间复杂度 O(n) 、空间复杂度 O(1) 连续子数组 > 【滑动窗口】 class Solution { public int minSubArrayLen(int s, int[] nums) { if (nums == null || nums
阅读全文
摘要:一、题目描述 ☆☆☆二、解法 【最优解】:双指针(对撞指针),时间复杂度O(n) 核心是 缩减搜索空间 class Solution { public int maxArea(int[] height) { /** * 方法1:暴力法,时间复杂度O(n^2) */ /*int res = 0; fo
阅读全文
摘要:一、题目描述 二、解法 思路:对撞指针 class Solution { public String reverseVowels(String s) { if (s == null || s.length() < 2) return s; char[] chars = s.toCharArray()
阅读全文
摘要:一、题目描述 二、解法 class Solution { public void reverseString(char[] s) { if (s == null || s.length == 0) return; int l = 0, r = s.length - 1; while (l < r)
阅读全文
摘要:一、题目描述 二、解法 思路1:双指针。 思路2:reverse后看是否相等。 class Solution { public boolean isPalindrome(String s) { if (s == null) return true; /** * 方法1:双指针 */ char[] c
阅读全文
摘要:一、题目描述 二、解法 思路1:双指针。最优解,时间复杂度为O(n) 思路2:二分搜索。 (Tips:看见 数组 + 有序,第一时间想到 二分!!) 时间复杂度:O(nlogn),其中二分的复杂度为O(logn) class Solution { public int[] twoSum(int[]
阅读全文
摘要:一、题目描述 ☆☆二、解法 方法1:基于快排的选择方法,即快排partition函数的应用。 Note: 针对本题来说,快排的枢纽点要随机取,否则极端测试用例,会导致退化为O(n^2) 方法2:基于堆排序的选择方法。 解法1: class Solution { public int findKthL
阅读全文
摘要:一、题目描述 二、解法 思路:就是归并排序的 “合并”部分。 class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { // 把nums1拷贝一份 int[] temp = new int[m]; for
阅读全文
摘要:一、题目描述 二、解法 思路1:计数排序。分别统计0,1,2的元素个数。 复杂度分析:时间复杂度:O(n);空间复杂度:O(k), k为元素的取值范围; 需要扫描数组两遍。 思路2:三路快排。 只需要遍历数组一遍 重点是设计循环不变量,定义zero和two的含义后,在循环中始终要维护这个定义。 cl
阅读全文
摘要:一、题目描述 ☆☆☆二、解法 思路:快慢指针。 class Solution { public int removeDuplicates(int[] nums) { if (nums == null || nums.length == 0) return 0; /** * 方法1 */ int in
阅读全文
摘要:一、题目描述 二、解法 class Solution { public int removeDuplicates(int[] nums) { if (nums == null || nums.length == 0) return 0; int index = 0; for (int i = 0;
阅读全文
摘要:一、题目描述 二、解法 思路1:与LeetCode283. 移动零 思路一模一样,相当于把所有等于val的值移到最后。(保持元素的顺序不变) 思路2:每遇到一个元素等于val时,将当前元素与最后一个元素交换,并释放最后一个元素。(元素顺序改变) 分析:思路2中赋值的次数等于要删除元素的数量,因此如果
阅读全文
摘要:一、题目描述 二、解法 class Solution { public void moveZeroes(int[] nums) { if (nums == null || nums.length == 0) return; /** * 方法1: 双指针,两次遍历 -> 把非0的往前挪,然后补0 */
阅读全文