Skip to content

Commit

Permalink
leetcode 300
Browse files Browse the repository at this point in the history
  • Loading branch information
YunaiV committed Jul 1, 2019
1 parent 4ca3479 commit 94a3980
Show file tree
Hide file tree
Showing 12 changed files with 587 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0121;

/**
* 贪心算法实现
*/
public class Solution02 {

public int maxProfit(int[] prices) {
if (prices == null || prices.length == 0) {
return 0;
}

int max = 0;
int buy = prices[0];

// 遍历,进行买卖
for (int i = 1; i < prices.length; i++) {
// 计算,当前位置,卖出,能赚多少钱。
max = Math.max(max, prices[i] - buy);
// 计算当前位置值得买不
buy = Math.min(buy, prices[i]);
}

return max;
}

public static void main(String[] args) {
Solution02 solution = new Solution02();
System.out.println(solution.maxProfit(new int[]{7,1,5,3,6,4}));
System.out.println(solution.maxProfit(new int[]{7,1,5,3,6,4,7}));
System.out.println(solution.maxProfit(new int[]{7,6,4,3,1}));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0122;

/**
* 贪心算法实现
*/
public class Solution01 {

public int maxProfit(int[] prices) {
int result = 0;
for (int i = 0; i < prices.length - 1; i++) {
if (prices[i] < prices[i + 1]) {
result += prices[i + 1] - prices[i];
}
}
return result;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0122;

/**
* DP 算法实现
*/
public class Solution02 {

public int maxProfit(int[] prices) {
if (prices == null || prices.length == 0) {
return 0;
}

int zero = 0; // 无持有
int one = -prices[0]; // 持有股票

// 遍历,进行买卖
for (int i = 1; i < prices.length; i++) {
// 尝试卖出
// if (one + (prices[i]) > zero) {
// zero = one + prices[i];
// }
zero = Math.max(zero, one + prices[i]); // 简化
// 尝试买入
// if (zero - prices[i] > one) {
// one = zero - prices[i];
// }
one = Math.max(one, zero - prices[i]); // 简化
}

return Math.max(one, zero);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0123;

public class Solution {

public int maxProfit(int[] prices) {
if (prices == null || prices.length == 0) {
return 0;
}
int k = 2; // 最大交易次数,只能两次
// 第一维度 k ,表示当前【买入股票】的次数;
// 第二维度 2 ,表示 0 - 未持有,1 - 持有 1 股
// 值为最大利润
int[][] dp = new int[k + 1][2];
// 初始化第一个股票的处理
dp[1][1] = -prices[0]; // 买入
dp[2][1] = -prices[0]; // 买入 + 卖出 + 买入
dp[0][1] = Integer.MIN_VALUE; // 相当于赋值为空,避免直接认为持有一股时,利润为 0 。

// 遍历,进行买卖
for (int i = 1; i < prices.length; i++) {
for (int j = 0; j <= k; j++) {
// 尝试卖出
dp[j][0] = Math.max(dp[j][0], dp[j][1] + prices[i]);
// 尝试买入
if (j > 0) {
dp[j][1] = Math.max(dp[j][1], dp[j - 1][0] - prices[i]);
}
}
}

return Math.max(dp[1][0], dp[2][0]);
}

// public int maxProfit(int[] prices) {
// if (prices == null || prices.length == 0) {
// return 0;
// }
// int k = 2; // 最大交易次数,只能两次
// // 第一维度 k ,表示当前【买入股票】的次数;
// // 第二维度 2 ,表示 0 - 未持有,1 - 持有 1 股
// int[][][] dp = new int[prices.length][k + 1][2];
// // 初始化第一个股票的处理
// dp[0][1][1] = -prices[0]; // 买入
//// dp[2][1] = -prices[0]; // 买入 + 卖出 + 买入
//
// // 遍历,进行买卖
// for (int i = 1; i < prices.length; i++) {
// for (int j = 0; j <= k; j++) {
// // 尝试卖出
// dp[i][j][0] = Math.max(dp[i][j][0], dp[i][j][1] + prices[i]);
// // 尝试买入
// if (j > 0) {
// dp[i][j][1] = Math.max(dp[i][j][1], dp[i][j - 1][0] - prices[i]);
// }
// }
// }
//
// return Math.max(dp[prices.length -1][1][0], dp[prices.length - 1][2][0]);
// }

public static void main(String[] args) {
Solution solution = new Solution();
System.out.println(solution.maxProfit(new int[]{3,3,5,0,0,3,1,4}));
System.out.println(solution.maxProfit(new int[]{1,2,3,4,5}));
System.out.println(solution.maxProfit(new int[]{7, 6, 4, 3, 1}));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0152;

@Deprecated // 解法不对
public class Solution01 {

public int maxProduct(int[] nums) {
Integer max = Integer.MIN_VALUE; // 最大值
Integer x = null; // 正数
Integer y = null; // 负数

// 遍历
for (int num : nums) {
if (num >= 0) { // 正数
if (x == null) {
x = num;
} else {
if (num * x > x) {
x = num * x;
} else {
x = num;
}
}
if (y != null) {
if (num == 0) {
y = null;
} else {
y = y * num;
}
}
} else { // 负数
if (y == null) {
if (x == null) {
y = num;
} else {
y = num * x;
x = null;
}
} else {
y = num * y;
if (y > 0) {
x = y;
y = num;
}
}
}
// 判断是否超过
if (x != null && x > max) {
max = x;
}
if (y != null && y > max) { // 处理,整个数组只有一个负数的情况。
max = y;
}
}

return max;
}

public static void main(String[] args) {
Solution01 solution = new Solution01();
// System.out.println(solution.maxProduct(new int[]{2, 3, -2, -4}));
// System.out.println(solution.maxProduct(new int[]{2, 3, -2, 4}));
// System.out.println(solution.maxProduct(new int[]{-2, 0, 1}));
// System.out.println(solution.maxProduct(new int[]{0, 2}));
// System.out.println(solution.maxProduct(new int[]{2, -5, -2, -4, 3}));
System.out.println(solution.maxProduct(new int[]{-1, -2, -9, -6}));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0152;

/**
* dp 方程
*
* dp1[i] = max(dp[i - 1] * nums[i], dp2[i -1] * nums[i], nums[i])
* dp2[i] = min(dp[i - 1] * nums[i], dp2[i -1] * nums[i], nums[i])
*
* 通过不断求,使用上当前数值时,能产生的最大值。
*
* 注意,结果不是 dp1[n - 1] ,而是在这个过程中,产生的最大值。因为 nums 有负数的可能性,导致不一定使用上当前值,就一定是最大值。
*/
public class Solution02 {

public int maxProduct(int[] nums) {
// 最大值
int max = nums[0];
// 使用上当前位置的数,最大值。max 和 dp1 并不等价,因为使用上当前数字后,可能不一定大于 max
int[] dp1 = new int[nums.length];
dp1[0] = nums[0];
// 使用上当前位置的数,最小值。使用最小值的原因是,可以有机会负负得正
int[] dp2 = new int[nums.length];
dp2[0] = nums[0];

// 开始 dp
for (int i = 1; i < nums.length; i++) {
int num = nums[i];
dp1[i] = max(dp1[i - 1] * num, // 如果 num 是正数的情况下,乘以 dp1,会变大
dp2[i - 1] * num, // 如果 num 是负数的情况,乘以 dp2 ,可能反倒比 dp1 大。
num); // 可能上面两个,乘了半天,还不如
dp2[i] = min(dp1[i - 1] * num, dp2[i - 1] * num, num); // 同上面的想法
// 求最大值
max = Math.max(dp1[i], max);
}

return max;
}

private int min(int a, int b, int c) {
return Math.min(Math.min(a, b), c);
}

private int max(int a, int b, int c) {
return Math.max(Math.max(a, b), c);
}

public static void main(String[] args) {
Solution02 solution = new Solution02();
System.out.println(solution.maxProduct(new int[]{2, 3, -2, -4}));
System.out.println(solution.maxProduct(new int[]{2, 3, -2, 4}));
System.out.println(solution.maxProduct(new int[]{-2, 0, 1}));
System.out.println(solution.maxProduct(new int[]{0, 2}));
System.out.println(solution.maxProduct(new int[]{2, -5, -2, -4, 3}));
System.out.println(solution.maxProduct(new int[]{-1, -2, -9, -6}));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0152;

/**
* {@link Solution02} 的改进,不使用两个一维数组,而是直接使用两个变量。
*/
public class Solution03 {

public int maxProduct(int[] nums) {
// 最大值
int max = nums[0];
// 使用上当前位置的数,最大值。max 和 dp1 并不等价,因为使用上当前数字后,可能不一定大于 max
int dp1 = nums[0];
// 使用上当前位置的数,最小值。使用最小值的原因是,可以有机会负负得正
int dp2 = nums[0];

// 开始 dp
for (int i = 1; i < nums.length; i++) {
int num = nums[i];
int[] results = minAndMax(dp1 * num, dp2* num, num);
dp1 = results[1];
dp2 = results[0];
// 求最大值
max = Math.max(dp1, max);
}

return max;
}

private int[] minAndMax(int a, int b, int c) {
return new int[]{Math.min(Math.min(a, b), c),
Math.max(Math.max(a, b), c)};
}

public static void main(String[] args) {
Solution03 solution = new Solution03();
System.out.println(solution.maxProduct(new int[]{2, 3, -2, -4}));
System.out.println(solution.maxProduct(new int[]{2, 3, -2, 4}));
System.out.println(solution.maxProduct(new int[]{-2, 0, 1}));
System.out.println(solution.maxProduct(new int[]{0, 2}));
System.out.println(solution.maxProduct(new int[]{2, -5, -2, -4, 3}));
System.out.println(solution.maxProduct(new int[]{-1, -2, -9, -6}));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package cn.iocoder.springboot.labs.lab09.leetcode.no0188;

/**
* TODO 需要优化,会超过。例如说 k = 10 亿
*/
public class Solution {

public int maxProfit(int k, int[] prices) {
if (prices == null || prices.length == 0) {
return 0;
}

// 超过股票的一半,则只要买的有赚,就买入,第二天卖出。
if (k >= prices.length / 2) {
int result = 0;
for (int i = 0; i < prices.length - 1; i++) {
if (prices[i] < prices[i + 1]) {
result += prices[i + 1] - prices[i];
}
}
return result;
}

// 第一维度 k ,表示当前【买入股票】的次数;
// 第二维度 2 ,表示 0 - 未持有,1 - 持有 1 股
// 值为最大利润
int[][] dp = new int[k + 1][2];
// 初始化第一个股票的处理
for (int i = 1; i <= k; i++) {
dp[i][1] = -prices[0]; // 买入
}
dp[0][1] = Integer.MIN_VALUE; // 相当于赋值为空,避免直接认为持有一股时,利润为 0 。

// 遍历,进行买卖
for (int i = 1; i < prices.length; i++) {
for (int j = 0; j <= k; j++) {
// 尝试卖出
dp[j][0] = Math.max(dp[j][0], dp[j][1] + prices[i]);
// 尝试买入
if (j > 0) {
dp[j][1] = Math.max(dp[j][1], dp[j - 1][0] - prices[i]);
}
}
}

// 求最大值
int max = dp[0][0];
for (int i = 1; i <= k; i++) {
max = Math.max(max, dp[i][0]);
}
return max;
}

public static void main(String[] args) {
Solution solution = new Solution();
System.out.println(solution.maxProfit(2, new int[]{2, 4,1 }));
System.out.println(solution.maxProfit(7, new int[]{3,2,6,5,0,3}));
System.out.println(solution.maxProfit(2, new int[]{3,3,5,0,0,3,1,4}));
System.out.println(solution.maxProfit(2, new int[]{1,2,3,4,5}));
System.out.println(solution.maxProfit(2, new int[]{7, 6, 4, 3, 1}));
}

}
Loading

0 comments on commit 94a3980

Please sign in to comment.