LeetCode 11-20题解

11 中等

Solution

  1. 用i, j(i < j)表示选取的两条线位置, 则水量为((j - i)* min(a_j, a_i))

  2. 我们考虑固定选取的右侧j, 则左侧可选为1...j - 1

  3. (i in [1, j - 1]), 若存在 (k in [1, j - 1] & k < i & a_k >= a_i),

    则有((j - i)* min(a_j, a_i) < (j - k)* min(a_j, a_k)), 右侧固定为j时,左侧k比i更优

  4. 当前位置左侧位置高度均小于当前位置时,当考虑其右侧的位置的左边界时,当前位置时有效候选,无法直接丢弃

  5. 根据以上,可以枚举右侧的j, 左边界用候选集,更新res, 同时更新候选集

  6. 判断左侧高度是否有不小于当前的,用树状数组即可

Sample Code

const int maxn = 30010;
struct Node{
  int pos;
  int val;
};
class Solution {
public:
  vector<Node> Pareto;
  int s[maxn];
  inline int lowbit(int x) { return x & (-x);}
  void add(int x, int v){
      while(x < maxn - 10){
          s[x] += 1;
          x += lowbit(x);
      }
  }
  int get(int x){
      int res = 0;
      while(x){
          res += s[x];
          x -= lowbit(x);
      }
      return res;
  }
  int cal(Node x){
      int res = 0;
      for(Node u : Pareto){
          res = max(res, (x.pos - u.pos) * min(x.val, u.val));
      }
      return res;
  }
  int maxArea(vector<int>& height) {
      int res = 0;
      for(int i = 0; i < height.size(); ++i){
          int curHeight = height[i];
          if(curHeight == 0) continue;
          Node curNode = {i, curHeight};
          res = max(res, cal(curNode));
          if(get(maxn - 10) - get(curHeight - 1) == 0){
              add(curNode.val, 1);
              Pareto.push_back(curNode);
          }
      }
      return res;
  }
};

12 中等

Solution

  • 模拟

Sample Code

char weight[] = {'I', 'V', 'X', 'L', 'C', 'D', 'M'};
class Solution {
public: 
    void work(string & res, int x, int bit){
        if(x == 4){
            res += weight[2 * bit];
            res += weight[2 * bit + 1];
            return;
        }
        if(x == 9){
            res += weight[2 * bit];
            res += weight[2 * bit + 2];
            return;
        }
        if(x >= 5) {
            res += weight[2 * bit + 1];
            x -= 5;
        }
        while(x--) res += weight[2 * bit];
    }
    string intToRoman(int num) {
        int _4 = num / 1000;
        int _3 = num % 1000 / 100;
        int _2 = num % 100 / 10;
        int _1 = num % 10;
        string res = "";
        work(res, _4, 3);
        work(res, _3, 2);
        work(res, _2, 1);
        work(res, _1, 0);
        return res;
    }
};

13 简单

Solution

  • 简单模拟, 上面逆运算

Sample Code

class Solution {
public:
    int getV(char ch){
        switch(ch){
            case 'I':
                return 1;
            case 'V':
                return 5;
            case 'X':
                return 10;
            case 'L':
                return 50;
            case 'C':
                return 100;
            case 'D':
                return 500;
            case 'M':
                return 1000;
            default:
                return -1;
        }
    }
    bool isPreChar(char ch){
        return ch == 'I' || ch == 'X' || ch == 'C';
    }
    bool isPreSuf(char p, char s){
        if(p == 'I') return s == 'V' || s == 'X';
        if(p == 'X') return s == 'L' || s == 'C';
        if(p == 'C') return s == 'D' || s == 'M';
        return false;
    }
    int romanToInt(string s) {
        int res = 0; int len = s.length();
        for(int i = 0; i < s.length(); ++i){
            if(isPreChar(s[i]) && i < len - 1 && isPreSuf(s[i], s[i + 1])){
                res += getV(s[i + 1]) - getV(s[i]);
                ++i;
            }else res += getV(s[i]);
        }
        return res;
    }
};

14 简单

Solution

  • 可用模拟遍历
  • 用字典树插入

Sample Code(字典树)

class Solution {
public:
    int ch[210 * 210][26];
    int sz = 1;
    int cnt[210 * 210 * 26];
    string ans = "";
    void insert(string s, int len){
        int u = 0;
        for(int i = 0; s[i]; ++i){
            int id = s[i] - 'a';
            if(!ch[u][id]) ch[u][id] = sz++;
            u = ch[u][id];
            ++cnt[u];
            if(cnt[u] == len) ans = s.substr(0, i + 1);
        }
    }
    string longestCommonPrefix(vector<string>& strs) {
        int len = strs.size();
        for(int i = 0; i < len; ++i)
            insert(strs[i], len);
        return ans;
    }
};

15 中等

Solution

  • 三指针
  • 排序后枚举固定最右侧,左侧两个位置用二分
  • set去重

Sample Code

