动态规划(一)

2018-03-25  本文已影响0人  lqsss

leetcode 198题目

给定一个数组(不同权重(钱)的店家),强盗可以抢不相邻的店家,求最大的钱数。

  1. 暴力搜索
public class HouseRobber {
    public int rob(int[] nums) {
        //return solve(nums.length-1 ,nums);
        return solve(0 ,nums);
    }

    private int solve(int idx, int[] nums) {
        if(idx > nums.length-1){
            return 0;
        }
        return Math.max(solve(idx+1,nums),solve(idx+2,nums) + nums[idx]);
    }
}

solve(int idx, int[] nums):抢下标为idx的店,最大的钱数。
return Math.max(solve(idx+1,nums),solve(idx+2,nums) + nums[idx]);
对于idx的店家只有两种可能:

结果:超时!
原因:

大量的重复运算,导致时间复杂度剧增,需要存储已经计算过的状态来解决这个问题

  1. 改进
    private static int[] res = null;

    public static int rob(int[] nums) {
        res = new int[nums.length];
        for (int i = 0; i < res.length; i++) {
            res[i] = -1 ;
        }
        return solve(0, nums);
    }

    private static int solve(int idx, int[] nums) {
        if (idx > nums.length - 1) {
            return 0;
        }
        if (res[idx] >= 0 ) {
            return res[idx];
        }
        res[idx] = Math.max(solve(idx + 1, nums), solve(idx + 2, nums) + nums[idx]);
        return res[idx];
    }

用res数组来记录已经计算过的状态
if (res[idx] >= 0 ) { return res[idx]; }
计算过的话,直接返回,去除冗余计算。

动态规划

public class HouseRobber {

    public int rob(int[] nums) {
        if (nums.length == 0) {
            return 0;
        }
        if (nums.length == 1) {
            return nums[0];
        }
        int[] dp = new int[nums.length]; //记录抢到某个下标时的最优解
        dp[0] = nums[0];
        dp[1] = Math.max(nums[0], nums[1]);
        for (int i = 2; i < dp.length; i++) {
            dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);
        }
        return dp[dp.length - 1];
    }
}
  1. 实质:递归
  2. 最优子结构
  1. 重叠子问题
    • 去冗余
    • 空间换时间
上一篇 下一篇

猜你喜欢

热点阅读