力扣刷题
加文斯利
跨考计算机学院硕士,自学java/java web
展开
-
TreeMap按照value排序
TreeMap默认实现只能根据key来排序,或者定义treeMap的时候new Comparator,自定义key排序的方法,但是不能按照value进行排序。可以使用下面的方法,对value进行一次排序。Map<String,Integer> map = new TreeMap<String,Integer>(); List<Map.Entry<String,Integer>> list = new ArrayList<Map.Ent原创 2021-06-26 16:20:15 · 5978 阅读 · 3 评论 -
leetcode 1105. 填充书架
题:https://leetcode-cn.com/problems/filling-bookcase-shelves/解1(超时):public static int minHeightShelves(int[][] books, int shelf_width) { int[] minHigh = new int[]{Integer.MAX_VALUE}; dfs(minHigh,0,books,shelf_width,0); return minH原创 2021-06-08 18:10:07 · 210 阅读 · 0 评论 -
leetcode103. 二叉树的锯齿形层序遍历
思:使用双端队列当奇数层结点被弹出后(使用尾部弹出),将它的孩子从左到右,模拟的加入到队列头部当偶数层结点被弹出后(使用头部弹出),将它的孩子从右到左,模拟的加入到队列尾部码:public static List<List<Integer>> zigzagLevelOrder(TreeNode root) { Deque<TreeNode> deque = new LinkedList<TreeNode>(); Lis原创 2021-05-29 21:51:06 · 97 阅读 · 0 评论 -
每日随机一题 leetcode778. 水位上升的泳池中游泳
题:思:使用迪杰斯特拉算法的思想,对其进行变化,改为:每次选一个当前可选的最小的边,当右下角那个点被遍历时,结束程序。刚开始只有(0,1)和(1,0)位置的点是可以选的,于是将它们加入到待遍历的点集合里。每次从待遍历的边里选一个权值最小的点,并更新当前最小值。然后将其上下左右还没有加入过队列的点,加入到队列中。当右下角那个点被遍历的时候,代表存在了一条连通的路使得左上角到右下角连通,并且此时最小值即为答案。使用优先队列来存放待遍历的点。码:class Node { in原创 2021-05-22 20:06:26 · 136 阅读 · 0 评论 -
每日一题 leetcode810. 黑板异或游戏 博弈论
看到这个题,第一反应就是上次连答案也没看懂的石子游戏,这个题答案讲的很清楚,属于博弈论内容题解链接:https://leetcode-cn.com/problems/chalkboard-xor-game/solution/hei-ban-yi-huo-you-xi-by-leetcode-soluti-eb0c/码:public boolean xorGame(int[] nums) { if(nums.length % 2 == 0) return ..原创 2021-05-22 14:58:00 · 116 阅读 · 0 评论 -
每日一题 leetcode 993.二叉树的堂兄弟结点
题:思:用第二个队列来保存在同一层的所有结点,如果能找到x和y,且它们不拥有同一个父节点,则返回true如果只能找到一个x或者y,则返回false,因为此时这意味着另一个x或者y,和我们这一层找到的x或者y一定不在同一层如果既没找到x又没找到y,则再找下一层最后也没找到,返回false码:public boolean isCousins(TreeNode root, int x, int y) { if (root.val == x || root.val == y)原创 2021-05-17 19:22:37 · 92 阅读 · 0 评论 -
每日随机一题 leetcode1452. 收藏清单 api的巧妙使用(List与Set的contains和containsAll的时间复杂度不同)
题:思:不断的考虑新的一个List,来更新map,map用于保存当前所有的满足条件的收藏清单如果新的list和过去的某一个list长度一样,那么他们一定不同如果新的list包含过去的某一个list的全部,那么就删除原来的,添加新的。可能会同时删除很多个如果新的list被包含于过去的一个list,那么新的list将不再考虑,直接考虑下一个list码:public List<Integer> peopleIndexes(List<List<String>>原创 2021-05-17 18:50:07 · 539 阅读 · 0 评论 -
leetcode 146. LRU缓存机制
题:思路:相当于自己定义一个带时间限制的treeMap 比较大小通过最后一次访问时间来判断map的底层显然是用链表实现的 1.put操作 遍历队列,看看是否已经存在这个key 如果已经存在,则找到位置并更新value,然后将该结点移至队列头 如果不存在 如果容量没满 直接头插 如果容量满了原创 2021-05-15 02:06:31 · 90 阅读 · 0 评论 -
二刷 leetcode 3. 无重复字符的最长子串 动态规划可以做
题:思:六个月前是用暴力解法做的,今天一看,可以用动态规划来做嘛!思路里最关键的一点在于Math.min详见代码码:public int lengthOfLongestSubstring(String s) { if(s.length() == 0) return 0; // int maxLen = 0; // map存的是 当前元素最后一次出现的位置 // dp存的是截止当前位置,从后往前没有重复元素的子串长度原创 2021-05-15 01:09:01 · 186 阅读 · 0 评论 -
每日随机一题 leetcode538. 把二叉搜索树转换为累加树
题:方法1:哈希表class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() { } TreeNode(int val) { this.val = val; } TreeNode(int val, TreeNode left, TreeNode right) {原创 2021-05-14 22:37:43 · 62 阅读 · 0 评论 -
每日随机一题 leetcode638. 大礼包
题:思:深搜暴力解法码:public static int shoppingOffers(List<Integer> price, List<List<Integer>> special, List<Integer> needs) { // 深搜 要使得needs的所有元素恰好变为0时,所需的最小的价格和 // 对于needs的每一项,只要不为0,就有以下几种选择: // 1.直接减少自己 2.寻找一原创 2021-05-14 21:56:20 · 169 阅读 · 0 评论 -
每日随机一题 leetcode37. 解数独
题:思:暴力解法,深搜+回溯每次判断当前格子能不能从1到9里面选一个数,如果能就继续dfs当dfs到最后一行结束的时候,整个递归结束,得到答案。如果当前这个位置选了一个数,不能使得我们的递归运行到最后一行,说明当前位置不能选择这个数,因为当前位置可以考虑选择下一个数。如果当前位置不能选1-9任意的一个数,说明前面出问题了,回溯到前一步,改变前一步的数字。码:public static void solveSudoku(char[][] board) { /*原创 2021-05-14 14:33:51 · 112 阅读 · 0 评论 -
每日一题 leetcode1482. 制作m束花所需的最少天数
题:思:flower[i][j]表示第i天的时候,第j朵花是否开放 1为开放,0为不开放遍历所有可能的i(从bloomDay中选),如果能找到m组连续的k个 flower[i][j] == true 则返回i最后也没找到就返回-1结果:超出空间限制,因为使用了flower数组,开辟了过多的空间,实际上不需要使用该数组优化空间后,超出时间限制,因为是从set[0]开始找哪一天能满足条件,其实这是个二分查找经过两次优化后,终于勉强过了所有测试用例码:public int minDays(i原创 2021-05-13 21:04:40 · 98 阅读 · 0 评论 -
每日一题 leetcode1734.解码异或后的排列
题:码+思:public int[] decode_overTime(int[] encoded) { // 使用前缀和的思想,使得encoded[i] = perm[0] ^ perm[i+1] // 因为已知答案唯一,所以第一个数的答案只能是1到n中的一个数,因此暴力解法,直到找到合适的第一个数为止 for(int i = 1 ; i < encoded.length ; i++){ encoded[i] = encod原创 2021-05-13 19:17:23 · 104 阅读 · 0 评论 -
每日一题 leetcode1269. 停留在原地的方案数
题:思+码:public int numWays(int steps, int arrLen) { int sum = 0; // sum最后的值至少为1,因为可以选择全不动 /* 每次可以选择 向右、不动、向左 相当于背包问题,每次选择一项相当于背包容量-1 向右导致value+1 向左导致value-1 不动的话value不变 初始value为0,要保证经过steps操原创 2021-05-13 11:23:05 · 92 阅读 · 0 评论 -
leetcode 850. 矩形面积II (线段树)
答案看不懂,放弃。原创 2021-05-10 18:58:56 · 250 阅读 · 0 评论 -
每日随机一题 leetcode1449. 数为成本和为目标值的最大数字 完全背包问题,两个小时 自己写出来了!
题:思:最终的数位成本和必须恰好等于target换算为背包问题(拿了以后还可以再拿)数位1到9 对应9个物品,cost[0到8] 对应9个物品的重量;物品本身代表了自己的价值:要在尽可能的多拿物品(多拿数位),然后对结果进行排序,得到最大的价值所以可以把每个物品的价值都理解为1,因为每个物品的价值是等价的dp[i]表示重量为i的时候,最大的数位和(String类型)对于每一个物品(数位),我们可以选择拿或者不拿,如果拿的话,则把它插入到头部,因为循环越往后,数位越大,这样就无需给已经获得原创 2021-05-09 01:41:03 · 92 阅读 · 2 评论 -
每日随机一题 leetcode879.盈利计划 0-1背包问题 最难的dp问题类型之一,直接看答案思路
题:正确思路:首先将本题转换为背包问题:n个人相当于背包容量,minProfit相当于要求我背包里最少装的价值,group代表每个物品的重量,profit代表每个物品的价值对于第i个物品,dp[j][k]表示截止到第i个物品时,用j大小的容量,获取k的价值,有dp[j][k]条策略初始化dp[M][0] = 1; M=1,2,3,…n 解释:对于M大小的容量,初始情况下想要获取0的价值,只有一种方案,就是什么都不放。(现在还没有遍历过所有物品,有的物品价值是为0的)设w为第i个物品的重量,v原创 2021-05-05 21:46:22 · 173 阅读 · 0 评论 -
每日一题 leetcode740.删除并获得点数(dp、没做出来)
一道很好的dp问题,一开始压根没想到要用dp做,以为贪心可以做。看了答案,才知道dp还可以这么用题:答案思路先搞一个数组arr,用来存放1这个数字出现了几次,2这个数字先了几次…比如[2,2,3,3,3,4]放到arr里就是[0,0,2,3,1] 分别代表0这个数字出现了0次,1这个数字出现了0次,2这个数字出现了2次…然后dp[i]表示到i这个数为止,可以获得的最大的点数。由题可知,我如果选择j这个数,则直接获得j的所有点数,比如上面我选了3,那么直接获得点数9,然后我不能再选2和4于原创 2021-05-05 19:26:03 · 144 阅读 · 0 评论 -
每日一题 leetcode1473. 粉刷房子III
题:思:如果房子数为0则直接返回-1先数出已有街区machi ,如果已有街区大于target,直接返回-1M=target-machi代表还需要的街区数量如果M = 0,则答案唯一,直接计算即可 —> 不对,如果M = 0 答案也不一定唯一e.g houses[1,2,0,1,1] target=3 M=0 ,此时0可以被刷成1也可以被刷成2否则题目化简为,在剩余的所有没上色的房子houses里,划分M个街区的最小消耗开始时,当前已有街区cur为0从houses[0]里选择最小原创 2021-05-05 00:35:57 · 175 阅读 · 0 评论 -
每日随机一题 leetcode980.不同路径III
题:思:dp[i][j] 表示到坐标轴为i,j的点时,有dp[i][j]条路线dp[i][j] = dp[i-1][j]+dp[i][j-1]+dp[i][j+1]+dp[i+1][j]初始化:如果grid[i][j] == 1 ,则dp[i][j] =1计算完所有dp的值以后,返回dp[i][j],满足grid[i][j]==2关键点:从哪个点开始计算dp? 从grid[i][j]==1的地方开始计算! —> 也不行,需要引入记忆化!答案的动态规划思路看不懂,放弃思2:dfs原创 2021-05-04 22:41:53 · 136 阅读 · 0 评论 -
每日随机一题 leetcode290. 单词规律
题:思:哈希表码:public boolean wordPattern(String pattern, String s) { Map<Character, String> map = new HashMap<Character, String>(); String[] str = s.split(" ", 0); if(pattern.length()!=str.length) return fals原创 2021-05-04 21:28:01 · 236 阅读 · 0 评论 -
每日随机一题 leetcode1425. 带限制的子序列和
题:思:dp[i]表示右端点为i的最大的子序列和dp[0] = nums[0]dp[i] = max(max(dp[i-Q])+nums[i],nums[i]) ; Q = 1,2,…,k化简得 dp[i] = max(dp[i-Q],0) + nums[i]; Q = 1,2,…,k返回dp里最大的值上面的方法会超时,看了答案的思路,需要使用单调队列(单调栈)进行维护,避免多余的运算单调栈原理:如果dp[i] > dp[i-1] 则每次挑选max的时候,就不要去和dp[i-1]原创 2021-05-03 01:07:18 · 104 阅读 · 0 评论 -
每日一题 leetcode690.员工的重要性
题:思:广度优先搜索码:public int getImportance(List<Employee> employees, int id) { // 先找到员工id Employee start = findUseId(employees, id); if (start == null) return 0; int sum = 0; if (start.subordinates == null) retu原创 2021-05-02 22:31:36 · 113 阅读 · 0 评论 -
每日一题:leetcode554. 砖墙
题:思:对于每一行,将砖块转换为数字 [1,2,2,1] -> [1,3,5,6]把每一行都转换完以后,遍历[1,5]每一列,找出一条竖线使穿过的砖头最小对于每一列,如果有一行存在对应列数的数字,则表示经过此行没有穿过砖头代码超时当wall == [[100000000],[100000000],[100000000]]时,还从1遍历到100000000,显然是浪费时间优化方法:不从1开始遍历,只遍历出现过的数字,因为如果数字没出现,代表根本不可能在这一列减去1码:pu原创 2021-05-02 19:17:32 · 137 阅读 · 0 评论 -
每日随机一题 leetcode846. 一手顺子
题:思:例:hand = [1,2,3,6,2,3,4,7,8], W = 3true --> [1,2,3],[2,3,4],[6,7,8]思:先排序[1,2,3,6,2,3,4,7,8] --> [1,2,2,3,3,4,6,7,8]每次先挑一个最小的数,然后顺着找,找不到连续的W-1个数,就直接返回false如果找到了W个连续的数,则再找下一组如:[1,2,3,4,5,6] W=2 时,应该返回true,因为可以[1,2],[3,4],[5,6]码:publi原创 2021-05-02 16:46:42 · 88 阅读 · 0 评论 -
贪心专项练习:leetcode134. 加油站
题:思:出发点只能选在gas[i]>=cost[i]的这些位置每次减去cost[i]如果为负数,则放弃本次循环如果为正数,则再加上gas[i+1]码:public int canCompleteCircuit(int[] gas, int[] cost) { Stack stack = new Stack(); // 寻找合适的初始位置 for (int i = 0; i < gas.length; i++) {原创 2021-05-02 15:52:00 · 88 阅读 · 0 评论 -
贪心专项练习:leetcode122. 买卖股票的最佳时机II
题:思:思路:贪心,只要涨了我就卖,然后跌了我就买。买的前提是确保他会涨,卖的前提是确保他会跌例:[6,1,3,2,4,7]如果用上面的算法,找到7比6大,所以最后结果是1,但是最好的结果应该是(3-1)+(7-2)=7所以外面还要再套一层,表示从第一个点开始找的情况,第二个点开始找的情况…最后选出max这样还是不行,因为例:[2,1,2,1,0,1,2],第四个数是1,找到比它大的2,循环结束。换思路:dp[i-1] = dp[i] + prices[i-1]<prices[i]原创 2021-05-02 15:22:06 · 73 阅读 · 0 评论 -
每日随机一题 leetcode1749. 任意子数组和的绝对值的最大值
题:思路:我一开始的思路是基于贪心,想着如果加上一个数以后还不如从这个数本身开始,那就从这个数开始,但是这样的思想是错误的,因为你没办法保证当前子数组不是因为有从正数变成负数或者从负数变成正数而导致max发生变化了。于是看了答案答案思路:当我们有了前缀和数组 sum 之后,需要求任意一段子数组 [i,j] 的和可以直接通过 sum[j] - sum[i - 1] 得出。现在 通过sum可以求得所有的子数组和的情况那么使得sum[j]最大,sum[i-1]最小,即为答案(sum[j]为正,原创 2021-04-28 19:03:33 · 228 阅读 · 0 评论 -
面试没做出来的题 leetcode435.无重叠区间
题:面试没做出来,看了答案。思路:贪心每个区间都有左端点和右端点首先按照右端点大小进行排序,然后选出右端点最小的区间作为起始区间,此时问题变为子问题:以当前右端点为起点,移除的最小数量每次取出一个右端点最小的,判断其左端点又没有小于上一个区间的右端点,如果小于的话,说明重复了,不要这个区间,否则,就把这个区间当做最新的区间。如果右端点相同的话,我们取出左端点较大的那个区间,因为这意味着这个区间的区间长度比较短,我们尽可能的留下区间短的空间,因为删掉区间大的空间,可以尽可能的少删,如果留下区间大原创 2021-04-27 19:18:20 · 101 阅读 · 0 评论 -
DP专项训练:leetcode.85 最大矩形
题:思:没思路,直接看了答案,感觉和dp没什么关系需要一个辅助数组letf,left[i][j]用来存放第i行第j列时,第i行前面有几个连续的1然后判断最大矩形时,比如以第i行第j列为右下角的矩形,其最大矩形面积为多个a*b的比较a为长,b为宽b初始为1,每次++a = Math.min(leftMatrix[k][j], a);码:public int maximalRectangle(char[][] matrix) { if (matrix.length == 0原创 2021-04-24 01:38:32 · 145 阅读 · 0 评论 -
拓扑排序专项训练:leetcode207. 课程表
题:思:一开始搞的是出边数组,最后失败了,因为不能保证一个课程学完以后一定能学它的后续课程,它的后续课程可能还依赖其他的前序课程看了答案以后,发现换成入边数组就可以题目:一共有n门课程,用序号0到n-1表示。给定先修课程集合,判断是否可能完成所有课程学习?思路:(a,b)代表想要学习a课程,必须已经学了b课程 即 b -> a创建邻接表list,大小为n,每个结点挂着修习了本课程以后,可以修习后面的哪些课程初始化邻接表时,判定(a,b)中,如果 b 在 a的结点下面挂着的话,说明出原创 2021-04-23 23:31:28 · 88 阅读 · 1 评论 -
dp专项训练:leetcode72. 编辑距离
题:思:自己的想法是错的,于是看了答案题目所给的三个操作,等价于以下三种操作:在单词a中增加一个字符在单词b中增加一个字符修改单词a的一个字符于是有:dp[i][j] = min( dp[i-1][j] , dp[i][j-1], dp[i-1][j-1]+M ) + 1; M=0(if a.i != b.j;else M=1)dp[i][j] 表示word1到i位置,word2到b位置时,word1与word2的编辑距离码:public static int minDistan原创 2021-04-23 21:06:01 · 85 阅读 · 0 评论 -
DP专项训练:leetcode64. 最小路径和
题:思:和62、63基本一样,注意矩阵里的数字是可以取0的public int minPathSum(int[][] grid) { int dp[][] = new int[grid.length][grid[0].length]; int x, y; for (int i = 0; i < grid.length; i++) { for (int j = 0; j < grid[0].length; j++) {原创 2021-04-22 20:31:51 · 84 阅读 · 0 评论 -
DP专项训练: leetcode63. 不同路径II
题:思:需要考虑到只有一行一列且为障碍物的情况public int uniquePathsWithObstacles(int[][] obstacleGrid) { int m = obstacleGrid.length; int n = obstacleGrid[0].length; int dp[][] = new int[m][n]; // 初始默认全为0 dp[0][0] = 1; int x, y;原创 2021-04-22 19:54:21 · 74 阅读 · 0 评论 -
DP专项训练:leetcode62. 不同路径
题:思:虽然知道是要用dp做,但还是先用第一反应的dfs来做,果然超时了,而且写dfs用了一个多小时,写dp只用了几分钟。思路一:深搜(超时)暴力深搜思路:初始化n*m的boolean矩阵,true代表还可以使用,false代表当前格子不能使用每次可以向右移动一格或者向下移动一格,移动后把已经经历过的格子变为false当到终点的时候,记录路线数目count=count+1,count初始为0每当不能移动的时候(不能向下或者向右或者已经到终点),退后一格每次执行退后操作的时候,如C->原创 2021-04-22 19:35:47 · 114 阅读 · 0 评论 -
DP专项训练:leetcode44.通配符匹配
// 44.通配符匹配 dp专项训练 4.21每日一题/* * 给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配。 * '?' 可以匹配任何单个字符。'*' 可以匹配任意字符串(包括空字符串)。 * 两个字符串完全匹配才算匹配成功。 * s 可能为空,且只包含从 a-z 的小写字母。 * p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *。 * *//* * --------------------------------原创 2021-04-22 00:18:05 · 150 阅读 · 0 评论 -
剑指Offer33. 二叉搜索树的后序遍历序列
先看一眼题:思路:二叉搜索树:左小右大后序遍历:左右中逆后序遍历:中右左结论:逆后序遍历的第一个数是整个树的根节点·对于每个根节点,第一个比它大的数是其右节点 右子树范围为(左根节点,右根节点)·对于每个根节点,第一个比他小的数是其左节点 左子树范围为(0,左根节点)·左根节点必须在右根节点的前面·每一次递归的时候根节点都应比左子树的所有元素要大-只需判断每个子树是否递归的满足该结论代码如下:public boolean verifyPostorder(int[] posto原创 2020-12-24 04:21:38 · 77 阅读 · 0 评论 -
leeetcode随机每日一题 528.按权重随机选择
思路: 看到题目,思考了三分钟,想起了遗传算法里的轮盘赌算法,思路和这个一样的。特别要注意区间问题代码如下://528.按权重随机选择public class Solution528 { int arr[]; public Solution528(int[] w) { arr = new int[w.length]; arr[0] = w[0]; for (int i = 1; i < w.length; i++) { .原创 2021-04-16 12:04:55 · 120 阅读 · 0 评论 -
leetcode随机每日一题 107.二叉树的层序遍历II
本题的关键在于,判断每一层有多少个数,如果单纯的把所有的null全部放进去,然后每一层为2的x次幂,那么层数过多的时候,由于null过多导致null冗余,最后会超出时间限制,所以不能单纯的使用2的x次幂。解决方案:每一层的数字个数恰好是当前队列的大小代码://改进:每层的size正好为当前queue的sizepublic class Solution107 { public List<List<Integer>> levelOrderBottom(TreeNode .原创 2021-04-15 23:10:53 · 98 阅读 · 0 评论