2021-06-02菜鸟刷题(12)【打家劫舍Ⅱ&股票买卖】

【打家劫舍Ⅱ&股票买卖】

力扣 213. 打家劫舍 II

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。

给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。

 

示例 1:

输入:nums = [2,3,2]
输出:3
解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。
示例 2:

输入:nums = [1,2,3,1]
输出:4
解释:你可以先偷窃 1 号房屋(金额 = 1),然后偷窃 3 号房屋(金额 = 3)。
     偷窃到的最高金额 = 1 + 3 = 4 。
示例 3:

输入:nums = [0]
输出:0

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/house-robber-ii
 

代码:

class Solution {
    public int rob(int[] nums) {
        int N = nums.length;
        if(N==0)return 0;
        int[] S=new int[N];//前n-1房子即去掉最后一间房子的最大利益
        int[] Sr=new int[N];//去掉第一间房子的最大利益
        if(N==1){
            S[0]=nums[0];
            return S[0];
        }
        if(N==2){
            S[1]=Math.max(nums[0],nums[1]);
            return S[1];
        }
        if(N==3){
            S[1]=Math.max(nums[0],nums[1]);
            Sr[1]=Math.max(nums[1],nums[2]);
            return Math.max(S[1],Sr[1]);
        }
        int[] numsr=new int[N];
        for(int i=0,j=N-1;i<N;i++,j--){//nums数组的值倒过来放在numsr中
            numsr[i]=nums[j];
        }
        if(N>3){
            S[0]=nums[0];
            S[1]=Math.max(nums[0],nums[1]);
            Sr[0]=numsr[0];
            Sr[1]=Math.max(numsr[0],numsr[1]);
            for(int i=2;i<N-1;i++){
                S[i]=Math.max(S[i-2]+nums[i],S[i-1]);
            }
            for(int i=2;i<N-1;i++){
                Sr[i]=Math.max(Sr[i-2]+numsr[i],Sr[i-1]);
            }
        }
        return Math.max(Sr[N-2],S[N-2]);
    }
}

分析:

承接昨天的打家劫舍(3条消息) 【爬楼梯&打家劫舍】_qq_43900762的博客-CSDN博客

该题房子变成环形相邻,所以我们考虑偷最后一个房子的时候不仅倒数第二个房子不能偷,第一个房子也不能偷,判断起来比较麻烦(第一个房子有没有偷过?该不该减去第一间房子的值?)。

但是我们发现,如果不偷最后一间房子,就是直接算前n-1间房子的最大利益,所以我们先直接去掉最后一个房子不看,假设总共有n个房子,即只考虑n-1个房子,那么方法就和昨天的一样了(昨天的:(3条消息) 【爬楼梯&打家劫舍】_qq_43900762的博客-CSDN博客),这样可以计算出前n-1间房子的最大利益,那么怎么考虑到最后一间房子(第n间房子)呢?倒过来看,即不考虑第一间房子,算n,n-1,n-2,n-3,...3,2这些房子的最大利益,最后正序和倒序的两种值取最大即可。

我这里用了numsr数组来放nums倒序的值来计算去掉第一间房子的情况,这样for判断条件就和之前的一样。应该可以用原数组nums来做,i起始值从nums的最后开始,应该是n-3(我不确定),然后i--

 因为是环形且我们要去掉一间房子来计算,所以n=3也是特殊情况,因为i<N-1

 

力扣 121. 买卖股票的最佳时机

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

 

示例 1:

输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
示例 2:

输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 没有交易完成, 所以最大利润为 0。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock
 

代码:

class Solution {
    public int maxProfit(int[] prices) {
        int len=prices.length;
        if(len==0)return 0;
        int[] dp=new int[len];//存放利益的数组
        dp[0]=0;//第一天利益为0,设置为0
        int min=prices[0];//假设第一天为最低买入价格
        for(int i=1;i<len;i++){
            dp[i]=Math.max(dp[i-1],prices[i]-min);//计算利益
            min=Math.min(min,prices[i]);//调整最低价格
        }
        return dp[len-1];
    }
}

dp[i]=Math.max(dp[i-1],prices[i]-min);

昨天的利益 和 今天的价格减去最低的价格即今天卖出的利益 比较取最大利益

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值