leetcode 11~20

leetcode 11~20

11. Container With Most

双指针

class Solution {
public:
    int maxArea(vector<int>& height) {
        int ans = 0, len = height.size();
        for(int l = 0, r = len - 1; l < r; ){
            ans = max(ans, (r - l) * min(height[l], height[r]));
            //哪个短就往里移动哪个指针,因为宽减小、高只有变大才可能出现更大面积
            if(height[l] < height[r])   l++;
            else    r--;
        }
        return ans;
    }
};

12. Integer to Roman

且记做数学吧,找规律

Clip_20220420_102116.png

class Solution {
public:
    string intToRoman(int num) {
        string res; 
        int values[] = {
            1000, 
            900, 500, 400, 100,
            90, 50, 40, 10,
            9, 5, 4, 1
        };
        string reps[] = {
            "M",
            "CM", "D", "CD", "C",
            "XC", "L", "XL", "X",
            "IX", "V", "IV", "I"
        };
        for(int i = 0; i < 13; i++){
            while(num >= values[i]){
                num -= values[i];
                res += reps[i];
            }
        }
        return res;
    }
};

13. Roman to Integer

数组模拟哈希表

class Solution {
public:
    int romanToInt(string s) {
        int hash[26] = {0}, ans = 0;
        hash['I' - 'A'] = 1, hash['V' - 'A'] = 5;
        hash['X' - 'A'] = 10, hash['L' - 'A'] = 50;
        hash['C' - 'A'] = 100, hash['D' - 'A'] = 500;
        hash['M' - 'A']  = 1000;
        for(int i = 0; i < s.length(); i++){
            //如果前面比后面小,那就是减
            if(i < s.length() - 1 && hash[s[i] - 'A'] < hash[s[i + 1] - 'A'])
                ans -= hash[s[i] - 'A'];
            else
                ans += hash[s[i] - 'A'];
        }
        return ans;
    }
};

14. Longest Common Pre

遍历就完事了

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        string res;
        if(strs.empty()) return res;
        for(int i = 0; ; i++){
            if(i >= strs[0].size()) return res;
            char c = strs[0][i];
            for(auto& s : strs){
                if(i >= s.size() || s[i] != c)
                    return res;
            }
            res += c;
        }
        return res;
    }
};

15. 3Sum

排序后双指针,并且加了一些优化

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> ans;
        sort(nums.begin(), nums.end());
        int len = nums.size();
        if(len < 3) return ans; //优化:长度小于3,必无
        for(int i = 0; i < len; i ++){
            //去重
            if(i && nums[i] == nums[i - 1]) continue;
            if(nums[i] > 0) break; //优化:如果第一个数都大于0,就不用判断了
            for(int j = i + 1, k = len - 1; j < k; j++){
                if(j - 1 > i && nums[j -1] == nums[j])  continue;
                if(nums[i] + nums[j] > 0) break; //优化:前两个和大于0,也不用找了
                //k是从最右边走的,所以要先向左找到最左边的使和不小于0的数
                while(k - 1 > j && nums[i] + nums[j] + nums[k - 1] >= 0)  k--;
                if(nums[i] + nums[j] + nums[k] == 0)
                    ans.push_back({nums[i], nums[j], nums[k]});
            }
        }
        return ans;
    }
};

16. 3Sum Closest

双指针,看着像O(n^3),但第二个for之内j 和 k移动的次数和最大为n,故O(n^2)

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        sort(nums.begin(), nums.end());
        int len =  nums.size();
        pair<int, int> ans(INT_MAX, INT_MAX);
        for(int i = 0; i < len; i++){
            for(int j = i + 1, k = len - 1; j < k; j ++){
                //找到和大于target的最小值
                while(k - 1 > j && nums[i] + nums[j] + nums[k - 1] >= target) k--;
                int t = nums[i] + nums[j] + nums[k];
                //pair先按first比较,如果相等,再按照second比较。
                ans = min(ans, make_pair(abs(t - target), t));
                //k左边一个便是小于target的最大值了
                if(k - 1 > j){
                    t = nums[i] + nums[j] + nums[k - 1];
                    ans = min(ans, make_pair(target - t, t));
                }
            }
        }
        return ans.second;
    }
};

