#P3775. 第1题-股票收益
-
ID: 3119
Tried: 18
Accepted: 3
Difficulty: 3
所属公司 :
中兴
时间 :2025年9月23日
-
算法标签>贪心
第1题-股票收益
解题思路
-
相关算法:贪心算法(或等价的两状态 DP)。 核心结论:把所有相邻两天的上涨差值都赚到手即可。对每个
i=1..n-1
,若prices[i] > prices[i-1]
,就把差值prices[i]-prices[i-1]
加入答案。将所有正差值求和就是最大收益。 -
实现要点:
- 一次遍历价格数组;
- 若今天价高于昨天,则把这一段利润累加;
- 遍历结束即为答案。 该思路等价于“把所有上升段拆成若干买入-卖出的子交易”,拆分或合并不影响总收益。
复杂度分析
- 时间复杂度:
O(n)
,只需线性遍历一次。 - 空间复杂度:
O(1)
,常数额外空间。
代码实现
说明:为兼容评测中常见的两种输入形式:
- 标准两行:第一行
n
,第二行n
个价格;- 单一整体字符串(内部用
\n
表示换行),形如:"6\n7 1 5 3 6 4"
; 代码在主函数中统一做了输入清洗,并按题意用双引号包裹输出(如"7"
)。
Python
# 功能函数:贪心累加相邻正差值
def max_profit(prices):
ans = 0
for i in range(1, len(prices)):
if prices[i] > prices[i - 1]:
ans += prices[i] - prices[i - 1]
return ans
# 主函数:ACM 风格输入输出(兼容整体字符串 "6\n7 1 5 3 6 4")
if __name__ == "__main__":
import sys, ast
# 读入全部文本,便于同时兼容两种输入
s = sys.stdin.read().strip()
# 若是带引号的整体字符串,如 "6\n7 1 5 3 6 4",用 literal_eval 反转义
if len(s) >= 2 and s[0] == '"' and s[-1] == '"':
s = ast.literal_eval(s) # 将 "\n" 等转成真正的换行
# 清洗:去除可能出现的中括号和逗号,统一按空白切分
s = s.replace('[', ' ').replace(']', ' ').replace(',', ' ')
parts = s.split()
# 解析 n 和价格数组(题目默认输入合法)
n = int(parts[0]) if parts else 0
nums = list(map(int, parts[1:1 + n]))
ans = max_profit(nums)
# 题目要求:输出加双引号
print(f'"{ans}"')
Java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main {
// 功能函数:贪心累加相邻正差值
public static long maxProfit(int[] prices) {
long ans = 0L;
for (int i = 1; i < prices.length; i++) {
if (prices[i] > prices[i - 1]) {
ans += (long)(prices[i] - prices[i - 1]);
}
}
return ans;
}
// 主函数:ACM 风格,兼容 "6\n7 1 5 3 6 4" 或标准两行
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
String line;
// 读入全部文本
while ((line = br.readLine()) != null) {
sb.append(line).append('\n');
}
String s = sb.toString().trim();
// 若整体被双引号包裹,去掉引号并将 \n 反转义为真实换行
if (s.length() >= 2 && s.charAt(0) == '"' && s.charAt(s.length() - 1) == '"') {
s = s.substring(1, s.length() - 1).replace("\\n", "\n");
}
// 清洗后按空白切分
s = s.replace("[", " ").replace("]", " ").replace(",", " ");
String[] parts = s.trim().isEmpty() ? new String[0] : s.trim().split("\\s+");
int n = 0;
if (parts.length > 0) n = Integer.parseInt(parts[0]);
int[] prices = new int[n];
for (int i = 0; i < n && i + 1 < parts.length; i++) {
prices[i] = Integer.parseInt(parts[i + 1]);
}
long ans = maxProfit(prices);
// 按要求用双引号包裹输出
System.out.println("\"" + ans + "\"");
}
}
C++
#include <bits/stdc++.h>
using namespace std;
// 功能函数:贪心累加相邻正差值
long long max_profit(const vector<int>& prices) {
long long ans = 0;
for (size_t i = 1; i < prices.size(); ++i) {
if (prices[i] > prices[i - 1]) {
ans += (long long)(prices[i] - prices[i - 1]);
}
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
// 读入全部标准输入,兼容整体字符串或两行输入
string s((istreambuf_iterator<char>(cin)), istreambuf_iterator<char>());
auto trim = [](string &t) {
while (!t.empty() && isspace((unsigned char)t.back())) t.pop_back();
size_t i = 0;
while (i < t.size() && isspace((unsigned char)t[i])) ++i;
t = t.substr(i);
};
trim(s);
// 若整体被双引号包裹,去掉引号并把 "\n" 反转义成真实换行
if (s.size() >= 2 && s.front() == '\"' && s.back() == '\"') {
s = s.substr(1, s.size() - 2);
string t;
for (size_t i = 0; i < s.size(); ++i) {
if (s[i] == '\\' && i + 1 < s.size() && s[i + 1] == 'n') {
t.push_back('\n');
++i; // 跳过 'n'
} else {
t.push_back(s[i]);
}
}
s.swap(t);
}
// 清洗后用字符串流解析:替换中括号和逗号为分隔空格
for (char &c : s) {
if (c == '[' || c == ']' || c == ',') c = ' ';
}
stringstream ss(s);
int n = 0;
ss >> n;
vector<int> prices;
prices.reserve(max(0, n));
for (int i = 0, x; i < n && (ss >> x); ++i) {
prices.push_back(x);
}
long long ans = max_profit(prices);
// 按要求用双引号包裹输出
cout << '"' << ans << '"' << "\n";
return 0;
}
题目内容
用给定一个正整数及非负整数 prices 的列表,第一个正整数表示 prices 列表中数字的总个数,prices 表示某个股票在每天的价格。
用户初始持有股票为 0 ,现在需要基于 prices 的价格列表计算出如何买入卖出能够得到最大的现金收益。
其中要求每天仅能够持有一份股票,但是每天都可以将股票买入或者卖出,如果无法取得收益,返回的结果应该为 0 。
示例:
6
715364
表示共有 6 天的股票价格,第 1 天到第 6 天的价格分别为 7 1 5 3 6 4 。
输出:
7
表示可以得到的最大收益为 7
方法为:在第 2 天以 1 的价格买入,第 3 天以 5 的价格卖出,收益为 5−1=4 ;
在第 4 天以 3 的价格买入,第 5 天以 6 的价格卖出,收益为 6−3=3 ,总共收益为 4+3=7 。
输入描述
输入两行数字,第一行仅有一个数字,代表待股票价格的总个数,第二行是每天的股票价格 prices ,股票价格之间使用空格间隔。
提示:
1<=prices.length<=105
0<=prices[i]<=104
输出描述
输出为一个数字,表示股票买入卖出后可获取的最大收益值。
样例1
输入
"6\n7 1 5 3 6 4"
输出
"7"