10.柠檬水找零 860. 柠檬水找零 - 力扣(LeetCode)
java
class Solution {
public boolean lemonadeChange(int[] bills) {
//每次都尽可能地找大的零钱
int[] amount=new int[2];//分别代表5,10
for(int bill:bills)
{
if(bill==5)//无需找钱
{
amount[0]++;
}
else
{
//看有没有5块
if(amount[0]<1)
{
return false;
}
amount[0]--;
if(bill==10)
{
amount[1]++;
}
else if(bill==20)
{
if(amount[1]>0)
{
amount[1]--;
}
else
{
if(amount[0]>=2)
{
amount[0]-=2;
}
else
{
return false;
}
}
}
}
}
return true;
}
}
11.根据身高重建队列 406. 根据身高重建队列 - 力扣(LeetCode)
java
class Solution {
public int[][] reconstructQueue(int[][] people) {
Arrays.sort(people, new Comparator<int[]>(){
public int compare(int[] person1, int[] person2){
if(person1[0]!=person2[0]){
return person1[0] - person2[0];
}
else
{
return person2[1]-person1[1];
}
}
});
int n = people.length;
int[][] ans = new int[n][];
for(int[] person:people){
int spaces=person[1]+1;
for(int i=0;i<n;i++){
if(ans[i]==null){
--spaces;
if(spaces==0){
ans[i]=person;
break;
}
}
}
}
return ans;
}
}
12.用最少数量的箭引爆气球 452. 用最少数量的箭引爆气球 - 力扣(LeetCode)
java
class Solution {
public int findMinArrowShots(int[][] points) {
//定义排序
Arrays.sort(points, new Comparator<int[]>(){
public int compare(int[] point1,int[] point2){
if(point1[0]!=point2[0]){
return Integer.compare(point1[0],point2[0]);
}
else
{
return Integer.compare(point1[1],point2[1]);
}
}
});
int arrowCnt=1;
int curEnd=points[0][1];
//计算重复区间
for(int i=1;i<points.length;i++){
if(points[i][0]>curEnd){
arrowCnt++;
curEnd=points[i][1];
}
else
{
curEnd=Math.min(curEnd,points[i][1]);
}
}
return arrowCnt;
}
}
13.无重叠区间 435. 无重叠区间 - 力扣(LeetCode)
java
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
//按照前一个进行排序
Arrays.sort(intervals, new Comparator<int[]>(){
public int compare(int[] interval1, int[] interval2){
return Integer.compare(interval1[1],interval2[1]);
}
});
//然后总的减去无重叠的部分 就是去掉的部分
int cnt=1;
int curEnd=intervals[0][1];
for(int i=1;i<intervals.length;i++){
if(intervals[i][0]>=curEnd)//没重叠
{
cnt++;
curEnd=intervals[i][1];
}
}
return intervals.length-cnt;
}
}
14.划分字母区间 763. 划分字母区间 - 力扣(LeetCode)
java
class Solution {
public List<Integer> partitionLabels(String s) {
//记录每个字母最后出现的位置 然后每一次有一次新的字母 就对可能的最后位置进行更新
//直到已经到达最后位置为止
int[] last=new int[26];
for(int i=0;i<s.length();i++)
{
last[s.charAt(i)-'a']=i;
}
List<Integer> ans=new ArrayList<>();
int end=0,start=0;
for(int i=0;i<s.length();i++)
{
end=Math.max(end,last[s.charAt(i)-'a']);
if(i==end)//已经是满足的了 可进行分割
{
ans.add(end-start+1);
start=end+1;
}
}
return ans;
}
}
动态规划
1.理论基础
简单的斐波那契和爬楼梯
背包问题
打家劫舍
股票问题
子序列问题
dp数组的含义以及递推公式
遍历顺序(背包问题,先遍历背包后遍历物品)
2.斐波那契数列 509. 斐波那契数 - 力扣(LeetCode)
java
class Solution {
public int fib(int n) {
if(n<2)
{
return n;
}
int[] tmp=new int[n+1];
tmp[0]=0;
tmp[1]=1;
for(int i=2;i<=n;i++)
{
tmp[i]=tmp[i-1]+tmp[i-2];
}
return tmp[n];
}
}
3.爬楼梯 70. 爬楼梯 - 力扣(LeetCode)
java
class Solution {
public int climbStairs(int n) {
//两种方式 一种是直接上一步 另一种就是上两步 所以也是n-1+n-2
if(n<2)
{
return 1;
}
int[] f=new int[n+1];
f[0]=1;
f[1]=1;
for(int i=2;i<=n;i++)
{
f[i]=f[i-1]+f[i-2];
}
return f[n];
}
}
4.使用最小花费爬楼梯 746. 使用最小花费爬楼梯 - 力扣(LeetCode)
java
class Solution {
public int minCostClimbingStairs(int[] cost) {
//其实也是两个中取最小值 min(f[n-1]+cost[i-1],f[n-2]+cost[i-2])
int n=cost.length;
if(n<2)
{
return 0;
}
int[] f=new int[n+1];
f[0]=0;
f[1]=0;
for(int i=2;i<=n;i++)
{
f[i]=Math.min(f[i-1]+cost[i-1],f[i-2]+cost[i-2]);
}
return f[n];
}
}
5.不同路径 62. 不同路径 - 力扣(LeetCode)
java
class Solution {
public int uniquePaths(int m, int n) {
int[][] dp=new int[m][n];
dp[0][0]=0;
for(int i=0;i<n;i++)
{
dp[0][i]=1;
}
for(int i=0;i<m;i++)
{
dp[i][0]=1;
}
for(int i=1;i<m;i++)
{
for(int j=1;j<n;j++)
{
dp[i][j]=dp[i-1][j]+dp[i][j-1];//两个方向的可能情况相加
}
}
return dp[m-1][n-1];
}
}
6.不同路径Ⅱ 62. 不同路径 - 力扣(LeetCode)
java
class Solution {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int m=obstacleGrid.length,n=obstacleGrid[0].length;
int[][] dp=new int[m+1][n+1];
dp[0][1]=1;//包是1的 不然游戏进行不下去了
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
if(obstacleGrid[i][j]==1)
{
continue;
}
dp[i+1][j+1]=dp[i][j+1]+dp[i+1][j];//两个方向的可能情况相加
}
}
return dp[m][n];
}
}
7.整数拆分 343. 整数拆分 - 力扣(LeetCode)
java
class Solution {
public int integerBreak(int n) {
//从小记到大 dp[1]=1 dp[2]=2 dp[3]=max(dp[3-i]*dp[i]) ... dp[n]=max(dp[n-i]*dp[i])
if(n<=2)
{
return 1;
}
int[] dp=new int[n+1];
dp[2]=1;
dp[3]=2;
for(int i=4;i<=n;i++)
{
for(int j=1;j<=i/2;j++)
{
//拆分成两个 和拆成很多个取最大值
int cur=Math.max(dp[j],j)*Math.max(dp[i-j],i-j);
dp[i]=Math.max(cur,dp[i]);
}
}
return dp[n];
}
}
8.不同的二叉搜索树 96. 不同的二叉搜索树 - 力扣(LeetCode)
卡特兰公式
java
class Solution {
public int numTrees(int n) {
int[] dp=new int[n+1];
dp[0]=1;
dp[1]=1;
for(int i=2;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
dp[i]+=dp[j-1]*dp[i-j];
}
}
return dp[n];
}
}
9.0-1背包理论
暴力求解:dfs回溯,选与不选
**动规:**dp[i] [j] [0,i]物品任取放置容量为j的背包中,背包的最大价值
所以就是放i物品和不放i物品 dp[i] [j]=max(dp[i-1] [j],dp[i-1] [j-weight[i]]+value[i])//放和不放
初始化第一排和第一列
10.0-1背包之滚动数组
其实可以化为一维的,dp[i]是容量为i的背包可以背的最大价值
dp[i]=max(dp[i],dp[i-weight[j]]+value[j])
初始化非常重要,只要看当前值是否大于i=0的那个,小于的时候初始化为0
两个for循环,一个遍历物品,一个遍历背包(倒序)