动态规划初级篇

1.什么是动态规划:

大问题可分解成子问题,问题之间不独立,一般用数组保存记录值,不用递归是因为递归会使得重复计算,而动态递归不同于分治法的一点就是可以利用之前求出的解,不需要从头来。

(1)解法:
1.找出最优子结构
2.找出状态转换方程
3.给边界赋值

2.题目(力扣)

(1).121. 买卖股票的最佳时机

在这里插入图片描述在这里插入图片描述
最优子结构:
状态转换方程:

class Solution {
    public int maxProfit(int[] prices) {
        //思路:前i天的最大盈利=MAX(前i-1天的最大营利,第i天的价格-前i-1天的最小价格)
        int result=0;
        int min=0;
        int []max=new int[prices.length];
        min=prices[0];
        for(int i=1;i<prices.length;i++){
            max[i]=Math.max(max[i-1],prices[i]-min);
            if(min>prices[i]){
                min=prices[i];
            }
        }
        return max[prices.length-1];
    }
}
(2)找零钱问题:

思路其实跟爬楼梯一样

状态转移方程为:
countMin[i]=Math.min(count[i-1],count[i-3],count[i-7])+1;

package com.company;

public class Main {
//有零钱1/3/7元的,求找零钱的数目最少。
    public static void main(String[] args) {
        int count=change(17);
        System.out.println(count);
    }

    public static int change(int value){
        if(value==1||value==3||value==7){
            return 1;
        }
        else{
            int []count=new int[value+1];
            count[0]=0;
            count[1]=1;
            count[3]=1;
            count[7]=1;
            for(int i=2;i<=value;i++){
                if(i-3<0){
                    count[i]=count[i-1]+1;
                }
                else if(i-7<0){
                    count[i]=Math.min(count[i-1],count[i-3])+1;
                }
                else{
                    int min=Math.min(count[i-1],count[i-3]);
                    count[i]=Math.min(min,count[i-7])+1;
                }
            }
            return count[value];
        }
    }
}
(3)303. 区域和检索 - 数组不可变

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

class NumArray {
    int [] nums;
    int [][] count;
    public NumArray(int[] nums) {
        this.nums=nums;
        count=new int[nums.length][];
    }
    
    public int sumRange(int left, int right) {
        if(count[left]!=null){
            return count[left][right-left];
        }
        else{
            count[left]=new int[nums.length-left];
            count[left][0]=nums[left];
            for(int j=1;j<nums.length-left;j++){
           count[left][j]=count[left][j-1]+nums[left+j];
            }
            return count[left][right-left];
        }
    }
}

/**
 * Your NumArray object will be instantiated and called as such:
 * NumArray obj = new NumArray(nums);
 * int param_1 = obj.sumRange(left,right);
 */

在这里插入图片描述
法二:直接每次都求

class NumArray {
    int[] nums;
    public NumArray(int[] nums) {
        this.nums=nums;
    }
    
    public int sumRange(int left, int right) {
        int sum=0;
        for(int i=left;i<=right;i++){
            sum+=nums[i];
        }
        return sum;
    }
}

/**
 * Your NumArray object will be instantiated and called as such:
 * NumArray obj = new NumArray(nums);
 * int param_1 = obj.sumRange(left,right);
 */

法三:法一中的二维变一维度:

class NumArray {
    int[] nums;
    int []count;
    public NumArray(int[] nums) {
        this.nums=nums;
        count=new int[nums.length+1];
        for(int i=0;i<nums.length;i++){
            if(i==0){
                count[i]=nums[i];
            }
            else{
                count[i]=count[i-1]+nums[i];
            }
        }
    }
    
    public int sumRange(int left, int right) {
        if(left>0){
            return count[right]-count[left-1];
        }
        else{
            return count[right];
        }
    }
}

/**
 * Your NumArray object will be instantiated and called as such:
 * NumArray obj = new NumArray(nums);
 * int param_1 = obj.sumRange(left,right);
 */

在这里插入图片描述
不用再新开数组,直接nums数组原地求和即可

class NumArray {
    int[] nums;
    public NumArray(int[] nums) {
        this.nums=nums;
        for(int i=1;i<nums.length;i++){
            nums[i]+=nums[i-1];
        }
    }
    
    public int sumRange(int left, int right) {
        if(left>0){
            return nums[right]-nums[left-1];
        }
        else{
            return nums[right];
        }
    }
}

/**
 * Your NumArray object will be instantiated and called as such:
 * NumArray obj = new NumArray(nums);
 * int param_1 = obj.sumRange(left,right);
 */
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值