日期:20220911
链接:https://leetcode.cn/contest/weekly-contest-310/
次数相等时选最小的数。因为这个WA一次
class Solution {
public:
int mostFrequentEven(vector& nums) {
unordered_map ct;
int ret = -1, m = 0;
for (auto c: nums) {
if (c % 2) continue;
ct[c]++;
if (ct[c] > m) {
m = ct[c];
ret = c;
} else if (ct[c] == m && c < ret) {
ret = c;
}
}
return ret;
}
};
直接贪心就行。
class Solution {
public:
int partitionString(string s) {
unordered_map dict;
int cnt = 0;
for (int i = 0, j = 0; i <= s.size(); i++) {
char c = s[i];
if (dict[c] > 0) {
cnt++;
dict.clear();
}
dict[c]++;
}
return cnt + 1;
}
};
看到一个大神的答案。可以用bitset来做。
第二次写,双指针更熟练了。
class Solution {
public:
int partitionString(string s) {
int n = s.size(), cnt = 0;
vector wd(26);
for (int i = 0, j = 0; i < n; i = j) {
while (j < n && wd[s[j] - 'a'] == 0) {
wd[s[j++] - 'a']++;
}
cnt++;
for (int i = 0; i < 26; i++) wd[i] = 0;
}
return cnt;
}
};
这题,没做出来。。。很郁闷。想着是贪心,按顺序排序后,一遍一遍的尽可能多的把所有不重叠的区间选完。
但是33个样例,是重复的得用multiset的过。换成multiset后,34个又不过。
看答案是用区间覆盖来做。某个区间最多被覆盖多少次,就需要分多少组。所以通过差分数组,可以统计每一个区间中的数字被覆盖了多少次。
class Solution {
public:
int minGroups(vector>& intervals) {
int n = intervals.size();
vector diff(1000005);
for (auto &vc : intervals) {
diff[vc[0]]++;
diff[vc[1] + 1]--;
}
int res = diff.front();
for (int i = 1; i <= 1000000; i++) {
diff[i] += diff[i - 1];
res = max(res, diff[i]);
}
return res;
}
};
第二次实现,开始还是超时了。快速敏锐的想到用 multiset 来做,然后通过了。还是第一种差分的方式好,但是难想。
事实上,完全可以用优先队列来做,因为优先队列也允许重复。
class Solution {
public:
int minGroups(vector>& intervals) {
int n = intervals.size(), cnt = 0;
sort(intervals.begin(), intervals.end());
multiset sset;
for (auto &p : intervals) {
if (sset.empty() || *sset.begin() >= p[0]) {
sset.insert(p[1]);
} else {
int x = *sset.begin();
sset.erase(sset.begin());
sset.insert(p[1]);
}
}
return sset.size();
}
};
// 优先队列版
class Solution {
public:
int minGroups(vector>& intervals) {
int n = intervals.size(), cnt = 0;
sort(intervals.begin(), intervals.end());
priority_queue, greater> que;
for (auto &p : intervals) {
if (que.empty() || que.top() >= p[0]) {
que.push(p[1]);
} else {
int x = que.top();
que.pop();
que.push(p[1]);
}
}
return que.size();
}
};
这里开了一个100w大小的数组,MB级别的。
典型的动态规划。
f
(
i
)
f(i)
f(i) 表示,以索引
i
i
i 结尾的子序列,最长是多少。对于
f
(
i
)
f(i)
f(i) ,我们要找到
j
j
j,满足
j
<
i
j < i
j<i,并且
n
u
m
s
[
i
]
−
k
≤
n
u
m
s
[
j
]
<
n
u
m
s
[
i
]
nums[i] - k \le nums[j] < nums[i]
nums[i]−k≤nums[j]<nums[i]
的最大的
f
[
j
]
f[j]
f[j]。如果这样做,每次转移需要遍历
[
0
,
i
)
[0, i)
[0,i) 就是
O
(
n
2
)
O(n^2)
O(n2) 的复杂度,肯定过不了。
可以转化思维:找索引
j
j
j 我求不了,干脆我直接求
n
u
m
s
[
j
]
nums[j]
nums[j] 值得范围得了。直接找
[
n
u
m
s
[
i
]
−
k
,
n
u
m
s
[
i
]
−
1
]
[nums[i] - k, nums[i] - 1]
[nums[i]−k,nums[i]−1] 这个区间的最大值。反正 nums[i] 的范围只有 10w。线段树搞定。
最近整理了线段树模板:
class SegmentTree {
public:
void init() {
_build_tree(1, 0, _n);
}
SegmentTree(int n) : _n(n), tree((n + 2) << 2) { }
void modify(int idx, int val) {
_modify(1, 0, _n, idx, val);
}
int query(int L, int R) {
return _query(1, 0, _n, L, R);
}
private:
void _build_tree(int root, int L, int R) {
if (L == R) {
// tree[root].max_num = arr[l];
return;
}
int mid = (L + R) >> 1;
_build_tree(root * 2, L, mid);
_build_tree(root * 2 + 1, mid + 1, R);
_update(root);
return ;
}
void _modify(int root, int rl, int rr, int idx, int val) {
if (rl == rr) {
tree[root] = val;
return;
}
int mid = (rl + rr) >> 1;
if (idx <= mid) {
_modify(root << 1, rl, mid, idx, val);
} else {
_modify(root << 1 | 1, mid + 1, rr, idx, val);
}
_update(root);
return ;
}
int _query(int root, int rl, int rr, int L, int R) {
if (rl >= L && rr <= R) {
return tree[root];
}
int ans = INT_MIN;
int mid = (rl + rr) >> 1;
if (mid >= L) {
ans = max(ans, _query(root << 1, rl, mid, L, R));
}
if (mid < R) {
ans = max(ans, _query(root << 1 | 1, mid + 1, rr, L, R));
}
return ans;
}
void _update(int root) {
tree[root] = max(tree[root << 1], tree[root << 1 | 1]);
return;
}
// default [0, n] root is 1;
int _n;
vector tree;
};
class Solution {
public:
int lengthOfLIS(vector& nums, int k) {
int n = nums.size();
vector f(n);
int res = 1;
SegmentTree sg(100000);
sg.init();
for (int i = 0; i < n; i++) {
int l = max(0, nums[i] - k), r = nums[i] - 1;
f[i] = sg.query(l, r) + 1;
sg.modify(nums[i], f[i]);
res = max(res, f[i]);
}
return res;
}
};