class Solution {
public:
    set<vector<int>> resSet; 
    vector<vector<int>> threeSum(vector<int>& nums) {
        int len = nums.size();
        vector<vector<int>> res;
        if(len == 0) return res;
        quickSort(nums, 0, len - 1);
        for(int k = len - 1; k > 1; --k){
            int i = 0, j = k - 1;
            while(i < j){
                int v = nums[i] + nums[j] + nums[k];
                if(v == 0){
                    vector<int> candidate;
                    candidate.push_back(nums[i]);
                    candidate.push_back(nums[j]);
                    candidate.push_back(nums[k]);
                    resSet.insert(candidate);
                    if(nums[i] == nums[j]) break;
                    ++i;
                }
                if(v > 0) --j;
                if(v < 0) ++i;
            }
        }
        set<vector<int>>::iterator it;
        for(it = resSet.begin(); it != resSet.end(); ++it)
            res.push_back(*it);
        return res;
    }
    void quickSort(vector<int> & nums, int l, int r){
        if(l == r) return;
        int mid = pivot(nums, l, r);
        if(mid > l) quickSort(nums, l, mid - 1);
        if(mid < r) quickSort(nums, mid + 1, r);
    }
    int pivot(vector<int> & nums, int l, int r){
        int v = nums[l], pos = r;
        while(l < r){
            while(nums[r] >= v && r > l) --r;
            nums[l] = nums[r];
            while(nums[l] <= v && r > l) ++l;
            nums[r] = nums[l];
        }
        nums[l] = v;
        return l;
    }
};

16 中等

Solution

  • 二分

Sample Code

class Solution {
public:
    int Abs(int x){
        return x > 0 ? x : -x;
    }
    int threeSumClosest(vector<int>& nums, int target) {
        sort(nums.begin(), nums.end());
        int len = nums.size(); int res = 0x80000000;//稍远的值
        for(int i = 0; i < len - 2; ++i){
            int l = i + 1; int r = len - 1;
            while(l < r){
                int v = nums[i] + nums[l] + nums[r];
                if(v == target) return v;
                if(v < target) ++l;
                if(v > target) --r;
                if(res == 0x80000000) res = v;
                else if(Abs(v - target) < Abs(res - target))
                        res = v;
            }
        }
        return res;
    }
};

17 中等

Solution

  • dfs

Sample Code

string re[] = {"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
class Solution {
public:
    vector<string> letterCombinations(string digits) {
        vector<string> vecRes; if(digits == "") return vecRes;
        string res = ""; int len = digits.length();
        dfs(vecRes, res, digits, 0, len);
        return vecRes;
    }
    void dfs(vector<string> & vecRes, string res, string & str, int pos, int len){
        if(pos == len){
            vecRes.push_back(res);
            return;
        }
        int x = str[pos] - '0';
        for(int i = 0; re[x - 2][i]; ++i){
            res += re[x - 2][i];
            dfs(vecRes, res, str, pos + 1, len);
            res = res.substr(0, pos);
        }
        
    }
};

18 中等

Solution

  • 2sum, 3sum变种
  • 枚举两层 + 2sum

Sample Code

class Solution {
public:
    set<vector<int>> resSet;
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        int len = nums.size();
        vector<vector<int>> res;
        if(len == 0) return res;
        quickSort(nums, 0, len - 1);
        for(int k = len - 1; k > 2; --k){
            for(int h = k - 1; h > 1; --h){
                int i = 0, j = h - 1;
                while(i < j){
                    long long v = (long long)nums[i] + nums[j] + nums[k] + nums[h];
                    if(v == target){
                        vector<int> candidate;
                        candidate.push_back(nums[i]);
                        candidate.push_back(nums[j]);
                        candidate.push_back(nums[k]);
                        candidate.push_back(nums[h]);
                        resSet.insert(candidate);
                        if(nums[i] == nums[j]) break;
                        ++i;
                    }
                    if(v > target) --j;
                    if(v < target) ++i;
                }
            }
        }
        set<vector<int>>::iterator it;
        for(it = resSet.begin(); it != resSet.end(); ++it)
            res.push_back(*it);
        return res;
    }
    void quickSort(vector<int> & nums, int l, int r){
        if(l == r) return;
        int mid = pivot(nums, l, r);
        if(mid > l) quickSort(nums, l, mid - 1);
        if(mid < r) quickSort(nums, mid + 1, r);
    }
    int pivot(vector<int> & nums, int l, int r){
        int v = nums[l], pos = r;
        while(l < r){
            while(nums[r] >= v && r > l) --r;
            nums[l] = nums[r];
            while(nums[l] <= v && r > l) ++l;
            nums[r] = nums[l];
        }
        nums[l] = v;
        return l;
    }
};

19 中等

Solution

  • 双指针一趟遍历
  • 双指针差n个结点

Sample Code

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode * vHead = new ListNode(0, head);
        ListNode * p = vHead;
        ListNode * q = vHead;
        for(int i = 1; i <= n; ++i) q = q->next;
        while(q->next){
            p = p->next;
            q = q->next;
        }
        p->next = p->next->next;
        return vHead->next;
    }
};

20 简单

Solution

  • 栈应用

Sample Code

class Solution {
public:
    bool isRight(char ch){
        return ch == ')' || ch == '}' || ch == ']';
    }
    bool isMapping(char l, char r){
        if(r == ')') return l == '(';
        if(r == ']') return l == '[';
        if(r == '}') return l == '{';
        return false;
    }
    bool isValid(string s) {
        stack<char> sta;
        for(int i = 0; s[i]; ++i){
            if(isRight(s[i])){
                if(!sta.empty() && isMapping(sta.top(), s[i]))
                    sta.pop();
                else return false;
            }
            else sta.push(s[i]);
        }
        return sta.empty();
    }
};
不忘初心
原文地址:https://www.cnblogs.com/CodingDreamer/p/15294017.html