一种递归转动态规划的方法

一种递归转动态规划的方法

FROM左神的视频。
参考的博客

递归

递归解题的思路:

  1. 大问题可以分解成小问题,小问题的解可以合成为大问题的解
  2. 必须有明确的退出条件(base case【左神的base case】)
  3. 通解的返回值应该如何考虑,这往往是比较复杂的。

递归1:二叉搜索树转双向链表

思路:根据二叉树的递归中序遍历的框架写的代码。

package com.tom.offer;

import java.util.Objects;
import java.util.Stack;

public class Ch27_ConvertBinarySearchTree {
    
    
    public static void main(String[] args) {
    
    
        TreeNode treeNode = TreeNode.buildTree(5);
        TreeNode.levelPrintTreeNode(treeNode);
        System.out.println();

        inOrder(treeNode);
        System.out.println();

        TreeNode treeNode1 = convertBinarySearchTree(new Stack<>(), treeNode);
        while(Objects.nonNull(treeNode1)){
    
    
            System.out.print(treeNode1.value + " ");
            treeNode1 = treeNode1.right;
        }
        System.out.println();
    }


    public static void inOrder(TreeNode treeNode) {
    
    
        if(Objects.isNull(treeNode)){
    
    
            return;
        }
        inOrder(treeNode.left);
        System.out.print(treeNode.value + " ");
        inOrder(treeNode.right);
    }

    public static TreeNode convertBinarySearchTree(Stack<TreeNode> stack, TreeNode treeNode) {
    
    
        TreeNode head = null;
        if(Objects.nonNull(treeNode.left)) {
    
    
        	//只要左子树的,因head一定是左子树中最左的节点
            head = convertBinarySearchTree(stack,treeNode.left);
        }
        if(stack.isEmpty()){
    
    
        	//找到head,记录
            head = treeNode;
            stack.push(treeNode);
        }else {
    
    
        	//通常情况下,双向链表的基本操作
            TreeNode pop = stack.pop();
            stack.push(treeNode);
            pop.right = treeNode;
            treeNode.left = pop;
        }

        if(Objects.nonNull(treeNode.right)) {
    
    
        	//右子树
            convertBinarySearchTree(stack,treeNode.right);
        }
        return head;
    }
}

递归2:字符串的所有的字串

#include <functional>
#include <string>
#include <iostream>
using namespace std;
void printAllSub(string str, int i, string res){
    
    
    if (i == str.length()){
    
    
        cout << res << endl;
        return;
    }
    //要与不要,超想要哈哈哈
    printAllSub(str, i+1, res);
    printAllSub(str, i+1, res + str.at(i));
}

int main(int argv, char** argc){
    
    
    string test = "abc";
    printAllSub(test, 0, "");
}

递归3:矩阵的最小路径

有一个矩阵map,它每个格子有一个权值。从左上角的格子开始每次只能向右或者向下走,最后到达右下角的位置,路径上所有的数字累加起来就是路径和,返回所有的路径中最小的路径和。
测试样例:[[1, 2, 3], [1, 1, 1]]
返回:4

思路:假如你已经到达矩阵中的某一个格子,那么当前格子最小的路径和是怎么来的呢?

在这里插入图片描述

从图中可以看出,肯定是从当前格子的左边,或者上边走过来的。因此当前格子最小的路径和是min(左边,上边) + 当前格子的权值

int process1(vector<vector<int>> matrix, int i, int j){
    
      // i, j表示行数和列数
    if(i == 0 && j == 0){
    
    
        return matrix[i][j];
    }
    if(i != 0 && j == 0){
    
    
        //第一列
        return process1(matrix, i - 1, j) + matrix[i][j];
    }
    if(i == 0 && j !=0){
    
    
    	//第一行
        return process1(matrix, i, j - 1) + matrix[i][j];
    }
    //通常情况
    return matrix[i][j]+ min(process1(matrix, i, j - 1), process1(matrix, i - 1, j)); 
}

int minPath1(vector<vector<int>> matrix){
    
    
    return process1(matrix, matrix.size()-1, matrix[0].size()-1);
}

动态规划

动态1: 矩阵的最小路径

思路:写好递归代码,根据base case写已知
1.

	if(i == 0 && j == 0){
    
    
        return matrix[i][j];
    }

在这里插入图片描述
2.

    if(i == 0 && j !=0){
    
    
    	//第一行
        return process1(matrix, i, j - 1) + matrix[i][j];
    }

在这里插入图片描述
3.

    if(i != 0 && j == 0){
    
    
        //第一列
        return process1(matrix, i - 1, j) + matrix[i][j];
    }

在这里插入图片描述
4. 在这里插入图片描述

完整代码

int minPath2(vector<vector<int>> matrix){
    
    
    if(matrix.size() == 0 || matrix[0].size() == 0){
    
    
        return 0;
    }
    int row = matrix.size();
    int col = matrix[0].size();
    vector<vector<int>> dp(row, vector<int>(col));  //二维vector初始化的方式
    dp[0][0] = matrix[0][0];
    for(int i = 1;i < row; i++){
    
    
        dp[i][0] = dp[i-1][0] + matrix[i][0];
    }
    for(int j = 1;j < col; j++){
    
    
        dp[0][j] = dp[0][j-1] + matrix[0][j];
    }
    for(int i = 1;i < row; i++){
    
    
        for(int j = 1;j < col; j++){
    
    
            dp[i][j] = matrix[i][j] + min(dp[i-1][j], dp[i][j-1]);
        }
    }
    return dp[row - 1][col - 1];
}

动态2: 打印矩阵的最小路径

如果要打印路径的话,还是要用动态规划吧。

package com.tom.offer;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

public class Ch49_StrToInt {
    
    
    public static void main(String[] args) {
    
    
        int[][] matrix = new int[][]{
    
     {
    
    1,7,9,2},
                {
    
    8,6,3,2},
                {
    
    1,6,7,8},
                {
    
    2,9,8,2}};

        List list = minPath2(matrix);
        list.forEach(System.out::println);
    }

    public static List minPath2(int[][] matrix){
    
    
        if(matrix.length == 0 || matrix[0].length == 0){
    
    
            return Collections.emptyList();
        }
        int row = matrix.length;
        int col = matrix[0].length;
        int[][] dp = new int[row][col];

        dp[0][0] = matrix[0][0];

        for(int i = 1;i < row; i++){
    
    
            dp[i][0] = dp[i-1][0] + matrix[i][0];
        }

        for(int j = 1;j < col; j++){
    
    
            dp[0][j] = dp[0][j-1] + matrix[0][j];
        }

        for(int i = 1;i < row; i++){
    
    
            for(int j = 1;j < col; j++){
    
    
                dp[i][j] = matrix[i][j] + Math.min(dp[i-1][j], dp[i][j-1]);
            }
        }

        //倒推路径
        int i = row - 1, j = col - 1;
        List<Integer> list = new ArrayList<>();
        while(i != 0 || j != 0){
    
    
            list.add(matrix[i][j]);
            if(j == 0 || (i > 0 && dp[i - 1][j] + matrix[i][j] == dp[i][j])){
    
    
                --i;
            }else if(i == 0 || (j > 0 && dp[i][j - 1] + matrix[i][j] == dp[i][j])){
    
    
                --j;
            }
        }
        list.add(matrix[0][0]);
        Collections.reverse(list);
        return list;
    }
}

猜你喜欢

转载自blog.csdn.net/xiaolixi199311/article/details/112130439