![](https://img-blog.csdnimg.cn/20201014180756913.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
LeetCode
Huiex胖子君
广告位招租
展开
-
剑指 Offer 35. 复杂链表的复制
主要思路是:以为题目的要求返回的链表和给的链表位置不一样,所以要新建结点将新建结点和原结点放入Map中,key为原结点,value为新建结点然后通过在map中取出原结点,得到新节点,让新节点next指向 map中原结点的next对应新节点连接random也同理public class Offer35 { /** 题目的要求返回的链表和给的链表位置不一样,所以要新建结点*/ public Node copyRandomList(Node head) { if (hea.原创 2021-12-08 18:24:12 · 252 阅读 · 0 评论 -
剑指 Offer 59 - II. 队列的最大值
参考:https://leetcode-cn.com/problems/dui-lie-de-zui-da-zhi-lcof/solution/ru-he-jie-jue-o1-fu-za-du-de-api-she-ji-ti-by-z1m/主要思路就是 创建两个队列,一个是先进先出队列,一个是双向队列普通队里用来执行pop 和push双向队列用来执行最大值的存放 如果加入的数值大于双向队列的最后元素,就将该元素从双向队列的从末尾弹出,直到双向队列的末尾元素大于该数值,就将数值从后面放入双向队列原创 2021-12-08 18:18:37 · 190 阅读 · 0 评论 -
剑指 Offer 66. 构建乘积数组
题目要求不能用除法,所以只能用乘法,如果每一个B[i]直接乘的话会有很多重复计算,费时所以可根据题意 可构建一个矩阵,分为上下两个三角区域下三角区域中,b[n] = b[n-1] * a[n-1]上三角区域中,b[n] = b[n-+] * a[n+1]这样递推可以有效地避免重复计算最后上三角的b[n] 乘上下三角的b[n],就得到结果public int[] constructArr(int[] a) { if (a.length == 0) return new int[0原创 2021-12-08 18:11:07 · 523 阅读 · 0 评论 -
剑指 Offer 12. 矩阵中的路径
回溯 剪枝回溯题,套模板这道题中,走过的路用一个特殊的字符进行标记,用来作为路径选择的判断条件具体思路看注解public class Offer12 { public boolean exist(char[][] board, String word) { /** 从网格的任意一个地方开始遍历寻找,也就是当前的ij位置上的字符是否为word的第一个字符,如果是说明该路径起点有戏,否则连起点都不对还是换一个起点吧*/ for (int i = 0; i &l原创 2021-12-08 17:57:40 · 67 阅读 · 0 评论 -
剑指 Offer 38. 字符串的排列
回溯很标致的一道回溯题照着模板写就行没有用剪枝具体的流程注解里面有public class Offer38 { public String[] permutation(String s) { HashSet<String> result = new HashSet<>();// ArrayList<String> result = new ArrayList<>();//结果集 String原创 2021-12-08 16:17:09 · 152 阅读 · 0 评论 -
剑指 Offer 48. 最长不含重复字符的子字符串
用滑动窗口主要注意滑动窗口的滑动的条件用两个指针,从最左边开始,右指针向右移动,并且右指针移动后,将对应字符存入set中,当右指针指向的字符已经存在set中时,就移动左指针,然后set删去左指针对应的字符,直到set中没有右指针对应的字符时,左指针停止移动public class Offer48 { /** 滑动窗口,*/ public int lengthOfLongestSubstring(String s) { /** 先将字符串转化为字符数组*/原创 2021-12-08 16:04:57 · 557 阅读 · 0 评论 -
剑指 Offer 26. 树的子结构
递归套递归一开始思路是 在 创建一个函数,进行在A中查找和B的根节点相同的结点,然后再创建一个函数,用来比较刚才在A中找到的子树和B树是否一样提交时发现,给的二叉树可能存在结点值相同,所以就只能 一旦找到A中和B的根节点相同的结点 后,就开始比较 A中子树和B是否一样public class Offer26 { public boolean isSubStructure(TreeNode A, TreeNode B) { /** 终止条件 : 穿过叶子结点 或者 如果当前原创 2021-12-06 10:58:09 · 617 阅读 · 0 评论 -
剑指 Offer 36. 二叉搜索树与双向链表
二叉搜索树的中序遍历是有序的,所以可以在中序遍历的基础上进行添加将中序遍历中的输出结点替换为本题所需要的结点中间的连接(具体看注解)public class Offer36 { /** 二叉搜索树的中序遍历是有序的,所以可以在中序遍历的基础上进行添加*/ /** 设立两个辅助指针,一个用来指向当前结点,一个指向上一个结点*/ private Node pre; private Node head; public Node treeToDoublyList(No原创 2021-12-05 20:37:23 · 145 阅读 · 0 评论 -
剑指 Offer 34. 二叉树中和为某一值的路径
深度优先 回溯法public class Offer34 { /** 先创建一个List用来存放路径*/ private List<List<Integer>> result = new ArrayList<>();//结果集 private List<Integer> path = new ArrayList<>();//设置一个变量,来判断目前路径是否满足目标路径 public List<List&原创 2021-12-05 19:14:41 · 405 阅读 · 0 评论 -
剑指 Offer 31. 栈的压入、弹出序列
建立一个辅助栈向辅助栈中放入pushed栈中的元素同时查找栈顶的元素 (根据popper数组的指针指向的数)如果没有找到就继续入栈,如果找到就出栈,并且吧指针向后移动当全部入栈时候,结束public boolean validateStackSequences(int[] pushed, int[] popped) { /** 建立一个辅助栈*/ Stack<Integer> stack = new Stack<>(); /原创 2021-12-04 18:08:53 · 640 阅读 · 0 评论 -
剑指 Offer 46. 把数字翻译成字符串
动态规划思路:其实和青蛙跳台阶一个道理当有 n 个数的排列方式为1. 第n个数字无法和前面的数字无法组合时排列方式为:前 n-1个数的排列方式 加上当前数字,数量为 fn-1(前n-1个数字饿排列方式)2. 第n个数字可以和前面的数字组合时排列方式为: 前 n-1个数的排列方式 加上当前数字,数量为 fn-1(前n-1个数字饿排列方式)和 前n-2个数的排列方式 (fn-2)两种情况,只需要判断 第n个数字是否可以和前面的数字组合如果组合的数字为 10 到 25 就说明可以组合转移方程:原创 2021-12-04 12:37:11 · 69 阅读 · 0 评论 -
剑指 Offer 49. 丑数
动态规划 三指针思想:在已有的丑数序列上每一个数都必须乘2, 乘3, 乘5,然后选取其中最小的丑数,这样才不会漏掉某些丑数,初始化: 第一个丑数为1,arr[0] = 1转移方程: 丑数 == 某较小丑数 × 某因子 即 min = (a2,b3,c*5)最优子结构: arr[a],arr[b],arr[c]来自k神的图/** 动态规划 三指针*/ public int nthUglyNumber(int n) { if (n == 0) return 0原创 2021-12-04 10:09:54 · 437 阅读 · 0 评论 -
剑指 Offer 14- I. 剪绳子
贪心 * 思想:当n大于4时,尽可能多的剪出长度为3的段,3就是最优的, * 当 n 被剪到小于4时,就不用再减,因为小于4时剪还不如不剪 * 如果给的n直接就小于4,没办法,特殊值,特殊处理,不剪也得剪 public int cuttingRope(int n) { if (n == 2) return 1; if (n == 3) return 2; if (n == 4) return 4; int res = 1;原创 2021-11-30 20:50:31 · 69 阅读 · 0 评论 -
剑指 Offer 33. 二叉搜索树的后序遍历序列
因为是搜索二叉树,所以 左结点 < root < 右结点先遍历找到 大于数组最后一个数(也就是root)的索引则 [left,i-1]为右子树的区间,[i,right-1]为左子树的区间判断右子树区间内的数是否都小于 root(也就是postorder[right])判断左子树区间内的数是否都大于 rootpublic class Offer33 { private int[] postorder; public boolean verifyPostorder(int原创 2021-11-30 20:13:06 · 348 阅读 · 0 评论 -
剑指 Offer 07. 重建二叉树
整体思想为:先通过先序找到中序中root的位置,再通过中序root的位置找到左子树的区间,和右子树的区间递归左右子树当穿过叶子结点结束public class Offer07 { /** 先通过先序找到中序中root的位置, * 再通过中序root的位置找到左子树的区间,和右子树的区间 * 递归左右子树 * * 当穿过叶子结点结束 * */ private HashMap<Integer,Integer> map原创 2021-11-30 17:13:47 · 64 阅读 · 0 评论 -
剑指 Offer 04. 二维数组中的查找
有点类似于二叉树了,从左上角开始,通过不断判断,将边界缩小(类似于这一题顺时针打印列表 https://blog.csdn.net/HUIEX/article/details/121564439) /** 从右上角开始,往下变大,往右边小*/ /** 设置边界 up,down,left,right ,当up < down,right < left,结束查找,即没有找到*/ /** 如果目标数小于当前数,就向右移动,如果目标数大于当前数,就像下移动*/ public原创 2021-11-29 21:29:21 · 149 阅读 · 0 评论 -
剑指 Offer 62. 约瑟夫环问题(动态规划法)
https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/solution/javajie-jue-yue-se-fu-huan-wen-ti-gao-su-ni-wei-sh/fx = (fx + m) % i;转移方程就直接记住吧,可以照着这个图去穷举分析,理解一下这个方程 /** 动态规划 /数学解法 约瑟夫环*/ public int lastRemaining(int n, in原创 2021-11-29 21:22:10 · 218 阅读 · 0 评论 -
剑指 Offer 62. 约瑟夫环问题(模拟法)
不建议使用,时间复杂度太大,这个用了1361ms用ArrayList会稍快一些模拟时,重点在于 如何计算要删除数字的坐标,具体看注解/** 模拟法*/ public int lastRemaining(int n, int m) { /** 创建一个集合用来模拟环*/ ArrayList<Integer> list = new ArrayList<>(); for (int i = 0; i < n; i++){原创 2021-11-29 21:15:48 · 196 阅读 · 0 评论 -
剑指 Offer 53 - II. 0~n-1中缺失的数字
二分法,主要是边界的细节,无了 public int missingNumber(int[] nums) { if (nums.length == 0) return 0; /** 判断nums[mid] 是否等于 mid * 如果等于mid,那么这个数字在 [mid+1,right]区间内 * 如果不等于mid,就在 [left,mid-1]*/ int left = 0; int right原创 2021-11-29 19:05:05 · 116 阅读 · 0 评论 -
剑指 Offer 53 - I. 在排序数组中查找数字 I
先用二分找到目标数字,同时也缩小了区间再用遍历找到目标区间的边界/** 典型二分,说了有序数组*/ public int search(int[] nums, int target) { /** 先确立好边界*/ int left = 0; int right = nums.length - 1; /** 开始二分,当left > right 时结束*/ while (left <= right){原创 2021-11-29 18:50:46 · 155 阅读 · 0 评论 -
剑指 Offer 18. 删除链表的节点
注意判断链表的第一个结点(也就是head结点)是否为目标结点和链表最后一个结点(因为用的是但指针,无法判断最后一个结点),需要在跳出循环后单独判断public class Offer18 { public ListNode deleteNode(ListNode head, int val) { if (head == null) return null; /** 找到目标结点的前一个结点temp*/ ListNode temp = head;原创 2021-11-29 16:33:39 · 50 阅读 · 0 评论 -
剑指 Offer 11. 旋转数组的最小数字
二分查找,范围逼近 减治思想当 nums[mid]小于最右边的数,说明旋转点在[left,mid]的区间内 ,将查找区间的右边界变为mid(细节)当 nums[mid]大于最右边的数,说明旋转点在[mid+1,right]的区间内,将将查找区间的左边界变为mid+1当 nums[mid]等于最右边的数,就将right–,缩小范围,因为 right–并不会结果产生影响,为什么? 因为right–的前提条件为nums[mid] = nums[right],那么该nums[right]一定不为旋转点最后原创 2021-11-29 11:00:16 · 238 阅读 · 0 评论 -
剑指 Offer 63. 股票的最大利润
当前天数的最大利润为 Math.max(前一天的最大利润,这一天的价钱减去前几天最小的价钱)从第二天开始算起,也就是 i = 1; /** 当前天数的最大利润为 Math.max(前一天的最大利润,这一天的价钱减去前几天最小的价钱)*/ public int maxProfit(int[] prices) { if (prices.length == 0) return 0; /** 初始状态: 第一天的最大利润为 0 */ int fn =原创 2021-11-27 20:51:40 · 61 阅读 · 0 评论 -
剑指 Offer 10- II. 青蛙跳台阶问题(动态规划法)
使用动态规划老三步初始状态: f1 = 1,f2 = 2转移方程: fn+1 = fn + fn-1fn = fn-1 + fn-2最优子结构: fnpublic int numWays(int n) { /** 初始状态: f1 = 1,f2 = 2 * 转移方程: fn+1 = fn + fn-1 * fn = fn-1 + fn-2 * 最优子结构: fn **原创 2021-11-27 17:21:40 · 138 阅读 · 0 评论 -
剑指 Offer 10- I. 斐波那契数列
典型动态规划老三步初始状态: f[1] = 1,f[0] = 0转移方程: f[n+1] = f[n] + f[n-1]f[n] = f[n-1] + f[n-2];最优子结构: f[n]注意一下题目要求的取模public int fib(int n) { /** 初始状态: f[1] = 1,f[0] = 0 * 转移方程: f[n+1] = f[n] + f[n-1] * f[n] = f[n-原创 2021-11-27 17:19:18 · 131 阅读 · 0 评论 -
剑指 Offer 42. 连续子数组的最大和
看题目感觉是动态规划然后列举分析一下,发现 过程中有些结果是重叠的规律为 nums中索引为n的数,其子数组最大值为 Math.max(索引为 n-1的最大子数组加上自己本身(数组中该索引本身的数),自己本身)得出:初始状态:f0 = nums[0]转移方程:fn+1 = fn + nums[n+1] 或 fn+1fn = fn-1 + nums[n] 或 fn最优子结构:fn/** 到索引为n的数,其子数组最大值为 索引为 Math.max(n-1的最大子数组加上自己,自己本身)*/原创 2021-11-27 17:16:46 · 202 阅读 · 0 评论 -
剑指 Offer 30. 包含min函数的栈
用链表实现一个栈重点在结点中设置一个min属性,用来存放当前结点和它下面栈元素的最小值还有就是利用头插法,简单方便public class Offer30 { private Node head; public Offer30() { } public void push(int x) { //如果当前栈为空 就让头结点指向当前结点,最小值为x if (head == null) head = new Node(x,x,nul原创 2021-11-27 14:58:40 · 233 阅读 · 1 评论 -
剑指 Offer 55 - II. 平衡二叉树
使用递归,终止条件:穿过叶子结点,root == null;子问题和问题的关系:左子树深度与右子树深度的差值小于1,并且左右子树也都为平衡二叉树/** 递归,终止条件:穿过叶子结点,root == null; 子问题和问题的关系:左子树深度与右子树深度的差值小于1,并且左右子树也都为平衡二叉树 * 当前方法为 传入结点,返回该结点下的树是否为平衡二叉树*/ public boolean isBalanced(TreeNode root){ if (root == nu原创 2021-11-27 13:40:43 · 168 阅读 · 0 评论 -
剑指 Offer 47. 礼物的最大价值
用动态规划找规律,确定最优子结构 :当前格子的累计最大价值为 上面和左边 的 最大累计价值 加上 当前格子的价值即:dp[i][j] = Math.max(dp[i][j-1],dp[i-1][j]) + grid[i][j]确定边界:第一个格子的最大累计价值就是当前格子价值public int maxValue(int[][] grid) { /** 创建一个dp矩阵,用来存放到达单元格 (i,j)(i,j) 时能拿到礼物的最大累计价值。(可以理解为记事本)原创 2021-11-26 21:27:02 · 57 阅读 · 0 评论 -
剑指 Offer 28. 对称的二叉树
public boolean isSymmetric(TreeNode root) { /** 特殊条件 root == null*/ if (root == null) return true; return is(root.left,root.right); } public boolean is(TreeNode left,TreeNode right){ /** 递归终止条件 * 左边和右边结点都.原创 2021-11-26 17:36:14 · 245 阅读 · 0 评论 -
剑指 Offer 29. 顺时针打印矩阵
主要是思想,利用边界进行打印和判断结束,实现起来不难,大部分简单题主要就是思路,实现都不难,思路的话如果以后碰见类似的题就能做出来沿着边界打印,即将元素按顺序添加到result边界向内收缩 (代表已被打印);判断边界是否相遇,若相遇说明打印完毕,结束打印public int[] spiralOrder(int[][] matrix) { if (matrix.length == 0) return new int[0]; int[] result = new int[原创 2021-11-26 17:21:35 · 438 阅读 · 0 评论 -
92. 反转链表 II
public static ListNode reverseBetween(ListNode head, int left, int right) { //找到4个点 1.左结点 2.左结点前一个结点 3.右结点 4.右结点之后的结点 //在头结点之前创建一个结点 ListNode foremost = new ListNode(-1); foremost.next = head; //寻找4个点 使用一个辅助结点 .原创 2021-11-06 17:35:17 · 62 阅读 · 0 评论 -
19. 删除链表的倒数第 N 个结点
先遍历一下整个链表的长度count,然后用count-n+1计算待删除的结点在链表的位置如何找到该结点的前一个结点temp.next = temp.next.next进行删除public static ListNode removeNthFromEnd(ListNode head, int n) { ListNode temp = head; int count = 1; for(int i = 0; temp.next != null; i++) { temp = temp.ne原创 2021-11-06 18:49:56 · 66 阅读 · 0 评论 -
83.从有序链表中删除重复节点
还是双指针,依次遍历 比较同样注意边界的判断条件,还有参数为空的条件public static ListNode deleteDuplicates(ListNode head) { if(head == null) { return null; } //先定义两个辅助指针 ListNode forward = head.next;//前 ListNode rear = head;//后 //开始循环判断 while(rea原创 2021-11-06 09:20:12 · 114 阅读 · 0 评论 -
合并两个有序链表
递归不会直接用while循环迭代先定义一个结点,ListNode head = new ListNode(-1);,不能用ListNode head = null;然后定义一个辅助指针ListNode prev = head;,主要思想就是辅助指针,根据两个链表边的当前头结点的比较,判断去指向谁,如果l1 != null && l2 != null就开始常规的 指针指向操作了prev.next = l1; l1 = l1.next; prev = prev.next;然后原创 2021-10-30 15:47:45 · 71 阅读 · 1 评论 -
206. 反转链表
https://leetcode-cn.com/problems/reverse-linked-list/solution/shi-pin-jiang-jie-die-dai-he-di-gui-hen-hswxy/定义三个辅助结点一个指向head前的null prev一个指向当前结点 curr一个指向当前结点的下一个结点 nextNode先将curr的next指向prev,然后同时将curr 和 prev 向后移动一个位置,nextNode结点的作用就在于 curr指原创 2021-10-30 09:40:05 · 63 阅读 · 0 评论 -
278. 第一个错误的版本
正确答案:public int firstBadVersion(int n) { int left = 1; int right = n; while(left < right) { int mid = left + (right - left) / 2; if(isBadVersion(mid)){ right = mid; }else{ left原创 2021-10-28 12:12:03 · 66 阅读 · 0 评论 -
540. 有序数组中的单一元素
二分法(1)先找到中间值mid,然后对左右元素进行判断,如果都不等于,就证明该元素为单独的(2)如果左相等或者右相等,就根据情况进行在次二分重点在于如何判断mid值二分 左边还是右边通过判断mid和相等这mid+1或者m-1,前后的数组元素的奇偶奇数证明该数组含有单个元素,就进行二分继续查找public static int singleNonDuplicate(int[] nums) { int left = 0; int right = nums.length-1;原创 2021-10-28 10:50:27 · 77 阅读 · 0 评论 -
241. 为运算表达式设计优先级
分治分治的本质就是拆分成最小的部分进行操作字符串通过调用递归进行运算符的拆分,拆分成一个个独立的运算结果,然后进行运算得到最终的结果 public static ArrayList<Integer> diffWaysToCompute(String expression) { ArrayList<Integer> res = new ArrayList<Integer>(); for(int i = 0;i < expressi原创 2021-10-26 11:28:30 · 72 阅读 · 0 评论 -
744. 寻找比目标字母大的最小字母
public static char nextGreatestLetter(char[] letters, char target) { int left = 0; int right = letters.length-1; while(left <= right) { int mid = left + (right - left) / 2 ; if(letters[mid] > target) { right = mid -1; }...原创 2021-10-26 11:24:50 · 52 阅读 · 0 评论