Hot 100题刷题 Day 2
Day2
-
三数之和题目:
题目简介:给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ,请你找出所有和为 0 且 不重复 的三元组。
题目解析:对于寻找不重复的三元组,首先想到使用 HashSet 结构去除重复的三元组元素,但乱序的三元组很难通过 HashSet 确定顺序不同的三元组是否产生了重复。因此,首先可以使用排序算法使得第二场循环元素大于第一层元素,第三层循环元素大于第二层循环元素。如此,顺序即可确定。但每次还需要遍历 HashSet 结构查找,因此这一题最佳的做法应当是双指针方法。
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> List = new ArrayList<>();
Arrays.sort(nums);
for (int c = nums.length - 1; c >= 2;) {
for (int a = 0, b = c - 1; b > a; ) {
// 为方便判断,这里使用两数之和为第三数的负数进行判断,由于是有序数组,左右指针的移动都较为简单。
int tmp_sum = nums[a] + nums[b];
if(tmp_sum > -nums[c])
b --;
else if(tmp_sum < -nums[c])
a ++;
else{
List<Integer> tmp = new ArrayList<Integer>();
tmp.add(nums[a]);
tmp.add(nums[b]);
tmp.add(nums[c]);
List.add(tmp);
// 注意!每次添加完一个三元数组进列表结构后,都应当移动左右指针一位,而为避免元素重复,使用了 do // while 循环,注意是改变位置后的元素和它前一元素进行对比,一旦相等,立即向前继续移动左指针
do{
a ++;
}while(a < b && nums[a - 1] == nums[a]);
//右指针则是移动后位置的元素与移动前的元素对比,一旦相等,继续移动,由于右指针必须大于左指针,避
//免了顺序互换产生的三元元组重复。
do{
b --;
}while(a < b && nums[b + 1] == nums[b]);
}
}
// c 元素是作为另外两个元素的负数存在的,所以它必须大于等于 2
do{
c --;
}while(c >= 2 && nums[c + 1] == nums[c]);
}
return List;
}
}
-
买卖股票的最佳时机:
题目简介:给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。买入股票和卖出股票均有时间顺序
题目解析:不难想到利用动态规划的思路进行操纵,但问题是时间复杂度需要限定在 \(O(N)\) 范围内,因此,使用 min 记录买入股票的最低价,使用 max 记录历史利用 min 买入股票到目前卖出的最高价格。
class Solution {
public int maxProfit(int[] prices) {
int max = 0, min = prices[0];
for(int i = 1; i < prices.length; i ++){
max = Math.max(max, prices[i] - min);
min = Math.min(min, prices[i]);
}
return max;
}
}
同时,还可以利用单调栈的思路进行操作。
在 pricesprices 数组的末尾加上一个 哨兵👨✈️(也就是一个很小的元素,这里设为 0)),就相当于作为股市收盘的标记(后面就清楚他的作用了)
假如栈空或者入栈元素大于栈顶元素,直接入栈
假如入栈元素小于栈顶元素则循环弹栈,直到入栈元素大于栈顶元素或者栈空。同时,在每次弹出的时候,我们拿他与买入的值(也就是栈底)做差,维护一个最大值。
-
买卖股票的最佳时机(包含冷冻期)
给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。
设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
- 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
- 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
对于动态规划题目,首先理清状态的分类,以及前后状态的转移:
动态规划状态 状态转移 \(i\) 天结束后持有股票 f[i][0] = max(f[i-1][0],f[i-1][2] - prices[i]) \(i\) 天结束后不持有股票,且 \(i + 1\) 天处于冷冻期 f[i][1] = f[i-1][0] + prices[i] \(i\) 天结束后不持有股票,且 \(i + 1\) 天不处于冷冻期(不做操作) f[i][2] = max(f[i-1][1],f[i-1][2]) 注意,状态是 \(i\) 天结束后的状态,代码如下:
class Solution { public int maxProfit(int[] prices) { if(prices.length <= 0) return 0; int [][] f = new int[prices.length][3]; f[0][0] = -prices[0]; f[0][1] = 0; f[0][2] = 0; int i = 1; for (;i < prices.length; i ++) { f[i][0] = Math.max(f[i - 1][0], f[i - 1][2] - prices[i]); f[i][1] = f[i - 1][0] + prices[i]; f[i][2] = Math.max(f[i - 1][1], f[i - 1][2]); } return Math.max(f[i - 1][1], f[i - 1][2]); } }

浙公网安备 33010602011771号