Leetcode 刷题 Lists Medium

目录

7. Reverse Integer

11. Container With Most Water

12. Integer to Roman

15. 3Sum

16. 3Sum Closest


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;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值