java tip
使int[]排序,使用Arrays.sort()
使list排序,使用Collections.sort()
392
此题中dp[n][z]是指站在n的位置看,出现下一个z
dp[0][a]=2指,在0号位看,下一次出现a是在2号位
因为查找是正向查找,所以建表是逆向建表
public boolean isSubsequence(String s, String t) {
// 预处理
t = " " + t; // 开头加一个空字符作为匹配入口
int n = t.length();
int[][] dp = new int[n][26]; // 记录每个位置的下一个ch的位置
for (char ch = 0; ch < 26; ch++) {
int p = -1;
for (int i = n - 1; i >= 0; i--) { // 从后往前记录dp
dp[i][ch] = p;
if (t.charAt(i) == ch + 'a') p = i;
}
}
// 匹配
int i = 0;
for (char ch : s.toCharArray()) { // 跳跃遍历
i = dp[i][ch - 'a'];
if (i == -1) return false;
}
return true;
}
1139
只有遍历到i=3,j=3,求出dp[3][3][0],dp[3][3][1]才能求出最终结果9
本题要判断一个正方形,只需判断右下角,根据min求出边长,依次找到右上角dp[i-k][j](求出上边长dp[i-k][j][1])和左下角dp[i][j-k](求出左边长dp[i][j-k][0])
但因为存在右下角dp为6,7,但正方形边长最多为4的情况,所以不能直接判断dp[i-k][j][1],而是要遍历min(6,7),求得最大边长
public int largest1BorderedSquare(int[][] grid) {
int m = grid.length, n = grid[0].length;
int[][][] dp = new int[m+1][n+1][2];
// 0 up 1 left;
int ans = 0;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (grid[i-1][j-1] == 0) continue; // 如果是0则不要继续了
dp[i][j][0] = dp[i-1][j][0] + 1; // 求出up情况下连续的个数
dp[i][j][1] = dp[i][j-1][1] + 1; // 求出left情况下连续的个数
int min = Math.min(dp[i][j][0], dp[i][j][1]); // 拿出两者较小的长度,因为四条边都要相等。
for (int k = 0; k < min; k++) {//拿出后并不一定就是min这个长度,有可能另外两条边比较短,没有min长,所以要一个一个判断。
// 判断另外的两条边是否都比当前长度大。
int k1=dp[i-k][j][1];
int k2=dp[i][j-k][0];
if ( k1>= k + 1 && k2>= k + 1)
ans = Math.max(ans, k + 1);
}
}
}
return ans * ans;
}
740
若转化为打家劫舍问题,得有一个LinkedList[],每个位置是同一个数字,但这种麻烦的方法可以用两个数组代替
unsorted int[],可以用Arrays.sort()排序
再制造一个数组表明没个数字的数量
举个例子:
nums = [2, 2, 3, 3, 3, 4]
构造后:
all=[0, 0, 2, 3, 1];
这样可以利用两个数组来替代
public int deleteAndEarn(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
} else if (nums.length == 1) {
return nums[0];
}
int len = nums.length;
int max = nums[0];
for (int i = 0; i < len; ++i) {
max = Math.max(max, nums[i]);
}
// 构造一个新的数组all
int[] all = new int[max + 1];
for (int item : nums) {
all[item] ++;
}
int[] dp = new int[max + 1];
dp[1] = all[1] * 1;
// 动态规划求解
for (int i = 2; i <= max; ++i) {
dp[i] = Math.max(dp[i - 1], dp[i - 2] + i * all[i]);
}
return dp[max];
}
各种背包问题
322
这个方法太快了
如果amount小于coins最大的,求出i=0,然后尝试index-1的硬币大小,完美
int ans = Integer.MAX_VALUE;
public int coinChange(int[] coins, int amount) {
Arrays.sort(coins);
coinChange(coins.length-1, coins, 0, amount);
return ans == Integer.MAX_VALUE ? -1 : ans;
}
private void coinChange(int index, int[] coins, int count, int needAmount) {
if (needAmount == 0) {
ans = Math.min(count, ans);
return;
}
if (index < 0) {
return;
}
int i = needAmount / coins[index];
for (int k=i; k>=0 && count+k<ans; k--) {
coinChange(index-1, coins, count+k, needAmount-k*coins[index]);
}
}
474
注意char一定要转换成int
c[str.charAt(i)-‘0’]++;
the ingenious part lies in the for-loop condition!!!
first exemine that i>zero[0] then checks dp[i-zero[0]]
dp another important fact
focus on the sequence of iterating the array
sometimes is in order, sometimes is reversed order
正向赋值还是反向赋值完全由状态转移方程决定。
public int findMaxForm(String[] strs, int m, int n) {
int[][] dp = new int[m+1][n+1];
for(String str:strs) {
int[] zero = countZero(str);
for (int i = m; i>zero[0];i--){
for(int j=n;j>zero[1];j--){
dp[i][j] =Math.max(1+dp[i-zero[0]][j-zero[1]],dp[i][j]);
}
}
}
return dp[m][n];
}
private int[] countZero(String str) {
int[] c = new int[2];
for(int i=0;i<str.length();i++){
c[str.charAt(i)-'0']++;
}
return c;
}
不用管逆序的方法
public class Solution {
private int[] countZeroAndOne(String str) {
int[] cnt = new int[2];
for (char c : str.toCharArray()) {
cnt[c - '0']++;
}
return cnt;
}
public int findMaxForm(String[] strs, int m, int n) {
int len = strs.length;
int[][][] dp = new int[len + 1][m + 1][n + 1];
for (int i = 1; i <= len; i++) {
// 注意:有一位偏移
int[] cnt = countZeroAndOne(strs[i - 1]);
for (int j = 0; j <= m; j++) {
for (int k = 0; k <= n; k++) {
// 先把上一行抄下来
dp[i][j][k] = dp[i - 1][j][k];
int zeros = cnt[0];
int ones = cnt[1];
if (j >= zeros && k >= ones) {
dp[i][j][k] = Math.max(dp[i - 1][j][k], dp[i - 1][j - zeros][k - ones] + 1);
}
}
}
}
return dp[len][m][n];
}
}
作者:liweiwei1419
链接:https://leetcode-cn.com/problems/ones-and-zeroes/solution/dong-tai-gui-hua-zhuan-huan-wei-0-1-bei-bao-wen-ti/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。