或许是优化的解法,O(n^2)

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        sort(nums.begin(), nums.end());
        const vector<int>::size_type N = nums.size();
        if (N >= 3) {
            // 前三个数之和作为初始化
            int sum = nums[0] + nums[1] + nums[2];
            for (auto x = nums.begin(); x < nums.end() - 2; ++x) {
                auto left = x + 1, right = nums.end() - 1;
                while (left < right) {
                    const int t = *x + *left + *right;
                    if (t > target) {
                        --right;
                        if (abs(target - sum) > abs(target - t)) sum = t;
                    }
                    else if (t < target) {
                        ++left;
                        if (abs(target - sum) > abs(target - t)) sum = t;
                    }
                    else return target;
                }
            }
            return sum;
        }
        return 0;
    }
};

17. Letter Combinations of

DFS

class Solution {
public:
    vector<string> ans;
    string map[10] = {
        "", "", "abc", "def",
        "ghi", "jkl", "mno",
        "pqrs", "tuv", "wxyz"
    };

    vector<string> letterCombinations(string digits) {
        //!!!这个很关键,不然输入空字符串时,会放进去一个空字符串
        if(digits.length() == 0) return ans;
        string temp;
        dfs(digits, 0, temp);
        return ans;
    }

    void dfs(string digits, int i, string& temp){
        if(i >= digits.length()){
            ans.push_back(temp);
            return;
        }
        for(int k = 0; k < map[digits[i] - '0'].length(); k++){
            temp += map[digits[i] - '0'][k];
            dfs(digits, i + 1, temp);
            temp = temp.substr(0, i);
        }
    }
};

y总的写法

    vector<string> letterCombinations(string digits) {
        if(digits.empty()) return ans;
        dfs(digits, 0, "");
        return ans;
    }

    void dfs(string digits, int i, string path){
        if(i >= digits.length()){
            ans.push_back(path);
            return;
        }
        for(auto c : map[digits[i] - '0'])
            dfs(digits, i + 1, path + c);
    }

18. 4Sum

遍历排序双指针,看着像O(n^4),但第三个for之内l 和 r移动的次数和最大为n,故O(n^3)

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>>  ans;
        int len = nums.size();
        sort(nums.begin(), nums.end());
        for(int i = 0; i < len; i ++){
            if(i && nums[i] == nums[i - 1]) continue;
            for(int j = i + 1; j < len; j ++){
                if(j - 1 > i && nums[j] == nums[j - 1]) continue;
                for(int l = j + 1, r = len - 1; l < r; l++){
                    if(l - 1 > j && nums[l] == nums[l - 1]) continue;
                    //每个数的范围都是abs <= 10^9,会溢出
                    while(r - 1 > l && ((long long)nums[i] + nums[j] + nums[l] + nums[r - 1]) >= target) r--;
                    if(((long long)nums[i] + nums[j] + nums[l] + nums[r]) == target)
                        ans.push_back({nums[i], nums[j], nums[l], nums[r]});
                }
            }
        }
        return ans;
    }
};

19. Remove Nth Node Fr

快慢指针,也可以先遍历求长度,复杂度是一样的

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        //需要建立个虚拟头节点,因为可能删除头结点
        auto dummy = new ListNode(-1);
        dummy->next = head;
        //搞一个双指针滑动窗口,当最后一个移动到null,找到倒数第n+1个节点
        auto left = dummy, right = head;
        while(n--)
            right = right->next;
        while(right){
            left = left->next;
            right = right->next;
        }
        left->next = left->next->next;
        return dummy->next;
    }
};

20. Valid Parentheses

数组模拟栈

class Solution {
public:
    char stack[5010];//栈中最多放一半才可能为有效的括号

    bool isValid(string s) {
        int len = s.length();
        int top = -1;//栈顶指针
        if(len & 1) return false;//奇数长度肯定不行
        for(int i = 0; i < len; i++){
            if(top >= len / 2) return false; //如果放的超过总长度一半就肯定不行了
            if(s[i] == '(' || s[i] == '[' || s[i] == '{')
                stack[++top] = s[i];
            else{
                if(s[i] == ')'){
                    //top如果是-1就越界了
                    if(top >= 0 && stack[top] == '(') top--;
                    else return false;
                }
                else if(s[i] == ']'){
                    if(top >= 0 && stack[top] == '[') top--;
                    else return false;
                }
                else{
                    if(top >= 0 && stack[top] == '{') top--;
                    else return false;
                }
            }
        }
        return top == -1;
    }
};

用stack模板,小技巧左括号与右括号asill码差小于等于2

class Solution {
public:
    bool isValid(string s) {
        if(s.length() & 1) return false;
        stack<char> stk;
        for(auto c : s){
            if(c == '[' || c == '(' || c == '{')
                stk.push(c);
            else if(!stk.empty() && abs(stk.top() - c) <= 2)
                stk.pop();
            else return false;
        }
        return stk.empty();
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值