2月刷题记录

动态规划

  1. NC128 接雨水问题(雨水数量=装满水的容器面积maxArr-容器本身面积arr,而这个装满水的容器数组,规律是递增再递减)
  2. NC183 最长公共子数组(二维dp,相等则左上方的数+1,不相等则为0,还要用一个max来维护最大的长度)
  3. NC59 矩阵的最小路径和(从上方和左方取一个较小的dp值,加上当前值)
  4. BM66 最长公共子串(不相等直接为0,相等的话取左上方的值+1,不断更新max和所在的row和col)
  5. BM67 求路径(由于只能向右走和向下走,dp[][]中的值可以通过其上方和左方的值相加获得)
  6. BM93 盛水最多的容器(双指针,只需遍历一次,哪边高度小,就把哪边指针往中间移,才有机会获得更大面积)
  7. BM64 最小花费爬楼梯(dp定义为到达这个台阶准备再向上走的最小花费。当走到倒数第一个或倒数第二个台阶,就可到达顶部,所以是返回这两者的较小值)
  8. BM78 打家劫舍(一)(如果偷第i家,就不能偷第i-1家,最大收益为dp[i-2]+nums[i]。如果不偷第i家,就可以偷第i-1家,最大收益为dp[i-1])
  9. BM79 打家劫舍(二)(和(一)的区别是偷第一家就不能偷最后一家,偷了最后一家就不能偷第一家。可以分两次进行dp再取较大值)
  10. BM81 买卖股票的最好时机(二) (和(一)的区别是可以多次买卖。因此遍历一遍数组,只要prices[i]大于prices[i-1],就加上这一段的收益(表示在prices[i-1]买入,在prices[i]卖出),遍历完即可得到最大收益。)
  11. BM82 买卖股票的最好时机(三)(先从右向左遍历获得第二次交易的最大收益,具体做法是用f[i]记录从i点到之后的最大收益。再从左向右计算第一次交易的最大收益,具体做法是从以min价格买入,price[i]价格卖出, result = Math.max(result, prices[i] - min + f[i]);)

  1. BM48 数据流中的中位数(小顶堆存较大一半的值,大顶堆存较小一半的值。为了保证有序:长度相等时,先放进大顶堆,再从大顶堆弹出一个元素放入小顶堆。长度不相等时,先放进小顶堆,再从小顶堆弹出一个元素放入大顶堆。取中位数时:长度相等时,取大小顶堆的堆顶的平均数,长度不相等时,小顶堆的堆顶就是中位数 )

二叉树

  1. BM30 二叉搜索树与双向链表(按中序遍历的顺序把整个链表连起来,root用来标记整棵树最左边的结点。递归左子树,连接pre和当前结点,递归右子树,返回root)

二分

  1. NC160 二分查找-I(两种模板,背熟)
  2. NC74 数字在升序数组中出现的次数(运用微妙的 + 0.5 和 - 0.5,使用二分法找出数组中第一个大于k和最后一个小于k的数的下标,相减就可以获得k在数组中的长度)
  3. NC105 二分查找-II(升序数组中找第一个和target相等的数,这种一般是用while(left<right)的模板)
  4. NC48 在旋转过的有序数组中寻找目标值(比较nums[start]和nums[mid]可以知道是前半部分还是后半部分有序,若nums[start]<=nums[mid],且nums[start]<=target<nums[mid] 则在前半部分找。后半部分有序同理)
  5. NC32 求平方根(mid<=x/mid&&(mid+1)>x/(mid+1))
  6. NC71 旋转数组的最小数字(i和j分别指向数组的两头,m指向中间。array[m]和arr[j]比就可以得出旋转点在m的左侧还是右侧,然后不断缩小i和j的范围。当i==j时就指向了最小数字(旋转点))
  7. NC254 合法的三角形个数(先选出两条边,再用二分法找符合条件的第三边。)
  8. NC164 最长上升子序列(二)(在动态规划03中做过最基础的LIS,同样的题目,但这道题要求时间复杂度是nlogn,因此需要结合二分来做。动态规划的dp[i]含义有变化:dp[i]存储的是长度为i+1的子序列的尽可能小的结尾值。遍历a[i]的时候,如果a[i]比dp的最后一个值大:把a[i]加入到dp的结尾。如果a[i]比dp的最后一个值小/相等:a[i]就可以替换掉dp中的某个值,但换哪一个?就要用二分法找到第一个大于等于a[i]的值)
  9. leetcode 35. 搜索插入位置(两种模板)
  10. leetcode 34.在排序数组中找到元素的第一个和最后一个位置 (两种模板)
  11. NC91 最长上升子序列(三)(dp[i]–以arr[i]为结尾的最长子序列长度,maxEnd[i]–长度为i+1的子序列的最小尾元素,二分法用来在arr中找到第一个大于等于t的数的位置。比较难)
  12. leetcode 74. 搜索二维矩阵(这一题每一行都是升序的,而且每一行的开头大于前一行的结尾。
    所以可以对行和列做二分,先找到target所在行,再找到target所在列。二分的时候要找的是最后一个小于等于target的位置)

