leetcode刷刷刷(一)

来源:互联网 发布:网络拓扑结构及配置 编辑:程序博客网 时间:2024/04/30 12:53

动态规划(自底向上):

338.countingbits(二进制串中有多少个1)

例:如果输入5,应该输出0,1,1,2,1,2

动态规划的最优子结构:f[i] = f[i / 2] + i % 2

647.Palindromic Substrings(求回文子串数量)

例:如果输入aaa,应输出6(a,a,a,aa,aa,aa,aaa)

二维数组dp[i][j]代表从位置i到位置j的子串是否是回文子串

动态规划的最优子结构:dp[i][j] = (s.charAt(i)==s.charAt(j)) && ( j-i<3 || dp[i+1][j-1] )

判断一个字符串是否是回文,首先知道去掉首尾字符的子串是否是回文;

去首尾子串是回文的情况下,若首尾相等则该字符串也为回文

516.Longest Palindromic Substrings(最长回文子序列长度)

例:输入bbbab,输出4(bbbb)

二维数组dp[i][j]代表从位置i到位置到位置j的最长回文子序列长度

动态规划的最优子结构:if(s.charAt(i)==s.charAt(j) && i < j-1) dp[i][j] = dp[i+1][j-1] + 2

计算最长回文子序列时,若首尾相等,则在去掉首位情况下的最长序列的长度加2;

若首尾不等则dp[i][j] = max(dp[i][j-1] ,dp[i+1][j])  【思路与求回文子串数量相同】

413. Arithmetic Slices(求算术切片数量)

例:输入1,2,3,4,应输出3(123,234,1234)

数组dp[i]代表以第i个元素为结尾的算术切片个数

动态规划的最优子结构:如果A[i] -A[i-1] =A[i-1] - A[i-2],则 dp[i] = dp[i-1]+1;否则dp[i] = 0

646. Maximum Length of Pair Chain(求最长链、贪心)

例:输入[1,2][2,3][3,4],应输出2([1,2][3,4])

本题使用贪心算法更为简便,是活动安排问题的变形

根据第二个元素从小到大排序,后通过一次遍历可得最长链

思路:总是选取当前具有最早完成时间的活动加入链中,可以为为安排的活动留下尽可能多的时间

343.Integer Break(正整数分解求最大积)

例:输入10,应输出36(3*3*4)

数组dp[i]代表正整数i的分解因子相乘的最大积

动态规划最优子结构:dp[i] = max( dp[i], max(j,dp[j]) * max(i-j,dp[i-j]) )

其中j代表i的分解因子,从1到i-1遍历

此题最简便方法是找到3的规律,只要尽可能多的分解出3,即可得到最大积

486.Predict the Winner(从数组两端取数,和最大胜利)

例:输入1,5,199,20,输出true(因为先手可以获得胜利)

二维数组dp[i][j]代表从i位置到j位置进行取数游戏,先手最多比后手多拿多少分数

动态规划最优子结构:dp[i][j]=max( num[i]-dp[i+1][j] , num[j]-dp[i][j-1] )

最终根据dp[0][n-1]的正负来判断是否可以获得胜利

392.Is Subsequence(是否是子序列)

例:输入asjbut、abt,输出true(后者是前者的子序列)

题,用两个指针遍历即可(不懂为啥放在动态规划一类。。)

650.2 Keys Keyboard(复制粘贴最少次数问题)

例:输入3,输出3(起初只有一个A,要获得三个:1.copy 2.paste 3.paste)

动态规划最优子结构:当i%j==0时,dp[i] = dp[j] + i/j

dp[i]代表获得i个A所需操作的最少次数,指针j从i向1遍历,找到第一个可以被i整除的j

此时获得i个A就在j个A的基础上复制一次,粘贴i/j - 1次,总操作次数为i/j次

416.Partition Equal Subset Sum(能否划分成两个和相等的子集)

例:输入1,2,3,6,输出true(1+2+3=6)

1.(二维数组)动态规划的最优子结构:j>=nums[i]时,dp[i][j] = dp[i-1][j]||dp[i-1][j-nums[i]];否则dp[i][j]=dp[i-1][j]

两层循环:i是1到nums.length-1,j是1到sum/2

dp[i][j]代表,位置i之前的元素是否可以组合产生j;

2.(一维数组)动态规划的最优子结构:j>=nums[i]时,dp[j]=dp[j]||dp[j-sum[i]]

同样是双层循环,i是0到nums.length-1,j是sum/2到1

dp[j]代表,当前位置之前的元素是否可以组合产生j,用一维代替二维,对j的遍历变为从大到小,防止更新dp[j]时用到新的dp[j-sum[i]]

494.Target Sum(给定数组,用加减号连接成式子,结果为S,求有多少种组合)

例:输入[1,1,1,1,1]和3,输出5

数组可分为正负两个子集,正子集和减去负子集和即为S;则可推出正子集和(sum+S)/2,负子集和为(sum-S)/2

即可转化成416题同类型题目subset sum

动态规划最优子结构:j>=nums[i]时,dp[j]=dp[j]+dp[j-nums[i]]

312.Burst Balloons(打破气球获得左右和本身乘积,求最大乘积和)【hard】

例:输入[3,1,5,8],输出167(3*1*5+3*5*8+1*3*8+1*8*1=167)假设nums[-1]=nums[n]=1

建立新数组rnums[len+2],即增加头尾俩个1

dp[left][right]代表打破位置left到位置right之间的气球所获得最大乘积,由i在left+1到right-1之间遍历,其中i代表着最后打破的气球序号

动态规划最优子结构:dp[left][right] = Math.max(dp[left][right],rnums[left]*rnums[i]*rnums[right]+dp[left][i]+dp[i][right])

689.Maximum Sum of 3 Non-Overlapping Subarrays(求三个无重叠子数组和的最大值)【hard】

例:输入[1,2,1,2,6,7,5,1]和2,输出[0,3,5](从位置0,3,5起的三个长度为2的子数组和最大)

三个子数组中,第二个数组的起始位置的范围应在k到len-2k之间;

那么第一个数组的结束位置的范围应在k-1到len-2k-1之间,第三个数组的起始位置的范围应在2k到len-k之间;

求出左边的以i为结束的最大k段数组的起始位置,k-1<=i<=len-2k-1;求出右边的以i为起始的最大k段数组的起始位置,2k<=i<=len-k;

最后以i遍历k到len-2k,得到以i-1为结束的最大k段数组的起始位置和以i+k为起始的最大k段数组的起始位置,通过i的遍历取得和的最大值。

377.Combination Sum IV(爬楼梯问题变形)

例:输入[1,2,3]和4,输出7(1111,112,121,13,211,22,31)

用数组onestep存储,一步是否可以达到

dp[target]代表要达到target有多少种方法,当onestep[target-i]为真,dp[target]+=dp[i](考虑最后一步)

198.House Robber(数组不相连元素最大和)

例:输入[1,2,3,4,4],输出8(1+3+4)

水题,动态规划的最优子结构:dp[i] = max(dp[i-1],dp[i-2]+nums[i])

96.Unique Binary Search Trees(独特二叉搜索树的个数)

例:输入3,输出5

水题,动态规划最优子结构:1<j<i-1时,dp[i]+=dp[j]*dp[i-1-j];j=1ori-1时,dp[i]+=dp[i-1]