学习目标:
每天复习代码随想录上的题目2-3道算法(时间充足可以继续)以及八股
今日碎碎念:
1)进入背包专题,过完准备二刷,以及刷剑指offer。
2)优化一下简历
3)坚持住吧,秋招马上来了!
力扣刷题
算法
力扣1049:1049. 最后一块石头的重量 II
解答思路:
1)本题思路大体上和分割等和子集是类似的,既然要尽可能粉碎石头,那么就要分成近似的两堆,
class Solution {
public int lastStoneWeightII(int[] stones) {
int len = stones.length;
int []dp = new int[1501];
int sum = 0;
//本题和分割等和子集类似,就是尽可能把石头分成近似重量的两堆
for(int i : stones) sum+=i;
int tar = sum / 2;
for(int i = 0;i<len;i++){
for(int j = tar;j>=stones[i];j--){
dp[j] = Math.max(dp[j],dp[j-stones[i]]+stones[i]);
}
}
return sum - dp[tar] - dp[tar];
}
}
力扣494:494. 目标和
解答思路:
1)本题难点在于思维
1.1)我们用i去遍历所有数,用j来拆分i,我们可以得到,题目中要求的拆分成k个数,其实最终体现出来的就是两个数,什么意思呢?我们要拆一个数,首先不是去思考一下子要拆成多少个合理,而是先考虑拆成最符合的两个数,然后分别对这两个数继续拆分。
2)方程怎么得到?最大是:dp[i],当前新拆分,之前拆分的
3)而我们可以推出来,越相近的两个数乘积会越大,因此在拆分i的时候,我们其实只需要遍历到i/2即可
class Solution {
public int integerBreak(int n) {
//dp[i]:拆分i得到的最大乘积为dp[i]
int[]dp = new int[n+1];
dp[0] = 0;
dp[1] = 1;
dp[2] = 1;
//遍历找答案
for(int i = 3;i<=n;i++){
//拆分i
//或者写成for(int j = 1;j<i/2;j++)
for(int j = 1;j<i-1;j++){
dp[i] = Math.max(dp[i],Math.max(j*(i-j),dp[i-j]*j));
}
}
return dp[n];
}
}
力扣474:474. 一和零
class Solution {
public int findMaxForm(String[] strs, int m, int n) {
//dp[i][j]:最多有i个0和j个1的strs的最大子集的大小为dp[i][j]。
//难点主要在想清楚背包定义是什么
int[][]dp = new int[m+1][n+1];
//初始化为0即可
for(String str : strs){
//先将当前串的0和1统计出来
int one = 0;
int zero = 0;
for(char cs : str.toCharArray()){
if(cs == '1') one++;
else if(cs == '0') zero++;
}
//此次开始遍历背包--倒着找就行
for(int i = m;i>=zero;i--){
for(int j = n;j>=one;j--){
dp[i][j] = Math.max(dp[i][j],dp[i-zero][j-one]+1);
}
}
}
return dp[m][n];
}
}