回溯

  1. BM55 没有重复项数字的全排列(做选择,递归,撤销选择)
  2. BM56 有重复项数字的全排列(加入mark数组,排除不合法路径 if(mark[i]||i>0&&num[i]==num[i-1]&&!mark[i-1]) continue;)

基础数学

  1. NC79 丑数(忘记了)

模拟

  1. NC57 反转数字(反转后的数字可能用int存不下,先用long来存。while(x!=0){n=n*10+x%10;x=x/10;})

数组

  1. NC36 在两个长度相等的排序数组中找到上中位数(双指针)
  2. NC86 矩阵元素查找(贪心法,从左下角的元素开始,比x小则往右走,比x大则往上走,每走一步都可以剔除掉一行或一列)
  3. NC202 长度最小的连续子数组(双指针,还没有达到目标值,向右扩展,已经达到目标值,向左收缩)
  4. NC252 多数组中位数(和NC36差不多也是双指针,但这题的两个数组长度不同,而且要取的是下中位数(指在两个数组的数个数在偶数时取更小的),mid=(m+n+1)/2)
  5. leetcode 240. 搜索二维矩阵 II(和NC86类似,左下角开始搜索)
  6. NC283 数组中重复的数字(先排序,再遍历)
  7. NC52 数组中只出现一次的两个数字(哈希表,出现第二次的数 从map中删除)
  8. BM20 数组中的逆序对(归并排序+计算逆序对)
  9. BM53 缺失的第一个正整数(数组中的n个数全部存进哈希表,然后从开始检查有没有1,2,3,。。。n,如果发现缺失,就返回它。如果都有,就返回n+1)
  10. BM97 旋转数组 (注意移动位数m可能会超过数组长度n,所以计算位置是要取模的newArr[(i+m)%n]=a[i];)
  11. BM98 螺旋矩阵(从最外围开始走到最中心的点。上面从左到右,左面从上到下,下面从右到左,左面从下到上)

贪心

  1. BM95 分糖果问题(从左向右遍历一次,从右向左遍历一次)

  1. NC90 包含min函数的栈(用到辅助栈,将node和minstack的栈顶比较,哪个小就push哪个进minstack,minstack的栈顶永远保存当前stack的最小元素)
  2. NC115 栈和排序(用tmp数组存i-n之间最大的数,遍历a数组放入栈,只要栈顶的数比tmp[i+1]大,就弹出来放到res)
  3. NC157 单调栈
  4. NC175 合法的括号字符串(遍历字符串是用来处理右括号的:见到右括号,先匹配左括号,没有左括号再匹配星号。如果发现有无法匹配的右括号,直接返回false。检查栈是用来处理左括号的:不断弹出两个栈,一个左括号匹配一个星号(满足左括号在前,星号在后)。如果发现左括号的索引比星号大,直接返回false。最后左括号栈空,才能返回true。)
  5. NC208 每日温度(单调栈。要找到每个数右边第一个比它大的数,并计算它们俩的差值,可以用一个递减的单调栈,每遍历一个数,与栈顶比较,比栈顶小则直接入栈,比栈顶大则不断让栈顶先弹出,记录弹出位置为pre,当前为i,则差值为i-pre)
  6. NC216 逆波兰表达式求值(遇到一个符号则计算前两个数。可以用栈解决。)
  7. NC209 最短无序连续子数组(nums[i]满足大于等于左边的最大值,小于等于右边的最小值,这个数在数组中就是不需要移动位置的。所以要从左到右遍历记录当前maxleft,从右到左遍历记录当前minright,找到无序的左边界和右边界,return r-l+1)
上一篇:leetcode474. 一和零


下一篇:夯实Java基础(十一)——内部类