java 递归和动态规划

Java下的迭代递归以及动态规划 迭代(iteration): 迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。 迭代是环结构,从初始状态开始,每次迭代都遍历这个环,并更新状态,多次迭代直到到达结束状态。 举个迭代的例子来说,计算n!就是前一个求和的结果作为这一次计算的初始值: private static int sum(i... 阅读详情

1、斐波那契系类问题的递归和动态规划

1.1 O(N)的解法

按照1,1,2,3,5.。。的顺序,依次求解即可。

package DynamicProgramming;

public class FibonacciSequenceV1 {

    public static int getN(int n){
        if(n<0)
            return 0;
        if(n==1 || n==2)
            return 1;
        int res = 1;
        int pre = 1;
        int temp = 0;
        for(int i =3 ;i<=n;i++){
            temp = res;
            res = pre + res;
            pre = temp;
        }
        return res;
    }

    public static void main(String[] args){
        System.out.println(getN(10));
    }
}

O(logN)的解法

主要用到了矩阵的思想,看下面的递推公式:

package DynamicProgramming;

public class FibonacciSequenceV2 {

    public static int[][] matrixPower(int[][] matrix,int p){
        int[][] res = new int[matrix.length][matrix[0].length];
        for(int i=0;i<matrix.length;i++){
            res[i][i] = 1;
        }
        int[][] temp = matrix;
        for(;p !=0; p >>= 1){
            if((p & 1) == 1){
                res = multiMatrix(res,temp);
            }
            temp = multiMatrix(temp,temp);
        }
        return res;
    }

    public static int[][] multiMatrix(int[][] m1,int[][] m2){
        int[][] res = new int[m1.length][m1[0].length];
        for(int i=0;i<m1[0].length;i++){
            for(int j=0;j<m1.length;j++){
                for(int k=0;k<m2.length;k++) {
                    res[i][j] += (m1[i][k] * m2[k][j]);
                }
            }
        }
        return res;
    }

    public static int getN(int n){
        if(n<1)
            return 0;
        if(n==1 || n==2)
            return 1;
        int[][] matrix = {{1,1},{1,0}};
        int[][] res = matrixPower(matrix,n-2);
        return res[0][0] + res[1][0];
    }

    public static void main(String[] args){
        System.out.println(getN(10));
    }

}

2、矩阵的最短路径和

使用动态规划的方法,建立dp数组,dp[i][j]代表从(0,0)位置到该处的最短路径。当然,我们可以使用空间压缩的方法,只用一维数组,保存每一行的结果,这样有效的降低的空间复杂度。

package DynamicProgramming;

public class minPathSum {

    public static int getMinPath(int[][] distance){
        int[] res = new int[distance[0].length];
        for(int i=0;i<distance.length;i++){
            for(int j=0;j<distance[0].length;j++){
                if(i==0 && j==0)
                    res[j] = distance[0][0];
                else if(i==0)
                    res[j] = distance[i][j] + res[j-1];
                else if(j==0)
                    res[j] = distance[i][j] + res[j];
                else
                    res[j] = Math.min(res[j],res[j-1]) + distance[i][j];
            }
        }
        return res[distance[0].length-1];
    }
    public static void main(String[] args){
        int[][] distance = {
                {1,3,5,9},
                {8,1,3,4},
                {5,0,6,1},
                {8,8,4,0}};
        System.out.println(getMinPath(distance));
    }
}

3、换钱最少的货币数

3.1 每种货币数量无限

在每种货币数量无限的情况下,使用动态规划的方法,从二维数组的角度出发,dp[i][j]代表使用arr[0,1..i]货币的情况下,组成j所需的最小张数。后面使用空间压缩的方法,可以将二维数组变为一维数组。

值得注意的地方是,我们首先给一维数组全部赋值了max,而不是使用默认值0,max表示无法组成目标货币,0表示的是最少用0张就可以组成目标货币,这显然是不合理的。

package DynamicProgramming;

public class minCoins {
    public static int getMinCoins(int[] arr,int aim){
        if(arr == null || arr.length == 0 || aim < 0)
            return -1;
        int[] res = new int[aim+1];
        int max = Integer.MAX_VALUE;
        for(int i=1;i<=aim;i++){
            res[i] = max;
        }
        int leftup;
        for(int i=0;i<arr.length;i++){
            for(int j=0;j<=aim;j++){
                if(i==0)
                    if(j>0 && j % arr[i] == 0)
                        res[j] = j / arr[i];
                else{
                    leftup = max;
                    if(j >= arr[i] && res[j-arr[i]] != max)
                        leftup = res[j-arr[i]] + 1;

                     res[j] = Math.min(leftup,res[j]);
                }
            }
        }
        return res[aim] != max?res[aim]:-1;
    }

    public static void main(String[] args){
        int[] arr = {5,2,3};
        int aim = 20;
        System.out.println(getMinCoins(arr,aim));
    }
}

3.2 每种货币只能使用1张

思路跟上面的题目是一样的,不过需要注意的一点是,由于每张货币只能使用一次,因此我们在内部遍历每一行时,需要从后往前遍历。因为如果从前往后遍历,会出现硬币被多次使用的情况。

package DynamicProgramming;

public class minCoinsV2 {
    public static int getMinCoins(int[] arr,int aim){
        if(arr == null || arr.length == 0 || aim < 0)
            return -1;
        int[] res = new int[aim+1];
        int max = Integer.MAX_VALUE;
        for(int i=1;i<=aim;i++){
            res[i] = max;
        }
        if(arr[0] <= aim)
            res[arr[0]] = 1;
        int leftup;
        for(int i=1;i<arr.length;i++){
            for(int j=aim;j>0;j--){
                leftup = max;
                if(j >= arr[i] && res[j-arr[i]] != max)
                    leftup = res[j-arr[i]] + 1;
                res[j] = Math.min(leftup,res[j]);
            }
        }
        return res[aim] != max?res[aim]:-1;
    }

    public static void main(String[] args){
        int[] arr = {5,2,3};
        int aim = 20;
        System.out.println(getMinCoins(arr,aim));
    }
}

4、换钱的方法数

这里要注意的一点是,组成0元的方法是1种,而不是0种。

package DynamicProgramming;

public class MaxChangeCoinsMethod {
    public static int getMaxCoinsMethod(int[] arr,int aim){
        if(arr == null || arr.length == 0 || aim < 0)
            return 0;
        int[] res = new int[aim+1];
        for(int j=0;j * arr[0] <= aim ;j++){
            res[j * arr[0]] = 1;
        }
        for(int i=1;i<arr.length;i++){
            for(int j=1;j<=aim;j++){
                if(j >= arr[I])
                    res[j] += (res[j-arr[i]]);
            }
        }
        return res[aim];
    }
    public static void main(String[] args){
        int[] arr = {5,10,25,1};
        int aim = 15;
        System.out.println(getMaxCoinsMethod(arr,aim));
    }
}

5、最长递增子序列

package DynamicProgramming;

public class LongestIncreaseList {

    public static int[] getLongestIncreaseList(int[] arr){
        int[] ends = new int[arr.length];
        ends[0] = arr[0];
        int[] dp = new int[arr.length]; //以index对应的数结尾的时候,最大递增子序列的长度
        int right = 0;
        int l = 0;
        int r = 0;
        int m = 0;
        for(int i=1;i<arr.length;i++){
            l = 0;
            r = right;
            while(l<=r){
                m = (r-l) / 2 + l;
                if(ends[m]<=arr[I])
                    l = m + 1;
                else
                    r = m - 1;
            }
            right = Math.max(l,right);
            ends[l] = arr[I];
            dp[i] = l + 1;
        }

        return dp;
    }

    public static int[] generateLIS(int[] arr,int[] dp){
        int len = 0;
        int index = 0;
        for(int i=0;i<dp.length;i++){
            if(dp[i] > len){
                len = dp[i];
                index = I;
            }
        }
        int[] lis = new int[len];
        lis[--len] = arr[index];
        for(int i=index;i>=0;i--){
            if(arr[i] < arr[index] && dp[i] == dp[index] - 1){
                lis[--len] = arr[i];
                index = I;
            }
        }
        return lis;
    }

    public static void main(String[] args){
        int[] arr = {2,1,5,3,6,4,8,9,7};
        int[] dp = getLongestIncreaseList(arr);
        int[] res = generateLIS(arr,dp);
        for(int i=0;i<res.length;i++)
            System.out.println(res[I]);
    }
}

6、最长公共子序列问题

package DynamicProgramming;

public class LongestCommonSubStr {

    public static int[][] findLongestSubStrDP(String str1,String str2){
        char[] char1 = str1.toCharArray();
        char[] char2 = str2.toCharArray();
        int[][] dp = new int[char1.length][char2.length];
        for(int i=0;i<char1.length;i++){
            for(int j=0;j<char2.length;j++){
                if(i==0){
                    dp[i][j] = (char2[j] == char1[i] ? 1:0);
                }
                else if(j==0){
                    dp[i][j] = (char2[j] == char1[i] ? 1:0);
                }
                else{
                    dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
                    if(char1[i] == char2[j])
                        dp[i][j] = Math.max(dp[i][j],dp[i-1][j-1] + 1);
                }
            }
        }
        return dp;
    }

    public static String lcse(String str1,String str2,int[][] dp){
        char[] char1 = str1.toCharArray();
        char[] char2 = str2.toCharArray();
        int m = char1.length-1;
        int n = char2.length-1;
        char[] res = new char[dp[m][n]];
        int index = res.length-1;
        while(index >= 0){
            if(n>0 && dp[m][n] == dp[m][n-1])
                n--;
            else if(m>0 && dp[m-1][n] == dp[m][n])
                m--;
            else{
                res[index--] = char1[m];
                m--;
                n--;
            }
        }
        return String.valueOf(res);
    }

    public static void main(String[] args){
        String str1 = "1A2C3D4B56";
        String str2 = "B1D23CA45B6A";

        int[][] dp = findLongestSubStrDP(str1,str2);
        String res = lcse(str1,str2,dp);
        System.out.println(res);
    }
}

7、最长公共子串

子串和子序列是不一样的, 子串必须是连续的,而子序列可以是不连续的。按照经典的动态规划方法,我们得到如下思路:

但题目中要求的空间复杂度是O(1),因此我们按照如下的思路,得到了正确的解决方法:

package DynamicProgramming;

public class LongestCommonSubString {

    public static String getLongestCommonSubString(String str1,String str2){
        if(str1==null || str2==null || str1.equals("") || str2.equals("")){
            return "";
        }
        char[] char1 = str1.toCharArray();
        char[] char2 = str2.toCharArray();

        int row = 0;
        int col = char2.length-1;
        int max = 0;
        int end = 0;
        while(row < char1.length){
            int i = row;
            int j = col;
            int len = 0;
            while(i<char1.length && j<char2.length){
                if(char1[i] == char2[j]){
                    len++;
                }
                else{
                    len = 0;
                }
                if(len > max){
                    max = len;
                    end = I;
                }
                I++;
                j++;
            }
            if(col > 0){
                col--;
            }
            else{
                row++;
            }
        }
        return str1.substring(end - max + 1,end + 1);
    }

    public static void main(String[] args){
        String str1 = "1AB2345CD";
        String str2 = "12345EF";
        System.out.println(getLongestCommonSubString(str1,str2));
    }
}

8、最小编辑代价

这里为什么会增加一列和一行,因为字符串是可以删除为空串,然后再通过插入操作来进行变换的,如果没有空串,会得到错误的答案。

package DynamicProgramming;

public class MinEditCost {

    public static int getMinEditCost(String str1,String str2,int ic,int dc,int rc){
        if(str1==null || str2==null)
            return 0;
        char[] char1 = str1.toCharArray();
        char[] char2 = str2.toCharArray();

        int[] dp = new int[char2.length+1];
        for(int j=0;j<char2.length+1;j++){
            dp[j] = j * ic;
        }
        for(int i=1;i<char1.length+1;i++){
            int pre = dp[0];
            dp[0] = dc * I;
            for(int j=1;j<char2.length+1;j++){
                int tmp = dp[j];
                if(char1[i-1] == char2[j-1]){
                    dp[j] = pre;
                }
                else{
                    dp[j] = pre + rc;
                }
                dp[j] = Math.min(dp[j],dp[j-1] + ic);
                dp[j] = Math.min(dp[j],tmp + dc);
                pre = tmp;
            }
        }
        return dp[char2.length];
    }

    public static void main(String[] args){
        String str1 = "abc";
        String str2 = "adc";
        int ic = 5;
        int dc = 3;
        int rc = 2;

        if(str1.length() >= str2.length())
            System.out.println(getMinEditCost(str1,str2,ic,dc,rc));
        else
            System.out.println(getMinEditCost(str2,str1,ic,dc,rc));
    }
}

9、龙与地下城游戏问题

与前面的题目不同的地方是,我们这里采用从右下角往左上角遍历的顺序。但是动态规划的思想都是一样的。

package DynamicProgramming;

public class MinHP {

    public static int getMinHP(int[][] arr){
        if(arr==null || arr.length==0 || arr[0].length==0)
            return 0;
        int[] dp = new int[arr[0].length];
        for(int i=arr.length-1;i>=0;i--){
            for(int j=arr[0].length-1;j>=0;j--){
                if(i == arr.length-1 && j==arr[0].length-1)
                    dp[j] = arr[i][j] > 0 ? 1:1-arr[i][j];
                else if(i==arr.length-1)
                    dp[j] = arr[i][j] > 0 ? dp[j+1]:dp[j+1] - arr[i][j];
                else if(j==arr[0].length-1)
                    dp[j] = arr[i][j] > 0 ? dp[j]:dp[j] - arr[i][j];
                else
                    dp[j] = arr[i][j] > 0 ? Math.min(dp[j],dp[j+1]) : Math.min(dp[j],dp[j+1]) - arr[i][j];
            }
        }
        return dp[0];
    }

    public static void main(String[] args){
        int[][] arr = {
                {-2,-3,3},
                {-5,-10,1},
                {0,30,-5}};
        System.out.println(getMinHP(arr));
    }
}

10、表达式得到期望结果的组成种数

首先判断express是否合理:

随后使用动态规划的方法:

package DynamicProgramming;

public class DesiredExpressionNum {
    public static boolean isValid(char[] exp){
        if((exp.length & 1) == 0)
            return false;
        for(int i=0;i<exp.length;i+=2){
            if((exp[i] != '1') && (exp[i] != '0')){
                return false;
            }
        }
        for(int i=1;i<exp.length;i+=2){
            if((exp[i] != '&') && (exp[i] != '|') && (exp[i]) != '^'){
                return false;
            }
        }
        return true;
    }

    public static int getDesiredExpressionNum(String express,boolean desired){
        if(express == null || express.equals(""))
            return 0;
        char[] exp = express.toCharArray();
        if(!isValid(exp))
            return 0;
        int[][] t = new int[exp.length][exp.length];//t[j][i] 表示express[j][i] 组成true的个数
        int[][] f = new int[exp.length][exp.length];//f[j][i] 表示express[j][i] 组成false的个数
        t[0][0] = exp[0] == '0' ? 0:1;
        f[0][0] = exp[0] == '1' ? 0:1;
        for(int i=2;i<exp.length;i+=2){
            t[i][i] = exp[i] == '0'?0:1;
            f[i][i] = exp[i] == '1'?0:1;
            for(int j = i-2;j>=0;j-=2){
                for(int k = j;k<i;k+=2){
                    if(exp[k+1] == '&'){
                        t[j][i] += t[j][k] * t[k+2][I];
                        f[j][i] += (f[j][k] + t[j][k]) * f[k+2][i] + f[j][k] * t[k+2][I];
                    }
                    else if(exp[k+1] == '|'){
                        t[j][i] += t[j][k] * f[k+2][i] + t[j][k] * t[k+2][i] + f[j][k] * t[k+2][I];
                        f[j][i] += f[j][k] * f[k+2][I];
                    }
                    else{
                        t[j][i] += f[j][k] * t[k+2][i] + t[j][k] * f[k+2][I];
                        f[j][i] += t[j][k] * t[k+2][i] + f[j][k] * f[k+2][I];
                    }
                }
            }
        }
        return desired?t[0][exp.length-1]:f[0][exp.length-1];
    }

    public static void main(String[] args){
        String express = "1^0|0|1";
        Boolean desired = false;
        System.out.println(getDesiredExpressionNum(express,desired));
    }
}

11、排成一条线的纸牌博弈游戏

package DynamicProgramming;

public class CardGameScore {

    public static int getWinnerScore(int[] arr){
        if(arr==null || arr.length==0)
            return 0;
        int[][] f = new int[arr.length][arr.length];
        int[][] s = new int[arr.length][arr.length];
        for(int j = 0;j<arr.length;j++){
            f[j][j] = arr[j];
            for(int i = j-1;i>=0;i--){
                f[i][j] = Math.max(s[i+1][j] + arr[i],s[i][j-1] + arr[j]);
                s[i][j] = Math.min(f[i+1][j],f[i][j-1]); //对手也是聪明决定的,我们能够得到的是min的结果,取决于对方拿牌的情况。
            }
        }
        return Math.max(f[0][arr.length-1],s[0][arr.length-1]);
    }

    public static void main(String[] args){
        int[] arr = {1,2,100,4};
        System.out.println(getWinnerScore(arr));
    }
}

12、跳跃问题

package DynamicProgramming;

public class JumpGame {
    public static int getMinJumpTimes(int[] arr){
        if(arr==null || arr.length==0)
            return 0;
        int times=0,cur=0,next=0;
        for(int i=0;i<arr.length;i++){
            if(cur < i){
                times ++;
                cur = next;
            }
            next = Math.max(next,i + arr[I]);
        }
        return times;
    }

    public static void main(String[] args){
        int[] arr = {3,2,3,1,1,4};
        System.out.println(getMinJumpTimes(arr));
    }
}

13、N皇后问题

著名的N皇后问题,我们给出一种基于递归的方法。这里我们用了一个小trick,即用一个一维数组保存每一行皇后的问题,这样,我们就可以只判断列活着斜线上是否已经放置了皇后即可。

package DynamicProgramming;

public class NQueenV1 {
    public static boolean isValid(int row,int col,int[] record){
        for(int i=0;i<row;i++){
            if(record[i] == col || Math.abs(row-i) == Math.abs(record[i] - col))
                return false;
        }
        return true;
    }

    public static int totalMethod(int index,int n,int[] record){
        if(index == n){
            return 1;
        }
        int res = 0;

        for(int j =0;j<n;j++){
            if(isValid(index,j,record)){
                record[index] = j;
                res += totalMethod(index + 1,n,record);
            }
        }
        return res;
    }

    public static void main(String[] args){
        int n = 8;
        int[] record = new int[n];
        System.out.println(totalMethod(0,n,record));

    }
}

 

动态规划的适用条件

任何思想方法都有一定的局限性,超出了特定条件,它就失去了作用。同样,动态规划也并不是万能的。适用动态规划的问题必须满足最优化原理和无后效性。

1.最优化原理(最优子结构性质)

最优化原理可这样阐述:一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。简而言之,一个最优化策略的子策略总是最优的。一个问题满足最优化原理又称其具有最优子结构性质。

 

2.无后向性

将各阶段按照一定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它未来的决策,而只能通过当前的这个状态。换句话说,每个状态都是过去历史的一个完整总结。这就是无后向性,又称为无后效性。

 

3.子问题的重叠性

动态规划将原来具有指数级复杂度的搜索算法改进成了具有多项式时间的算法。其中的关键在于解决冗余,这是动态规划算法的根本目的。

动态规划实质上是一种以空间换时间的技术,它在实现的过程中,不得不存储产生过程中的各种状态,所以它的空间复杂度要大于其它的算法。

以Bitonic旅行路线问题为例,这个问题也可以用搜索算法来解决。动态规划的时间复杂度为O(n2),搜索算法的时间复杂度为O(n!) ,但从空间复杂度来看,动态规划算法为O(n2),而搜索算法为O(n),搜索算法反而优于动态规划算法。选择动态规划算法是因为动态规划算法在空间上可以承受,而搜索算法在时间上却无法承受,所以我们舍空间而取时间。

设原问题的规模为n,容易看出,当子问题树中的子问题总数是n的超多项式函数,而不同的子问题数只是n的多项式函数时,动态规划法显得特别有意义,此时动态规划法具有线性时间复杂性。所以,能够用动态规划解决的问题还有一个显著特征:子问题的重叠性。这个性质并不是动态规划适用的必要条件,但是如果该性质无法满足,动态规划算法同其他算法相比就不具备优势。

 

JAVA算法:切割木棒—递归算法与动态规划算法 JAVA算法:切割木棒—递归算法与动态规划算法 给定一根长度为N的木棒和一系列价格,其中包含所有小于N的尺寸的价格。通过切割木棒和出售木棒来确定可获得的最大值。 例如,如果木棒的长度为8,不同部分的值如下所示,则可获得的最大值为22(通过切割两段长度2和6) 长度 1 2 3 4 5 6 7 8 价值 1 5 8 9... 阅读详情

相关推荐

动态规划解决旅行商问题(TSP)的递归实现(Java)

动态规划(Dynamic Programming)是一种解决优化问题的常用方法,而旅行商问题(Traveling Salesman Problem,TSP)则是其中一种经典的优化问题。在本篇文章中,我们将探讨如何使用递归的方式实现动态规划解决TSP问题的算法,并给出相应的Java源代码。动态规划(Dynamic Programming)是一种解决优化问题的常用方法,而旅行商问题(Traveling Salesman Problem,TSP)则是其中一种经典的优化问题。

DevNinja的博客 617

Java中的递归算法优化:如何通过尾递归与动态规划提升性能

尾递归优化减少了递归调用的栈空间消耗,而动态规划通过保存中间结果避免了重复计算。方法通过将递归调用的结果作为参数传递,从而减少了递归调用的栈深度,实现了尾递归优化。虽然Java并不直接支持尾递归优化,但良好的尾递归编程习惯可以帮助实现更高效的递归调用。尾递归是指在递归函数的最后一步是递归调用自身,这样编译器可以优化递归调用,减少栈帧的消耗。通过尾递归优化,可以避免递归调用时栈空间的消耗,提高程序的性能。我们可以结合尾递归与动态规划的优势,优化一个实际应用场景中的递归算法。

微赚淘客系统开发者博客 926

用递归求1+2+3+...+n的程序

用递归求1+2+3+...+n的算法。初学者使用。

java---递归的理解到由递归引入动态规划

1.理解递归 1. 理解递归 2 Fibonacci 递归写法 3. 由暴力递归到动态规划 递归的过程很复杂,而且递归也很重要,它能够解决我们遇到的很多问题。所以理解递归很重要。 再一个就是在学习算法的时候我们会遇见动态规划,直接解决动态规划对于大多数人来说都不太现实,而从暴力递归到动态规划就相对变得简单一点了。 1.递归的理解 ...

qq_63763951的博客 917

STM32F103 CAN通信避坑指南:从标准库配置到收发测试的完整流程

本文详细介绍了STM32F103 CAN通信的实现流程,从标准库配置到收发测试,帮助开发者避开常见陷阱。内容涵盖硬件连接、波特率计算、过滤器配置及错误处理等关键环节,提供实用的代码示例和调试技巧,确保CAN通信的稳定性和可靠性。

weixin_30627341的博客 324

SECS/GEM协议库及开源代码

以下是在开发SECS/GEM协议过程中,在网络上搜集协议实现资源,希望对SECS/GEM协议感兴趣的同学能有所帮助。 开源代码 freesecs FREESECS 是一个开源的SEMI SECS协议库,采用C++语言实现,可运行于Linux, MacOS X, NetBSD。 实现协议:E37.1、E5 开源地址:freesecs download | SourceForge.net 下载地址:https://download.youkuaiyun.com/download/BT_LEO/24305429

码农的历程 9940

java数据结构与算法6---递归&动态规划

java数据结构与算法6---递归&amp;动态规划 介绍递归&amp;动态规划的形成步骤 暴力递归: 把问题转化为规模缩小的同类问题的子问题 有明确不需要继续递归的条件 有当得到子问题结果的决策过程 不记录每一个子问题的解 动态规划(暴力递归的优化|贪心算法): 从暴力递归中来 将每一个子问题的解记录下来,避免重复计算 把暴力递归的过程抽象为状态表达 存在化简状态表达...

知飞翀的博客 370

RAGFlow 离线部署:解决cl100k_base.tiktoken问题

摘要 本文详细解决了RAGFlow离线部署时tiktoken缓存文件下载失败的问题。通过分析tiktoken库的缓存机制,一次性不改代码解决.

baidu_25691461的博客 830

动态规划算法及其经典问题求解(Java)

与之相反,动态规划应用于子问题重叠的情况,即不同的子问题具有公共的子子问题。对于每个数,都有选和不选两种状态,如果选了这个数,那么就不能选他相邻的那个数,那么最大和就等于本身加上他相邻的那位数之前那些数的最大和,如果不选这个数,那么便可以选它相邻的那个数,那么最大和就等于这个数之前的那些数的最大和。将整个问题划分成一个个子问题,也就是说要求整个数列的最大和,可以先求出前面若干个数的和,一直划分到求出只有一个数的最大和(即本身),而每个子问题的解对于后面的结果都是有用的,这就是用到了动态规划的思想。

博客简介 6557

S7-1200PLC 与温控仪表Modbus RTU通信

硬件:cpu 1214C 目的:通过Modbus RTU协议,实现对温控仪表的控制 软件:Portal V14SP1

weixin_43922025的博客 3万+

有限元中的对称魔法:用1/6模型算整个涡轮叶片(含MATLAB代码)

本文深入解析了有限元分析中针对循环对称结构的高效求解策略。通过利用涡轮叶片等结构的几何重复性,仅需对1/6基本扇区建模并施加循环对称条件,即可精确推演整体力学行为,大幅降低计算规模。文章从数学原理推导到MATLAB代码实现,提供了完整的实战指南,适用于旋转机械的静力、模态及谐响应分析。

fire9的博客 310

递归与动态规划关系

递归与动态规划关系        其实递归与动态规划有紧密的关系,且一般递归都可以转化为动态规划。这个问题从一般的递归构成就能够解释清楚, 首先,问题可以分解,拆成很多重叠子问题才可以求解,而动态规划也是这一思路,说白了动态规划其实就是记忆化了的 递归程序。动态规划把很多递归问题的解存储下来,这样就省去了求许多子问题的解,从而达到了快速求解的目的。        递归其实就是自上往下求解,

mejustdoit的专栏 5214

YOLOv8目标出入计数部署:讲解C#使用ONNX检测模型进行目标出入计数 可运行完整实例

代码、步骤、讲解完整,可一键运行,效果如下:车辆出入计数人员出入计数。

Limiiiing的博客 79

java 递归回溯_java——递归(动态规划,回溯)

最近刷面试题经常刷到递归方面的算法,一直以为都是递归,后来发现竟然都有具体的叫法,所以写了这篇博客来牢记以下1. 五大常用算法(1) 分治算法把一个复杂的问题分成两个或多个相同或者相似的子问题,然后不断地细分,直到最后的子问题可以很简单地求解出来,原问题的解就是自问题的合并。比如常见的快速排序算法和归并算法分治法的核心思想就是把大的难解的问题不断分割,分而治之。(2) 动态规划类似于分治法,将带求...

weixin_39651735的博客 412

Java开源海外跨境电商购物商城源码,TikToK商城系统源码,外贸商城在线交易

最近很火的一款商城源码,朋友分享给我的,完整版,java开源代码,带有非常详细的搭建教程,文件都一个多G,喜欢的可以下载来研究研究!3、创建mall 数据库并导入数据,数据库名用户名为:mall 数据库密码保持为:XXKytcACPX3GbdsH。8、进入cd /data/deploy/mall-tool/目录执行./build.sh脚本。7、宝塔ssh进入cd /data/deploy/mall/ 执行./build.sh脚本。2、安装宝塔环境:安装 Redis、MySQL5.7、Ngin1.2。

百创科技 2821

【单片机】STM32F103C8T6 最小系统板原理图

STM32F103C8T6是一款基于ARM Cortex-M3内核的32位微控制器,由STMicroelectronics(ST)公司生产。它是STMicroelectronics的STM32系列微控制器中的一员,被广泛应用于嵌入式系统和电子设备中。LQFP48封装(Low-profile Quad Flat Package,48引脚)SRAM(静态随机访问存储器):20 KB。支持JTAG调试和编程接口(可选)多个通用输入/输出口(GPIO)USB接口(用于USB设备模式)内置调试和编程接口(SWD)

q742971636的博客 6万+

Fibonacci数列--动态规划与递归的Java实现

Fibonacci数列–动态规划与递归的Java实现 递归与动态规划 相似点:递归和动态规划都要求给出 递推公式 ,将大问题划分为相似子问题求解。而动态规划比递归好处是:保存中间计算结果(子问题的解),去除重复计算! 递归的特点: (1) 外层往往需要内层计算结果:发现父问题与子问题的关系,具体问题具体实现 (2) 必须有一个明确的递归结束条件,称为递归出口! 递归实现 public class ...

颜的博客 1056

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Java解决 合唱团问题 (动态规划、递归)

/* 求最优解问题——递归/动态规划 从n个学生中找出k个————————从n个学生中找到最后一个,然后从剩下的里面找出k-1个 */ import java.util.Scanner; public class Main { public static void main(String[] args){ Scanner sc = new Scanne...

Zhengxinyu666的博客 789

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

JAVA算法动态规划与递归论文_死磕递归和动态规划算法

正文最近在忙着找实习,因而做了大量的笔试算法题,阿里,网易,腾讯,华为,发现各大厂商都喜欢出递归和动态规划题,而且出的特别多,这种题以前一直没有搞懂,总是半懂状态,现在感觉有必要好好整理一下。1.斐波那契数列谈到递归问题,我们不妨先从斐波那契数列开始,这个大家应该都不陌生吧,1,1,2,3,5,8......除了第一项和第二项为1外,对于第N项,有F(N) = F(N - 1) + F(N - ...

weixin_29343657的博客 282

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

java 动态规划,递归实现 找零问题,币值最大化

java 动态规划,递归实现 找零问题,币值最大化 package package1; import java.util.Random; class Coin { int monly; int num; public Coin(int monly, int num) { this.monly = monly; this.num = num; } } public class alg { public static int ma

TianXiaobie的博客 1579

递归与动态规划:Java算法优化的奥秘

递归和动态规划是Java中两种重要的算法设计方法。在实际应用中,应根据具体场景选择合适的算法。递归算法简洁直观,但需要注意性能问题;动态规划可以显著提高性能,但代码复杂度较高。随着技术的不断发展,递归和动态规划在Java中的应用将会越来越广泛。未来,我们将看到更多基于这两种算法的创新应用。

南客先生的博客 730

【Java算法入门】爬楼梯问题详解,递归→动态规划的完美进阶!✨

摘要 爬楼梯问题是经典的算法入门案例,要求计算n阶楼梯每次爬1或2阶的不同方法数。其本质是斐波那契数列问题,解法从递归逐步优化到动态规划:1)朴素递归直接模拟但效率低;2)记忆化递归通过缓存避免重复计算;3)动态规划自底向上构建解;4)优化版仅用常数空间。该问题帮助初学者理解递归与动态规划的关系、重叠子问题优化等核心算法思想,是学习算法设计的重要阶梯。

红目香薰 1034

矩阵连乘的JAVA实现(动态规划,递归)

递归,动态规划两种方法实现 1.递归实现: public class MatrixChainDiGui { static int p[] = { 30, 35, 15, 5, 10, 20, 25 }; public static void main(String[] args) { System.out.println(getMatrixChain(1,6)); }

fool宋的专栏 5902

Java:以递归的形式实现动态规划的TSP问题算法(附带源码)

Java:以递归的形式实现动态规划的TSP问题算法(附带源码)

欢迎来到我的博客!这里是一个专注于计算机技术的分享平台,涵盖编程开发、算法研究、系统架构、软件工程等多个领域。无论你是初学者还是资深开发者,都能在这里找到有价值的内容。 1295

矩阵连乘动态规划Java_矩阵连乘的JAVA实现(动态规划,递归) | 学步园

递归,动态规划两种方法实现1.递归实现:public class MatrixChainDiGui {static int p[] = { 30, 35, 15, 5, 10, 20, 25 };public static void main(String[] args) {System.out.println(getMatrixChain(1,6));}public static int get...

weixin_42507868的博客 512

java 递归 正则_【算法】正则匹配:java - 递归算法 - 动态规划

1、题目给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。'.' 匹配任意单个字符'*' 匹配零个或多个前面的那一个元素所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。说明:s 可能为空,且只包含从 a-z 的小写字母。p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。示例1:输入:s = "aa"p = "a"输出: f...

weixin_28692867的博客 304
上一篇: 【机器学习】条件随机场CRF算法 梳理
下一篇: 【机器学习】EM 期望最大化算法 整理
CWS_chen
博客等级 码龄11年 220粉丝 51原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值