力扣刷题笔记(11)

开始做动态规划部分的内容了,这部分有四个题,所以就对半开吧。

做这些题目的时候,有那么一些感觉像是回到了小时候做奥数的感觉,反正都是难。

第一题:(爬楼梯)

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 12 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

示例 1:

输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1.  1+ 12.  2 阶
示例 2:

输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1.  1+ 1+ 12.  1+ 23.  2+ 1> 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/climbing-stairs
> 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


第二题:买卖股票的最佳时机

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。

注意:你不能在买入股票前卖出股票。

示例 1:

输入: [7,1,5,3,6,4]
输出: 5

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

输入: [7,6,4,3,1]
输出: 0

解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


我的题解(1)

这题居然判定为简单题,看来是我太菜了。

我倒也不是做不出来,只是我的算法无法处理过大的数据,哎。

我是这样想的:既然有n个台阶,假设两步走的次数为k,则一步走的次数就是n-2k,那么将这些两步走的次数穿插在一步走的情况当中,就是一个排列组合问题。

那就将排列组合整理成一个函数,对k进行递归并求和2,便是最后的结果。

于是代码就出来了:


//二代版本
int twostep(int n,int two)
{
	int temp = 1;
	int i = n - two;
	int del = 1;

	for (; i > n - 2 * two; i--)
	{
		temp *= i;
		while (temp % del == 0 && del <= two)
		{
			temp /= del;
			del++;
		}
	}
	while (del <= two)
	{
		temp /= del;
		del++;
	}
	return temp;
}

int climbStairs(int n) 
{
	int step = n / 2;
	int ret = 1;
	while (step > 0)
	{
		ret += twostep(n, step);
		step--;
	}
	return ret;
}

一代版本是全乘完再统一除。

然后发现当n到35的时候就扛不住了,换了二代版本。没想到还是抗不过45。
其实如果将除数放在数组里面做三代版本是可以的,但是那样就太肥了。。。

最后,我接受了现实,人外有人,那就看看别人怎么做的。
斐波那契数列。。。

斐波那契解法
int climbStairs(int n) {
        if(n==1||n==2)
            return n;
        int n1=1,n2=2;
        for(int i=3;i<=n;i++)
            {
            int temp=n1+n2;
            n1=n2;
            n2=temp;
        }
        return n2;
    }

原来这是一个找规律的题目啊。。。


我的题解(2)

上次做的那题,可以多次买卖,这次只能单次,那波峰波谷法就不好用了。

因为当天下降可能是“虚假下降”,接下来会有反弹。

其实虚假下降也好判断。但是吧,困扰我的是:

“过度虚假下降”:就是后面会反弹,但是这个下降力度已经超过了之前积攒下来的盈利,出现这种情况,应该认为之前的天数都不存在,从波谷重头来过。

其实这个情况单独处理也并不是什么很难的事情,但是把这些单独处理都没什么问题的糅杂在一起的时候,那就很麻烦了。


前面失败了之后,我又想起了最初那个被掐断的小火苗:干脆递归传入当前最小值,遍历找利益最大处。然后,过了。

int maxProfit(vector<int>& prices) {
        if (prices.size() < 1)
            return 0;
        int the_min= prices[0];
        int ret = 0;

        for (int i = 1; i < prices.size(); i++) {
            ret = max(ret, prices[i] - the_min);
            the_min = min(the_min, prices[i]);
        }
        return ret;
    }

其实我只是尝试一下,因为一开始掐灭这个想法也不是没有道理的。
因为最后买入点可不一定会是波谷,卖出点是不是波峰倒是无所谓,关键就是那个买入点。

但是,当它奇迹般的通过的时候,我突然想通了,ret和不止有the_min一个变量在控制,所以the_min是不是波谷对ret并没有绝对的影响。

有点绕,没绕出来打盘王者冷静冷静。一定是可以绕出来的。


官方题解(1)

方法三:动态规划(斐波那契数列)
算法

不难发现,这个问题可以被分解为一些包含最优子结构的子问题,即它的最优解可以从其子问题的最优解来有效地构建,我们可以使用动态规划来解决这一问题。

第 ii 阶可以由以下两种方法得到:

在第 (i-1) 阶后向上爬一阶。

在第 (i−2) 阶后向上爬 2 阶。

所以到达第 ii 阶的方法总数就是到第 (i-1)(i−1) 阶和第 (i-2)(i−2) 阶的方法数之和。

令 dp[i]dp[i] 表示能到达第 ii 阶的方法总数:

dp[i]=dp[i-1]+dp[i-2]
dp[i]=dp[i−1]+dp[i−2]

作者:LeetCode
链接:https://leetcode-cn.com/problems/climbing-stairs/solution/pa-lou-ti-by-leetcode/
来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


官方题解(2)

方法二:一次遍历
算法

假设给定的数组为:[7, 1, 5, 3, 6, 4]

如果我们在图表上绘制给定数组中的数字,我们将会得到:

在这里插入图片描述

我们来假设自己来购买股票。随着时间的推移,每天我们都可以选择出售股票与否。那么,假设在第 i 天,如果我们要在今天卖股票,那么我们能赚多少钱呢?

显然,如果我们真的在买卖股票,我们肯定会想:如果我是在历史最低点买的股票就好了!太好了,在题目中,我们只要用一个变量记录一个历史最低价格 minprice,我们就可以假设自己的股票是在那天买的。那么我们在第 i 天卖出股票能得到的利润就是 prices[i] - minprice。

因此,我们只需要遍历价格数组一遍,记录历史最低点,然后在每一天考虑这么一个问题:如果我是在历史最低点买进的,那么我今天卖出能赚多少钱?当考虑完所有天数之时,我们就得到了最好的答案。

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/solution/121-mai-mai-gu-piao-de-zui-jia-shi-ji-by-leetcode-/
来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

public class Solution {
    public int maxProfit(int prices[]) {
        int minprice = Integer.MAX_VALUE;
        int maxprofit = 0;
        for (int i = 0; i < prices.length; i++) {
            if (prices[i] < minprice)
                minprice = prices[i];
            else if (prices[i] - minprice > maxprofit)
                maxprofit = prices[i] - minprice;
        }
        return maxprofit;
    }
}

> 作者:LeetCode-Solution
> 链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/solution/121-mai-mai-gu-piao-de-zui-jia-shi-ji-by-leetcode-/
> 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

总结

动手前,还是先想清楚吧。。。。。。
永远不要节省整理思绪的时间,不然,在实现功能的时候都会让你还。

原创文章 153 获赞 719 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_43762191/article/details/105905529