目录
7. Reverse Integer
主要考察了 C++ Int 类型的最大值和最小值的边界问题,按照题目意思不能出现 long 类型的数字,因为在 while 循环中设置 res 的大小判断及判读方式比较关键。
class Solution {
public:
int reverse(int x) {
// 涉及到正负号的处理
if((x / 10) == 0){
return x;
}
int positive = 1;
if(x < 0){
positive = -1;
if(x <= INT_MIN){
return 0;
}
x = -x;
}
int res = 0;
while(x > 0){
int num = x % 10;
// 这里比较关键,不需要减去 num 再除以 10,直接除 10 即可,前者会报错
// 最容易出现问题的地方
if(res > (INT_MAX/10) || -res < (INT_MIN/10)){
return 0;
}
// cout << INT_MAX << INT_MIN << endl;
// if (res > INT_MAX / 10) return 0;
res = res*10 + num;
cout << res << endl;
x /= 10;
}
return res * positive;
}
};
11. Container With Most Water
双指针移动问题
class Solution {
public:
int maxArea(vector<int>& height) {
// int maxRes = 0;
// // O(N^2) 算法会超时,N <= 10^5
// for(int i=0; i<height.size(); i++){
// for(int j=height.size()-1; j>=i; j--){
// int area = (j-i) * min(height[j], height[i]);
// cout << area << endl;
// maxRes = max(area, maxRes);
// }
// }
// return maxRes;
// 那么应该怎么以线性时长的算法进行解决呢?
int height_min = 0;
int i = 0, j = height.size()-1;
int maxRes = 0, area = 0;
while(i < j){
height_min = min(height[j], height[i]);
area = (j-i) * height_min;
if(maxRes < area){
maxRes = area;
}
if(height[j] > height_min){
// 省略了一些计算时长,不断优先移动较矮的柱子以缩小横坐标范围
// 如果同时移动两个柱子则可能丢掉最优解
while(height[i] <= height_min){
i++;
if(i >= j){
break;
}
}
}else{
while(height[j] <= height_min){
j--;
if(i >= j){
break;
}
}
}
}
return maxRes;
}
};
12. Integer to Roman
打表解决,对于数量较少的情况比较好用
class Solution {
public:
string intToRoman(int num) {
// 感觉是对每种情况逐一进行处理,居然是打表法解决
// 1 <= num <= 3999
int nums[15] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
string romans[15] = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
string ans = "";
for(int i=0; i<13; i++){
while(num >= nums[i]){ // 不断减去当前最大的值,转化成罗马数字
num -= nums[i];
ans += romans[i];
}
}
return ans;
}
};
15. 3Sum
指针移动操作,先固定一个,移动另外两个。值得注意的是去除重复元素的操作,每一个指针都要进行跳过重复元素。是一道细节操作值得借鉴的题目。
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
// 0 <= nums.length <= 3000,-10^5 <= nums[i] <= 10^5
// 首先排序,然后先固定一个指针,移动另外两个指针,时间复杂度是O(N^2)
// 要避免出现重复的情况
vector<vector<int>> res;
if(nums.size() < 3){
return res;
}
// C++ 数组排序函数
sort(nums.begin(), nums.end());
for(int i=0; i<nums.size()-2; i++){
int j = i+1;
int k = nums.size()-1;
while(j < k){
// 将此更新和的操作写到了 while 循环上面,导致和无法根据指针移动更新,导致错误
int twoSum = nums[j] + nums[k];
// cout << nums[i] << nums[j] << nums[k] << endl;
if(j < k && twoSum + nums[i] < 0){
j++;
}else if (j < k && twoSum + nums[i] > 0){
k--;
}
else if(twoSum + nums[i] == 0){
// 将其添加到结果集合中,但是要去重复
vector<int> ans;
ans.push_back(nums[i]);
ans.push_back(nums[j]);
ans.push_back(nums[k]);
res.push_back(ans);
// 去除重复的操作方法,并且在跳过重复元素后,还要进行指针的移动
while(j < k && (nums[j+1] == nums[j])){
j++;
}
while(j < k && (nums[k-1] == nums[k])){
k--;
}
j++; k--;
}
}
// 去除重复的操作方法,三个移动指针都需要去除重复
while(i<nums.size()-1 && nums[i] == nums[i+1]) i++;
}
return res;
}
};
16. 3Sum Closest
相比 3Sum 更简单的一道题,只需要移动指针并且记录和更新差的最小值就可以了。
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
int res = 0;
int min_gap = 100000;
for(int i=0; i<nums.size()-2; i++){
int j = i+1;
int k = nums.size()-1;
while(j < k){
int sum = nums[i] + nums[j] + nums[k];
if(abs(target-sum) < min_gap){
min_gap = abs(target-sum);
res = sum;
}
if(target > sum){
j++;
}else if(target < sum){
k--;
}else{
break;
}
}
}
return res;
}
};