wy的leetcode刷题记录_Day14
904. 水果成篮
今天的每日一题是:904. 水果成篮
题目介绍
你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果种类 。你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:
你只有两个篮子,并且每个篮子只能装 单一类型的水果。
每个篮子能够装的水果总量没有限制。你可以选择任意一棵树开始采摘,你必须从每棵树(包括开始采摘的树)上恰好摘一个水果
。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。
给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。
示例 1:
输入:fruits = [1,2,1]
输出:3
解释:可以采摘全部 3 棵树。
示例 2:
输入:fruits = [0,1,2,2]
输出:3
解释:可以采摘 [1,2,2] 这三棵树。如果从第一棵树开始采摘,则只能采摘 [0,1] 这两棵树。
思路
本题可以采用滑动窗口来做,有题目知道我们只有俩个篮子,我们使用哈希表来果子的种类和果子的数量,使用俩个指针来指向滑动窗口的开始和结束位置,一旦种类超过俩种(哈希表的大小大于2)就将递减活动窗口最左边的树直到滑动窗口内的树上的果子的种类只有俩种(哈希表的大小小于2),用一个临时遍历ans来记录每次哈希表大于2之后的数量,返回其中的最大值。
代码
class Solution {
public:
int totalFruit(vector<int>& fruits) {
int n=fruits.size();
unordered_map<int,int> temp;
int left=0,right=0;
int ans=0;
for(int right=0;right<n;right++)
{
temp[fruits[right]]++;
while(temp.size()>2)
{
auto it=temp.find(fruits[left]);
it->second--;
if(it->second==0)
{
temp.erase(it);
}
left++;
}
ans=max(ans,right-left+1);
}
return ans;
}
};
收获
简单的滑动窗口题,熟练了STL
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。
思路
一、暴力解法
直接循环遍历时间序上从左到右寻找最大间距。
二、贪心算法
暴力解法的优化,减少了一层循环,通过遍历每一个元素,取左区间的最小值,然后用右区间的最大值得到差值。
三、动态规划:
1.确定dp数组的含义:dp[i][0]表示第i天持有股票所拥有的最大现金,dp[i][1]表示第i天不持有股票所拥有的最大现金
2.确定dp数组的递推公式:
dp[i][0]可以是第i-1天所持有股票所拥有的现金,或者是第i天购入股票,选取其中的最大值,其公式为dp[i][0] = max(dp[i - 1][0], -prices[i]);
dp[i][1]可以是第i-1天持有股票所拥有的现金,或者第i天卖出去(第i-1天所持有股票所拥有的现金+今日股票价格),选取其中的最大值,其公式为:dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0])
代码
class Solution {
public:
int maxProfit(vector<int>& prices) {
int result = 0;
for (int i = 0; i < prices.size(); i++) {
for (int j = i + 1; j < prices.size(); j++){
result = max(result, prices[j] - prices[i]);
}
}
return result;
}
};
class Solution {
public:
int maxProfit(vector<int>& prices) {
int low = INT_MAX;
int result = 0;
for (int i = 0; i < prices.size(); i++) {
low = min(low, prices[i]); // 取最左最⼩价格
result = max(result, prices[i] - low); // 直接取最⼤区间利润
}
return result;
}
};
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n=prices.size();
if(n==0)
return 0;
vector<vector<int>>dp(n,vector<int>(2));
dp[0][0]=-prices[0];
dp[0][1]=0;
for(int i=1;i<n;i++)
{
dp[i][0]=max(dp[i-1][0],-prices[i]);
dp[i][1]=max(dp[i-1][1],dp[i-1][0]+prices[i]);
}
return dp[n-1][1];
}
};
收获
巩固了动态规划的知识,掌握一点贪心。做题要从基础做法开始,先暴力法,再仔细观察题目是否有可优化的算法,优化后再观察是否可以二次优化(节省空间or时间之类的)。