classSolution{ publicintmaxProduct(int[] A){ // store the result that is the max we have found so far int r = Integer.MIN_VALUE; int imax = 1; int imin = 1;
// imax/imin stores the max/min product of // subarray that ends with the current number A[i] for (int i = 0; i < A.length; i++) { // multiplied by a negative makes big number smaller, small number bigger // so we redefine the extremums by swapping them if (A[i] < 0) { int tmp = imax; imax = imin; imin = tmp; } // max/min product for the current number is either the current number itself // or the max/min by the previous number times the current one imax = Math.max(A[i], imax * A[i]); imin = Math.min(A[i], imin * A[i]);
// the newly computed max value is a candidate for our global result r = Math.max(r, imax); } return r; }
publicintmaxProduct(int[] A){ int r = Integer.MIN_VALUE; int[] dpMax = newint[A.length + 1]; dpMax[0] = 1; int[] dpMin = newint[A.length + 1]; dpMin[0] = 1; for (int i = 1; i <= A.length; i++) { if (A[i-1] < 0) { int tmp = dpMax[i-1]; dpMax[i-1] = dpMin[i-1]; dpMin[i-1] = tmp; } dpMax[i] = Math.max(A[i-1],dpMax[i-1]*A[i-1]); dpMin[i] = Math.min(A[i-1],dpMin[i-1]*A[i-1]);
classSolution{ publicintlengthOfLIS(int[] nums){ int[] dp = newint[nums.length+1]; // base case:dp 数组全都初始化为 1 Arrays.fill(dp, 1); int res = 0; for (int i = 1; i <= nums.length; i++) { for (int j = 1; j < i; j++) { if (nums[i-1] > nums[j-1]) dp[i] = Math.max(dp[i], dp[j] + 1); } res = Math.max(res, dp[i]); } return res; }
publicintlengthOfLIS(int[] nums){ int[] tails = newint[nums.length]; int size = 0; for (int x : nums) { int i = 0, j = size; while (i != j) { int m = (i + j) / 2; if (tails[m] < x) i = m + 1; else j = m; } tails[i] = x; if (i == size) ++size; } return size; } }
背包问题
0-1 背包问题
给你一个可装载重量为 totalWeight 的背包和 N 个物品,每个物品有重量和价值两个属性。其中第 i 个物品的重量为 wt[i],价值为 val[i],现在让你用这个背包装物品,最多能装的价值是多少?
N = 3, totalWeight = 4 weight = [2, 1, 3] value = [4, 2, 3]
/** * dp[3][5] = 6,其含义为:对于给定的一系列物品中,若只对前 3 个物品进行选择,当背包容量为 5 时,最多可以装下的价值为 6。 */ intknapsack(int totalWeight, int[] weight, int[] value){ // base case 已初始化 int[][] dp = newint[totalWeight + 1][totalWeight + 1]; for (int i = 1; i <= weight.length; i++) { for (int w = 1; w <= totalWeight; w++) { if (w - weight[i - 1] < 0) { // 这种情况下只能选择不装入背包 dp[i][w] = dp[i - 1][w]; } else { // 装入或者不装入背包,择优 dp[i][w] = Math.max(dp[i - 1][w - weight[i - 1]] + value[i - 1], dp[i - 1][w]); } } } return dp[weight.length][totalWeight]; }
leetcode 416. 分割等和子集
给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
注意:
每个数组中的元素不会超过 100 数组的大小不会超过 200
classSolution{ publicbooleancanPartition(int[] nums){ int sum = 0; for (int num : nums) { sum += num; } if (sum % 2 != 0) { returnfalse; } sum /= 2;
int n = nums.length; boolean[][] dp = newboolean[n+1][sum+1];
// base case for (int i = 0; i <= n; i++) dp[i][0] = true;
for (int i = 1; i <= n; i++) { for (int j = 1; j <= sum; j++) { if (j - nums[i - 1] < 0) { // 背包容量不足,不能装入第 i 个物品 dp[i][j] = dp[i - 1][j]; } else { // 装入或不装入背包 dp[i][j] = dp[i - 1][j] | dp[i - 1][j-nums[i-1]]; } } } return dp[n][sum]; } }