本文主要是介绍2月刷题记录,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
动态规划
NC128 接雨水问题(雨水数量=装满水的容器面积maxArr-容器本身面积arr,而这个装满水的容器数组,规律是递增再递减) NC183 最长公共子数组(二维dp,相等则左上方的数+1,不相等则为0,还要用一个max来维护最大的长度) NC59 矩阵的最小路径和(从上方和左方取一个较小的dp值,加上当前值) BM66 最长公共子串(不相等直接为0,相等的话取左上方的值+1,不断更新max和所在的row和col) BM67 求路径(由于只能向右走和向下走,dp[][]中的值可以通过其上方和左方的值相加获得) BM93 盛水最多的容器(双指针,只需遍历一次,哪边高度小,就把哪边指针往中间移,才有机会获得更大面积) BM64 最小花费爬楼梯(dp定义为到达这个台阶准备再向上走的最小花费。当走到倒数第一个或倒数第二个台阶,就可到达顶部,所以是返回这两者的较小值) BM78 打家劫舍(一)(如果偷第i家,就不能偷第i-1家,最大收益为dp[i-2]+nums[i]。如果不偷第i家,就可以偷第i-1家,最大收益为dp[i-1]) BM79 打家劫舍(二)(和(一)的区别是偷第一家就不能偷最后一家,偷了最后一家就不能偷第一家。可以分两次进行dp再取较大值) BM81 买卖股票的最好时机(二) (和(一)的区别是可以多次买卖。因此遍历一遍数组,只要prices[i]大于prices[i-1],就加上这一段的收益(表示在prices[i-1]买入,在prices[i]卖出),遍历完即可得到最大收益。) BM82 买卖股票的最好时机(三)(先从右向左遍历获得第二次交易的最大收益,具体做法是用f[i]记录从i点到之后的最大收益。再从左向右计算第一次交易的最大收益,具体做法是从以min价格买入,price[i]价格卖出, result = Math.max(result, prices[i] - min + f[i]);)
堆
BM48 数据流中的中位数(小顶堆存较大一半的值,大顶堆存较小一半的值。为了保证有序:长度相等时,先放进大顶堆,再从大顶堆弹出一个元素放入小顶堆。长度不相等时,先放进小顶堆,再从小顶堆弹出一个元素放入大顶堆。取中位数时:长度相等时,取大小顶堆的堆顶的平均数,长度不相等时,小顶堆的堆顶就是中位数 )
二叉树
BM30 二叉搜索树与双向链表(按中序遍历的顺序把整个链表连起来,root用来标记整棵树最左边的结点。递归左子树,连接pre和当前结点,递归右子树,返回root)
二分
NC160 二分查找-I(两种模板,背熟) NC74 数字在升序数组中出现的次数(运用微妙的 + 0.5 和 - 0.5,使用二分法找出数组中第一个大于k和最后一个小于k的数的下标,相减就可以获得k在数组中的长度) NC105 二分查找-II(升序数组中找第一个和target相等的数,这种一般是用while(left<right)的模板) NC48 在旋转过的有序数组中寻找目标值(比较nums[start]和nums[mid]可以知道是前半部分还是后半部分有序,若nums[start]<=nums[mid],且nums[start]<=target<nums[mid] 则在前半部分找。后半部分有序同理) NC32 求平方根(mid<=x/mid&&(mid+1)>x/(mid+1)) NC71 旋转数组的最小数字(i和j分别指向数组的两头,m指向中间。array[m]和arr[j]比就可以得出旋转点在m的左侧还是右侧,然后不断缩小i和j的范围。当i==j时就指向了最小数字(旋转点)) NC254 合法的三角形个数(先选出两条边,再用二分法找符合条件的第三边。) 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]的值) leetcode 35. 搜索插入位置(两种模板) leetcode 34.在排序数组中找到元素的第一个和最后一个位置 (两种模板) NC91 最长上升子序列(三)(dp[i]–以arr[i]为结尾的最长子序列长度,maxEnd[i]–长度为i+1的子序列的最小尾元素,二分法用来在arr中找到第一个大于等于t的数的位置。比较难) leetcode 74. 搜索二维矩阵(这一题每一行都是升序的,而且每一行的开头大于前一行的结尾。 所以可以对行和列做二分,先找到target所在行,再找到target所在列。二分的时候要找的是最后一个小于等于target的位置)
回溯
BM55 没有重复项数字的全排列(做选择,递归,撤销选择) BM56 有重复项数字的全排列(加入mark数组,排除不合法路径 if(mark[i]||i>0&&num[i]==num[i-1]&&!mark[i-1]) continue;)
基础数学
NC79 丑数(忘记了)
模拟
NC57 反转数字(反转后的数字可能用int存不下,先用long来存。while(x!=0){n=n*10+x%10;x=x/10;})
数组
NC36 在两个长度相等的排序数组中找到上中位数(双指针) NC86 矩阵元素查找(贪心法,从左下角的元素开始,比x小则往右走,比x大则往上走,每走一步都可以剔除掉一行或一列) NC202 长度最小的连续子数组(双指针,还没有达到目标值,向右扩展,已经达到目标值,向左收缩) NC252 多数组中位数(和NC36差不多也是双指针,但这题的两个数组长度不同,而且要取的是下中位数(指在两个数组的数个数在偶数时取更小的),mid=(m+n+1)/2) leetcode 240. 搜索二维矩阵 II(和NC86类似,左下角开始搜索) NC283 数组中重复的数字(先排序,再遍历) NC52 数组中只出现一次的两个数字(哈希表,出现第二次的数 从map中删除) BM20 数组中的逆序对(归并排序+计算逆序对) BM53 缺失的第一个正整数(数组中的n个数全部存进哈希表,然后从开始检查有没有1,2,3,。。。n,如果发现缺失,就返回它。如果都有,就返回n+1) BM97 旋转数组 (注意移动位数m可能会超过数组长度n,所以计算位置是要取模的newArr[(i+m)%n]=a[i];) BM98 螺旋矩阵(从最外围开始走到最中心的点。上面从左到右,左面从上到下,下面从右到左,左面从下到上)
贪心
BM95 分糖果问题(从左向右遍历一次,从右向左遍历一次)
栈
NC90 包含min函数的栈(用到辅助栈,将node和minstack的栈顶比较,哪个小就push哪个进minstack,minstack的栈顶永远保存当前stack的最小元素) NC115 栈和排序(用tmp数组存i-n之间最大的数,遍历a数组放入栈,只要栈顶的数比tmp[i+1]大,就弹出来放到res) NC157 单调栈 NC175 合法的括号字符串(遍历字符串是用来处理右括号的:见到右括号,先匹配左括号,没有左括号再匹配星号。如果发现有无法匹配的右括号,直接返回false。检查栈是用来处理左括号的:不断弹出两个栈,一个左括号匹配一个星号(满足左括号在前,星号在后)。如果发现左括号的索引比星号大,直接返回false。最后左括号栈空,才能返回true。) NC208 每日温度(单调栈。要找到每个数右边第一个比它大的数,并计算它们俩的差值,可以用一个递减的单调栈,每遍历一个数,与栈顶比较,比栈顶小则直接入栈,比栈顶大则不断让栈顶先弹出,记录弹出位置为pre,当前为i,则差值为i-pre) NC216 逆波兰表达式求值(遇到一个符号则计算前两个数。可以用栈解决。) NC209 最短无序连续子数组(nums[i]满足大于等于左边的最大值,小于等于右边的最小值,这个数在数组中就是不需要移动位置的。所以要从左到右遍历记录当前maxleft,从右到左遍历记录当前minright,找到无序的左边界和右边界,return r-l+1)
这篇关于2月刷题记录的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!