马上要面试了,把前些天在LeetCode上刷的题再看一遍。
写上注释,算复习了,也方便以后复习。
带 * 号的为忘记怎么做的。
16. 121. 买卖股票的最佳时机(简单优化)
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
if (n == 0) return 0;
int minPrice = prices[0];
int ans = 0;
// 只需要遍历一遍的做法
for (int i = 1; i < n; i++) {
// 发现更优答案,则当前价格一定大于之前的最小价格
if (prices[i] - minPrice > ans) ans = prices[i] - minPrice;
// 否则,看看能不能更新一下最小价格,以便之后获得更优答案
else if (prices[i] < minPrice) minPrice = prices[i];
}
return ans;
}
};
/*
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
if (n == 0) return 0;
// 需要遍历三遍
vector<int> left(n), right(n);
// left[i]存第0到第i天价格的最低值
left[0] = prices[0];
for (int i = 1; i < n; i++) {
left[i] = min(prices[i], left[i - 1]);
}
// right[i]存第n-1到第i天价格的最高值
right[n - 1] = prices[n - 1];
for (int i = n - 2; i >= 0; i--) {
right[i] = max(prices[i], right[i + 1]);
}
// 寻找最优值,对非递增序列也有效
int ans = 0;
for (int i = 0; i < n; i++) {
ans = max(ans, right[i] - left[i]);
}
return ans;
}
};
*/
17. 42. 接雨水(数组优化)
class Solution {
public:
int trap(vector<int>& height) {
// 遍历三遍数组
int n = height.size();
if (n == 0) return 0;
vector<int> left_max(n), right_max(n);
// left[i]存从0到i的最大值
left_max[0] = height[0];
for (int i = 1; i < n; i++) left_max[i] = max(left_max[i-1], height[i]);
// right[i]存从n-1到i的最大值
right_max[n-1] = height[n-1];
for (int i = n - 2; i >= 0; i--) right_max[i] = max(right_max[i+1], height[i]);
// 寻找答案,每个位置能存的水的量为两边最大值较小的减去高度
int ans = 0;
for (int i = 0; i < n; i++) ans += (min(left_max[i], right_max[i]) - height[i]);
return ans;
}
};
18. 53. 最大子序和(动态规划)
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int n = nums.size();
if (n == 0) return 0;
vector<int> dp(n);
// dp[i]记录以i位置为结尾的最大子序列和
dp[0] = nums[0];
for (int i = 1; i < n; i++) {
// 老题了,动态规划的状态转移
if (dp[i-1] < 0) dp[i] = nums[i];
else dp[i] = dp[i-1] + nums[i];
}
// 再遍历一遍找到最值
int ans = dp[0];
for (int i = 1; i < n; i++) {
ans = max(ans, dp[i]);
}
return ans;
}
};
19. 20. 有效的括号(栈模拟)
class Solution {
public:
// 是否是右括号
bool isRight(char ch) {
return (ch == ')' || ch == ']' || ch == '}');
}
// 是否是配套括号
bool isOK(char ch1, char ch2) {
return (ch1 == '(' && ch2 == ')' || ch1 == '[' && ch2 == ']' || ch1 == '{' && ch2 == '}');
}
bool isValid(string s) {
int len = s.length();
stack<char> stk;
for (int i = 0; i < len; i++) {
char ch = s[i];
// 右括号需要进行判断与处理
if (isRight(ch)) {
// 如果为空,则不配套,返回false
if (stk.empty()) return false;
char temp = stk.top();
// 否则,如果配套,弹出左括号
if (isOK(temp, ch)) {
stk.pop();
}
// 不配套就返回false
else {
return false;
}
}
// 左括号直接压入
else {
stk.push(ch);
}
}
return stk.empty();
}
};
20. 15. 三数之和(对撞指针)
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int n = nums.size();
sort(nums.begin(), nums.end());
vector< vector<int> > ans;
for (int i = 0; i < n - 2; i++) {
if (nums[i] > 0) break; // 不可能再等于0了
if (i > 0 && nums[i] == nums[i - 1]) continue; // 去重
int l = i + 1, r = n - 1; // 对撞指针
while (l < r) {
int sum = nums[i] + nums[l] + nums[r];
if (sum == 0) {
vector<int> v;
v.push_back(nums[i]);
v.push_back(nums[l]);
v.push_back(nums[r]);
ans.push_back(v);
while (l < r && nums[l] == nums[l + 1]) l++; // 去重
while (l < r && nums[r] == nums[r - 1]) r--; // 去重
l++;
r--;
}
else if (sum < 0) l++;
else r--;
}
}
return ans;
}
};