11 中等
Solution
-
用i, j(i < j)表示选取的两条线位置, 则水量为((j - i)* min(a_j, a_i))
-
我们考虑固定选取的右侧j, 则左侧可选为1...j - 1
-
设(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更优
-
当前位置左侧位置高度均小于当前位置时,当考虑其右侧的位置的左边界时,当前位置时有效候选,无法直接丢弃
-
根据以上,可以枚举右侧的j, 左边界用候选集,更新res, 同时更新候选集
-
判断左侧高度是否有不小于当前的,用树状数组即可
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();
}
};