From 233d50dbed231a666ea276b758eb21426982750a Mon Sep 17 00:00:00 2001 From: markilue <745518019@qq.com> Date: Tue, 14 Feb 2023 14:02:45 +0800 Subject: [PATCH] =?UTF-8?q?leecode=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../leecode/dynamic/second/T01_Fib.java | 71 +++++++++++++ .../dynamic/second/T02_ClimbStairs.java | 58 ++++++++++ .../second/T03_MinCostClimbingStairs.java | 58 ++++++++++ .../dynamic/second/T04_UniquePaths.java | 87 +++++++++++++++ .../second/T05_UniquePathsWithObstacles.java | 100 ++++++++++++++++++ .../dynamic/second/T06_IntegerBreak.java | 80 ++++++++++++++ 6 files changed, 454 insertions(+) create mode 100644 Leecode/src/main/java/com/markilue/leecode/dynamic/second/T01_Fib.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/dynamic/second/T02_ClimbStairs.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/dynamic/second/T03_MinCostClimbingStairs.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/dynamic/second/T04_UniquePaths.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/dynamic/second/T05_UniquePathsWithObstacles.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/dynamic/second/T06_IntegerBreak.java diff --git a/Leecode/src/main/java/com/markilue/leecode/dynamic/second/T01_Fib.java b/Leecode/src/main/java/com/markilue/leecode/dynamic/second/T01_Fib.java new file mode 100644 index 0000000..51177a2 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/dynamic/second/T01_Fib.java @@ -0,0 +1,71 @@ +package com.markilue.leecode.dynamic.second; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.dynamic.second + *@Author: markilue + *@CreateTime: 2023-02-14 10:15 + *@Description: + * TODO 力扣509题 斐波那契数: + * 斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是: + * F(0) = 0,F(1) = 1 + * F(n) = F(n - 1) + F(n - 2),其中 n > 1 + * 给定 n ,请计算 F(n) 。 + *@Version: 1.0 + */ +public class T01_Fib { + + /** + * 递归: + * 时间复杂度O(2^n) + * 速度击败10.43% 内存击败88.93% 9ms + * @param n + * @return + */ + public int fib(int n) { + if (n < 2) return n; + return fib(n - 1) + fib(n - 2); + + } + + /** + * 动态规划法: + * 1.dp定义:dp[i]表示n=i时的斐波那契数 + * 2.dp状态转移方程: dp[i]=dp[i-1]+dp[i-2] + * 3.dp初始化;dp[0]=0;dp[1]=1; + * 4.dp遍历顺序:从前往后 + * 5.dp举例推导: + * 时间复杂度O(N) + * 速度击败100% 内存击败33.74% 0ms + * @param n + * @return + */ + public int fib1(int n) { + if (n < 2) return n; + int[] dp = new int[n + 1]; + dp[0] = 0; + dp[1] = 1; + for (int i = 2; i <= n; i++) { + dp[i] = dp[i - 1] + dp[i - 2]; + } + return dp[n]; + } + + /** + * 动态规划法:一维dp优化 + * 速度击败100% 内存击败9.5% + * @param n + * @return + */ + public int fib2(int n) { + if (n < 2) return n; + int dp0 = 0; + int dp1 = 1; + for (int i = 2; i <= n; i++) { + int temp = dp1; + dp1 = dp1 + dp0; + dp0 = temp; + } + return dp1; + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/dynamic/second/T02_ClimbStairs.java b/Leecode/src/main/java/com/markilue/leecode/dynamic/second/T02_ClimbStairs.java new file mode 100644 index 0000000..28898b3 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/dynamic/second/T02_ClimbStairs.java @@ -0,0 +1,58 @@ +package com.markilue.leecode.dynamic.second; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.dynamic.second + *@Author: markilue + *@CreateTime: 2023-02-14 10:29 + *@Description: + * TODO 力扣70题 爬楼梯: + * 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 + * 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? + * 1= 2 ),并使这些整数的乘积最大化。 + * 返回 你可以获得的最大乘积 。 + *@Version: 1.0 + */ +public class T06_IntegerBreak { + + /** + * 根据证明:一个数拆成2和3的组合是最大的,依次进行递推 + * 1.dp定义; dp[i]表示i拆分后的乘积最大值 + * 2.dp状态转移方法: dp[i]=max(dp[i-2]*2,dp[i-3]*3) + * 3.dp初始化:dp[1]=1,dp[2]=2,dp[3]=3 + * 4.dp遍历顺序:从前往后 + * 5.dp举例推导: 以10为例 + * i=4:4 + * i=5:6 + * i=6:9 + * i=7:12 + * i=8:18 + * i=9:27 + * i=10:36 + * @param n + * @return + */ + public int integerBreak(int n) { + if(n<4)return n-1; + + int[] dp = new int[n+1]; + dp[1]=1;dp[2]=2;dp[3]=3; + + for (int i = 4; i <= n; i++) { + dp[i]=Math.max(dp[i-2]*2,dp[i-3]*3); + } + return dp[n]; + + } + + + /** + * 思路:如何未知拆成2或3最大呢? for循环,遍历拆 + * @param n + * @return + */ + public int integerBreak1(int n) { + int[] dp = new int[n+1]; + dp[2]=1; + + for (int i = 2; i <= n; i++) { + //遍历j进行拆分 + for (int j = 1; j < i; j++) { + //这里dp[i]可以不用进行初始化,因为dp[i]一定比0大 + dp[i]=Math.max(dp[i],Math.max((i-j)*j,dp[i-j]*j)); + } + } + + return dp[n]; + + } + + public int integerBreak2(int n) { + if (n <= 3) { + return n - 1; + } + int[] dp = new int[n + 1]; + dp[2] = 1; + for (int i = 3; i <= n; i++) { + dp[i] = Math.max(Math.max(2 * (i - 2), 2 * dp[i - 2]), Math.max(3 * (i - 3), 3 * dp[i - 3]));//这样才是合理的 + } + return dp[n]; + } + +}