动态规划

This commit is contained in:
whai 2024-03-08 22:49:58 +08:00
parent 2dabc83adb
commit 1eb60f9be4
8 changed files with 525 additions and 4 deletions

View File

@ -0,0 +1,48 @@
package cn.whaifree.leetCode.Dynamic;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/3/8 11:44
* @注释
*/
public class LeetCode509 {
@Test
public void test() {
System.out.println(new Solution1().fib(10));
}
class Solution {
public int fib(int n) {
if (n==0) return 0;
if (n==1) return 1;
return fib(n - 1) + fib(n - 2);
}
}
class Solution1 {
/**
* 1. 确定dp数组dp table以及下标的含义
* 2. 确定递推公式 dp[i] = dp[i - 1] + dp[i - 2];
* 3. dp数组如何初始化 dp[0] = 0; dp[1] = 1;
* 4. 确定遍历顺序
* 5. 举例推导dp数组 0 1 1 2 3 5 8 13 21 34 55
* @param n
* @return
*/
public int fib(int n) {
if (n<=1) 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];
}
}
}

View File

@ -0,0 +1,44 @@
package cn.whaifree.leetCode.Dynamic;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/3/8 12:58
* @注释
*/
public class LeetCode62 {
@Test
public void test(
) {
System.out.println(new Solution().uniquePaths(3, 3));
}
class Solution {
/**
* 确定dp[i,j] 该点可能的路径数
* 递推公式 dp[i,j]= dp[i-1,j] + dp[i,j-1]
* 初始化 dp[0,0]=1
*
* 0 1 1 1 1 1 1
* 1 2 3 4 5 6 7
* 1 3 6 10 15 21 28
* @param m
* @param n
* @return
*/
public int uniquePaths(int m, int n) {
int[][] dp = new int[m][n];
dp[0][0] = 1;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (i>=1) dp[i][j] += dp[i - 1][j];
if (j>=1) dp[i][j] += dp[i][j - 1];
}
}
return dp[m - 1][n - 1];
}
}
}

View File

@ -0,0 +1,42 @@
package cn.whaifree.leetCode.Dynamic;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/3/8 12:11
* @注释
*/
public class LeetCode70 {
@Test
public void test() {
System.out.println(new Solution().climbStairs(0));
}
class Solution {
/**
* 1. 确定dp数组含义 dp[i] 表示到这里的方法数
* 2. 地推公式 dp[i] = dp[i-1]+dp[i-2]
* 3. 初始化 dp[0] = 1;dp[1]=1
* 4. 模拟推导1 1 2 3 5 8
* 0 1 2 3 4 5
* @param n
* @return
*/
public int climbStairs(int n) {
if (n <= 1) {
return n;
}
int[] dp = new int[n];
dp[0] = 1;
dp[1] = 2;
for (int i = 2; i < n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n-1];
}
}
}

View File

@ -0,0 +1,46 @@
package cn.whaifree.leetCode.Dynamic;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/3/8 12:24
* @注释
*/
public class LeetCode746 {
@Test
public void test() {
System.out.println(new Solution().minCostClimbingStairs(new int[]{1,1001}));
}
class Solution {
/**
* 含义 dp[i] 走到这最少支出的花费
* 递推公式
* dp[i] = min{dp[i-2]+cost[i-2] , dp[i-1]+cost[i-1]}
* 初始化 dp[0]=0 dp[1]=0
* 模拟推导
* 1,100,1,1,1,100,1,1,100,1
* 0 0 1 2
*
* @param cost
* @return
*/
public int minCostClimbingStairs(int[] cost) {
//一旦你支付此费用即可选择向上爬一个或者两个台阶
int length = cost.length;
int[] dp = new int[length+1];
dp[0] = 0;
dp[1] = 0;
for (int i = 2; i <= length; i++) {
// 前面两个数有可能跳到本数判断前两个数跳本数的代价
dp[i] = Math.min(dp[i - 2] + cost[i - 2], dp[i - 1] + cost[i - 1]);
}
return dp[length];
}
}
}

View File

