【数据结构】递归、分治、回溯、动态规划

递归

爬楼梯

https://leetcode.com/problems/climbing-stairs/

package codingTest2;


//1.假设当有n个台阶时假设有f(n)种走法。
//2.最后一步要么跨1个台阶要么跨2个台阶。
//3.当最后一步跨1个台阶时即之前有n-1个台阶,根据1的假设即n-1个台阶有f(n-1)种走法。
//4. 当最后一步跨2个台阶时即之前有n-2个台阶,根据1的假设即n-2个台阶有f(n-2 )种走法。
//5.显然n个台阶的走法等于前两种情况的走法之和即f(n)=f(n-1)+f(n-2)。
//6.找出递推公式后要找公式出口,即当n为1、2时的情况,显然n=1时f(1)等于1,f(2)等于2
//7.        | 1, (n=1)
//f(n) =    |2, (n=2)
//          | f(n-1)+f(n-2) ,(n>2,n为整数)


public class ClimbStairs {
	//递归版
	public static int ClimbStairs(int n) {
		if(n == 1) {
			return 1;
		}if(n == 2) {
			return 2;
		}else {
			return ClimbStairs(n-1) + ClimbStairs(n-2);
		}
	}
	
	//循环版本
//	public static int ClimbStairs(int n) {
//		if(n == 1) {
//			return 1;
//		}
//		if(n == 2) {
//			return 2;
//		}
//		
//		int first = 1;
//		int second = 2;
//		int third = 0;
//		for(int i = 3; i <=n; i++) {
//			third = first + second;
//			first = second;
//			second = third;
//		}
//		return third;
//	}
	

	
	public static void main(String[] args) {
		System.out.println(ClimbStairs(1));
		System.out.println("------------");
		System.out.println(ClimbStairs(2));
		System.out.println(ClimbStairs(3));
		System.out.println(ClimbStairs(4));
	}
}

买卖股票的最佳时期

https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/comments/ 

class Solution {
    public int maxProfit(int[] prices) {
        int low=0;
        int high=1;
        int result=0;
        while(low<high&&high<prices.length)
        {
               while(high<prices.length)
            {
               if(prices[high]-prices[low]>result) 
               {
                   result=prices[high]-prices[low];
               }
                  high++; 
            } 
            low++;
            high=low+1;
            
        }
        return result;
    }
}

Minimum Path Sum(最小路径和)

题目链接:

https://leetcode-cn.com/problems/minimum-path-sum/comments/

方法一:递归

        假设当前出发位置就是最右下角的位置,那么经过的最短路径就是最右下角的格子的值;

        假设在最后一行格子中,即grid[grid.length-1][j] ,那么从这个点出发到最右下角的最小路径就只能往右走;

        假设在最后一列格子中,即grid[i][grid.length-1],那么从这个点出发到最右下角的最小路径和就只能往下走;

        假设就在普通的一个位置,既可以往下走又可以往右走:

        如果选择往右走,最短路径:往右走的最短路径和         +         我现在自身的值;

        如果选择往下走,最短路径:往下走的最短路径和         +         我现在自身的值。

       因此,从该点出发到右下角的最小路径值:从以上往左、往下两个中选出最小值  + 我现在自身的值。

package codingTest7;

public class minPath {
	/*
	 * 一个二维数组,里面都是正数,要求从左上到右下,每一步只能向右或者向下。
	 * 沿途经过的数字要累加起来。返回最小路径和。
	 * 
	 * */
	public static int walk(int[][] matrix ,int i, int j) {
		if(i == matrix.length-1 && j == matrix[0].length-1) {
			//如果当前已经到达最右下角的点
			return matrix[i][j];//直接返回当前点的值
		}
		
		if(i == matrix.length - 1) {
			return matrix[i][j] + walk(matrix, i, j+1);//到这行的最后一个位置,只能往下走
		}
		
		if(j == matrix[0].length - 1) {
			return matrix[i][j] + walk(matrix, i+1, j);//到这一列的最后一个位置,只能往右走
		}
		
		int right = walk(matrix, i, j+1);//right -> 右边位置到右下角的最短路径和
		int down = walk(matrix, i+1, j);//down -> 下边位置到右下角的最短路径和
		
		return matrix[i][j] + Math.min(right, down);
	}
	
	public static void main(String[] args) {
		int[][] m = {{1, 3, 5, 9},{8, 1, 3, 4},{5, 0, 6, 1},{8, 8, 4, 0}};
		System.out.println(walk(m, 0, 0));
	}
	
}

        该方法属于暴力枚举,它的复杂度很高!

        f(0,0) 会调用 f(0,1),f(1,0) 这两个过程。

        f(0,1) 是从该位置走到最右下角的路径和;f(1,0)是从该位置走到最右下角的路径和。

        f(0,1)又需要f(1,1),f(0,2)这两个状态;同理,f(1,0)需要f(1,1),f(2,0)这两个状态。

        但是可以发现这俩个中的f(1,1)重复了!即就是说他会整棵树都重新算一遍,里面会出现很多重复的状态,代价是很高的!

方法二、动态规划

      (无后效性问题)当我们发现递归中有重复状态的时候,而且重复状态与它到达的路径无关的时候,那么就一定可以改写成动态规划。如果参数确定,那么最后的结果一定确定。

      (有后效性问题)比如汉诺塔问题,之前的选择会影响后续的解。

        由暴力递归解法改写为动态规划;分析可变参数(可以代表返回值的状态)

        我们设定两个可变参数i与j,将i遍历所有的行号,将j遍历所有的列号,那么,它们的所有情况都装在一个二维表里。

        对于该问题,设置最后一行 /最后一列 /普遍的位置。

     

回溯

利用回溯算法求解八皇后问题

利用回溯算法求解 0-1 背包问题      

分治

利用分治算法求一组数据的逆序对个数

动态规划 0-1 背包问题

最小路径和(详细可看 Minimum Path Sum)

编程实现莱文斯坦最短编辑距离

编程实现查找两个字符串的最长公共子序列

编程实现一个数据序列的最长递增子序列     

对应的 LeetCode 练习题

实战递归:完成Leetcode上的Letter Combinations of a Phone Number(17)及permutations(46) (保留往期第六天任务)

实战DP:完成0-1背包问题实现(自我实现)及Leetcode上Palindrome Partitioning II(132) (保留往期第七天任务)

Regular Expression Matching(正则表达式匹配)

Coin Change (零钱兑换)

 Best Time to Buy and Sell Stock(买卖股票的最佳时机)

 Maximum Product Subarray(乘积最大子序列)

 Triangle(三角形最小路径和)

        

          

猜你喜欢

转载自blog.csdn.net/volcano1995/article/details/88557343