121. 买卖股票的最佳时机
题目
121. 买卖股票的最佳时机 难度:easy
给定一个数组 prices
,它的第 i
个元素 prices[i]
表示一支给定股票第 i
天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0
。
示例 1:
代码语言:javascript复制输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
示例 2:
代码语言:javascript复制输入: prices = [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
方法一:贪心
思路
这里的话,贪心思想是比较适用的,即想获取最大利润,那么就要买入的时候价格相对最低,卖出的时候价格相对最高,所以需要找出给定数组中两个数字之间的最大差值(即,最大利润);
形式上,对于每组 i 和 j(其中 j > i)我们需要找出 max(prices[j]−prices[i])
。
解题
Python:
代码语言:javascript复制# 此方法会超时
class Solution:
def maxProfit(self, prices: List[int]) -> int:
ans = 0
for i in range(len(prices)):
for j in range(i 1, len(prices)):
ans = max(ans, prices[j] - prices[i])
return ans
Java:
代码语言:javascript复制public class Solution {
public int maxProfit(int[] prices) {
int maxprofit = 0;
for (int i = 0; i < prices.length - 1; i ) {
for (int j = i 1; j < prices.length; j ) {
int profit = prices[j] - prices[i];
if (profit > maxprofit) {
maxprofit = profit;
}
}
}
return maxprofit;
}
}
方法二:动态规划
思路
上述方法一只是展示了一下「贪心」算法的思想,但实际是,两次遍历的时间复杂度非常高,因此我们需要对此进行优化,做到一次遍历,下边就使用「动态规划」来进行优化;
假设给定的数组为:[7, 1, 5, 3, 6, 4]
如果我们在图表上绘制给定数组中的数字,我们将会得到:
我们来假设自己来购买股票。随着时间的推移,每天我们都可以选择出售股票与否。那么,假设在第 i
天,如果我们要在今天卖股票,那么我们能赚多少钱呢?
显然,如果我们真的在买卖股票,我们肯定会想:如果我是在历史最低点买的股票就好了!太好了,在题目中,我们只要用一个变量记录一个历史最低价格 minprice
,我们就可以假设自己的股票是在那天买的。那么我们在第 i
天卖出股票能得到的利润就是 prices[i] - minprice
。
因此,我们只需要遍历价格数组一遍,记录历史最低点,然后在每一天考虑这么一个问题:如果我是在历史最低点买进的,那么我今天卖出能赚多少钱?当考虑完所有天数之时,我们就得到了最好的答案。
解题
Python:
代码语言:javascript复制class Solution:
def maxProfit(self, prices: List[int]) -> int:
inf = int(1e9)
minprice = inf
maxprofit = 0
for price in prices:
maxprofit = max(price - minprice, maxprofit)
minprice = min(price, minprice)
return maxprofit
Java:
代码语言:javascript复制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;
}
}
409. 最长回文串
题目
409. 最长回文串 难度:easy
给定一个包含大写字母和小写字母的字符串 s
,返回 通过这些字母构造成的 最长的回文串 。
在构造过程中,请注意 区分大小写 。比如 "Aa"
不能当做一个回文字符串。
示例 1:
代码语言:javascript复制输入: s = "abccccdd"
输出: 7
解释: 我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。
示例 2:
代码语言:javascript复制输入: s = "a"
输入: 1
提示:
1 <= s.length <= 2000
s
只由小写 和/或 大写英文字母组成
方法一:贪心
思路
根据题意,我们主要将字符串重新构造形成一个最长的回文串,因此,需要先对每个字符进行统计,
代码语言:javascript复制count = []
for ..:
# ch 表示字符串中的单个字符
count[ch] = 1
然后根据回文串的性质,对其进行处理:如果该字符一共出现了偶数次,那就一股脑的放在两侧,如果出现了奇数次,则需要慎重选择了;
因为在回文串中,偶数个字符并不会对回文造成影响,但奇数个会,比如起始有 aba
,这时候来了两个 c
,可以直接加入两侧变成 cabac
,还是回文,如果是一个 c
呢,那么插入在哪里都会出现问题,因为原字符串中已经有一个字符的个数是奇数的了;
因此得出结论,回文串中允许出现字符的个数为奇数,但只能有一个字符的个数为奇数,所以为了得到最长回文串,所以对个数为奇数的字符,我们要选择长度最长的;
解题
Python:
代码语言:javascript复制class Solution:
def longestPalindrome(self, s: str) -> int:
ans = 0
count = collections.Counter(s)
for v in count.values():
ans = v // 2 * 2
if ans % 2 == 0 and v % 2 == 1:
ans = 1
return ans
Java:
代码语言:javascript复制class Solution {
public int longestPalindrome(String s) {
int[] count = new int[128];
int length = s.length();
for (int i = 0; i < length; i) {
char c = s.charAt(i);
count[c] ;
}
int ans = 0;
for (int v: count) {
ans = v / 2 * 2;
if (v % 2 == 1 && ans % 2 == 0) {
ans ;
}
}
return ans;
}
}