@ -2,6 +2,8 @@ package cn.whaifree.leetCode.String;
import org.junit.Test;
import java.util.Arrays;
/**
* 28. 找出字符串中第一个匹配项的下标
*
@ -27,9 +29,9 @@ public class LeetCode28 {
@Test
public void test() {
String haystack = "abc";
String needle = "bc";
int i = new Solution().strStr(haystack, needle);
String haystack = "aabaadaabaaf";
String needle = "aabaaf";
int i = new Solution1().strStr(haystack, needle);
System.out.println(i);
}
@ -47,8 +49,77 @@ public class LeetCode28 {
end++;
}
return -1;
}
}
// KMP
class Solution1 {
public int strStr(String haystack, String needle) {
int[] next = next(needle);
System.out.println(Arrays.toString(next));
int length = haystack.length();
// [0, 1, 0, 1, 2, 0]
// aabaadaabaaf
// aabaaf
int j = 0;
for (int i = 0; i < length; i++) {
// 往前跳
while (j > 0 && needle.charAt(j) != haystack.charAt(i)) {
j = next[j - 1];
}
if (needle.charAt(j) == haystack.charAt(i)) {
j++;
}
if (j == needle.length()) {
return i - needle.length() + 1;
}
}
return -1;
}
// 求Next数组
public int[] next(String s) {
int[] next = new int[s.length()];
int j = 0;
for (int i = 1; i < s.length(); i++) {
// 不匹配
while (j > 0 && s.charAt(i) != s.charAt(j)) {
j = next[j - 1];
}
// 匹配
if (s.charAt(i) == s.charAt(j)) {
j++;
}
next[i] = j;
}
return next;
}
}
}
class Dfather{
static int count = 1;
static{
System.out.println("Initialize class Dfather");
}
}
class Dson extends Dfather{
static{
System.out.println("Initialize class Dson");
}
}
class Test4 {
public static void main(String[] args) {
String a = "d"; //字面量
String b = "d"; //字面量存常量池
System.out.println(a == b);
a = new String("d"); //对象存堆
System.out.println("a=" + a);
System.out.println("b=" + b);
System.out.println(a == b);
}
}

View File

@ -0,0 +1,71 @@
package cn.whaifree.leetCode.String;
import org.junit.Test;
import java.util.Arrays;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/3/7 11:49
* @注释
*/
public class LeetCode459 {
@Test
public void test() {
String s = "aa";
Solution solution = new Solution();
boolean repeatedSubstringPattern = solution.repeatedSubstringPattern(s);
System.out.println(repeatedSubstringPattern);
String aabaaf = "aabaaf";
int[] ints = conNext(new int[aabaaf.length()], aabaaf);
System.out.println(Arrays.toString(ints));
}
class Solution {
/**
* 如果一个串能s被子串重复出现组成 abcabc 由两个abc组成
* - s+s如果能被s组成 abcabcabcabc能被abcabc组成
* @param s
* @return
*/
public boolean repeatedSubstringPattern(String s) {
if (s.length() == 1) {
return false;
}
String contact = s.substring(1) + s.substring(0, s.length() - 1);
if (contact.contains(s)) {
return true;
}
return false;
}
}
public int[] conNext(int[] next, String s) {
// 1. 初始化
int j = 0; // 前缀
// i 为后缀
for (int i = 1; i < next.length; i++) {
//如果前缀后缀不相同不断往前跳前缀
while (j > 0 && s.charAt(i) != s.charAt(j)) {
j = next[j - 1];
}
//前后缀相同设置next[i]为next[i-1]+1, 并且j++
if (s.charAt(i) == s.charAt(j)) {
j++;
}
// 表示j前后相同的部分 aabaa 如果j指向b i指向a那么i前面经历过两次s.i==s.j 对应j=2那么next i对应位置的下标就是前缀j=2
// 实际就是两个指针不断对比如果一样就继续对比下一个数如果不一样就让前缀j进行回退
next[i] = j;
}
return next;
}
// 如何找到
}

View File

@ -0,0 +1,135 @@
package cn.whaifree.leetCode;
import cn.whaifree.leetCode.model.TreeNode;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/3/6 19:14
* @注释
*/
public class Tes1 {
// public static void main(String[] args) {
//// new Tes1().localvarGc1();
//// new Tes1().localvarGc2();
//// new Tes1().localvarGc3();
// new Tes1().localvarGc4();
// }
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("SystemGCTest 重写了finalize()");
}
/**
* -XX:+PrintGCDetail
*/
public void localvarGc1() {
byte[] buffer = new byte[10 * 1024 * 1024];
//10MB
System.gc(); // 成功回收PSYoungGen移动到ParOldGen老年代
/**
* 新生代 PSYoungGen: 15482K->11192K(152576K 10mb
* full gc后移动到老年代 [Full GC (System.gc()) [PSYoungGen: 11192K->0K(152576K)] 0mb [ParOldGen: 8K->10885K(348160K)]
* [GC (System.gc()) [PSYoungGen: 15482K->11192K(152576K)] 15482K->11200K(500736K), 0.0059640 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
* [Full GC (System.gc()) [PSYoungGen: 11192K->0K(152576K)] [ParOldGen: 8K->10885K(348160K)] 11200K->10885K(500736K), [Metaspace: 3210K->3210K(1056768K)], 0.0060621 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
* Heap
*/
}
public void localvarGc2() {
byte[] buffer = new byte[10 * 1024 * 1024];
buffer = null;// 对象已经没被引用byte[]被回收
System.gc();
/**
* 回收 空余的堆new byte[10 * 1024 * 1024];
* [GC (System.gc()) [PSYoungGen: 15482K->840K(152576K)] 15482K->848K(500736K), 0.0009380 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
* [Full GC (System.gc()) [PSYoungGen: 840K->0K(152576K)] [ParOldGen: 8K->645K(348160K)] 848K->645K(500736K), [Metaspace: 3215K->3215K(1056768K)], 0.0043640 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
*/
}
public void localvarGc3() {
{
byte[] buffer = new byte[10 * 1024 * 1024];
}
System.gc();
/**
* - 新生代 10mb
* [GC (System.gc()) [PSYoungGen: 15482K->11112K(152576K)] 15482K->11120K(500736K), 0.0064283 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
* - 进入老年代
* [Full GC (System.gc()) [PSYoungGen: 11112K->0K(152576K)] [ParOldGen: 8K->10882K(348160K)] 11120K->10882K(500736K), [Metaspace: 3169K->3169K(1056768K)], 0.0041698 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]*/
}
public void localvarGc4() {
{
byte[] buffer = new byte[10 * 1024 * 1024];
}
int value = 10;
System.gc();
/**
* // 局部变量表长度是2第一个为this第二个为value替换了buffer所以被回收了
* [GC (System.gc()) [PSYoungGen: 15482K->904K(152576K)] 15482K->912K(500736K), 0.0006836 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
* [Full GC (System.gc()) [PSYoungGen: 904K->0K(152576K)] [ParOldGen: 8K->669K(348160K)] 912K->669K(500736K), [Metaspace: 3216K->3216K(1056768K)], 0.0043170 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
*/
}
public void localvarGc5() {
localvarGc1();
System.gc();
}
public static void main1(String[] args) {
TreeNode treeNode = new TreeNode(11);
SoftReference<TreeNode> treeNodeSoftReference = new SoftReference<>(treeNode);
treeNode = null; // 取消强引用
System.out.println(treeNodeSoftReference.get().val);
System.gc();//回收
System.out.println(treeNodeSoftReference.get().val); // 堆空间内存足够不会回收软引用
try {
byte[] bytes = new byte[1024 * 1024 * 7]; //导致资源紧张不够
} catch (Exception e) {
e.printStackTrace();
}finally {
System.out.println(treeNodeSoftReference.get()); // 在OOM之前GC软引用对象treeNodeSoftReference
}
}
public static void main(String[] args) {
// 创建一个TreeNode对象并创建其对应的PhantomReference和ReferenceQueue
TreeNode treeNode = new TreeNode(11);
ReferenceQueue<TreeNode> referenceQueue = new ReferenceQueue<>();
PhantomReference<TreeNode> treeNodePhantomReference = new PhantomReference<>(treeNode, referenceQueue);
// 取消对TreeNode对象的强引用
treeNode = null;
// 尝试输出虚引用的对象由于虚引用不能直接获取对象所以此行会报错或无输出
// System.out.println(treeNodePhantomReference.get().val); // 不允许直接访问
// 请求垃圾回收
System.gc();
// 虽然对象可能已经被回收但由于虚引用特性此处仍然不会被回收
// 需要检查ReferenceQueue来判断对象是否已被垃圾回收器处理
if (referenceQueue.poll() != null) {
System.out.println("TreeNode对象已被垃圾回收器回收但虚引用仍然存在");
} else {
System.out.println("TreeNode对象还未被垃圾回收器回收");
}
}
}

View File

@ -0,0 +1,64 @@
package cn.whaifree.radom;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/3/8 11:09
* @注释
*/
public class LeetCode28 {
@Test
public void test() {
int i = new Solution().strStr("aabaadaabaaf", "aabaaf");
System.out.println(i);
}
class Solution {
public int strStr(String haystack, String needle) {
int[] next = constructNext(needle);
int j = 0;
for (int i = 0; i < haystack.length(); i++) {
while (j > 0 && haystack.charAt(i) != needle.charAt(j)) {
j = next[j - 1];
}
if (haystack.charAt(i) == needle.charAt(j)) {
j++;
}
if (j == needle.length()) {
return i - j + 1;
}
}
return -1;
}
// 构造next数组
public int[] constructNext(String needle) {
int length = needle.length();
int[] next = new int[length];
int j = 0;// 前缀
for (int i = 1; i < length; i++) {
// 如果不匹配 往前跳
while (j > 0 && needle.charAt(i) != needle.charAt(j)) {
j = next[j - 1];
}
// 如果匹配 设置next[i]=j
if (needle.charAt(i) == needle.charAt(j)) {
j++;
}
next[i] = j;
}
return next;
}
}
}