前言
欢迎大家积极在评论区留言发表自己的看法,知无不言,言无不尽,养成每天刷题的习惯,也可以自己发布优质的解题报告,供社区一同鉴赏,吸引一波自己的核心粉丝。
今天是六月集训第二十二天:有序集合🔥🔥🔥🔥🔥
一、练习题目
二、算法思路
- 1、732. 我的日程安排表 III:🔥🔥🔥 利用差分的思想来做,这题一下子理解不了的可以先做729. 我的日程安排表 I和731. 我的日程安排表 II,做完这两道加深理解再回到咱这个困难题,你会发现一招鲜吃遍天。
1.差分数组的定义
假设有数组A,我们将数组A中的每一项与前一项的差值组成的新数组F称为差分数组。对于F显然有:
F [ i ] = { A [ i ] ( i = 0 ) A [ i ] − A [ i − 1 ] ( i > 0 ) F[i]=\begin{cases} A[i](i=0)\\ A[i]-A[i -1](i >0)\end{cases} F[i]={A[i](i=0)A[i]−A[i−1](i>0)
举例:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
---|---|---|---|---|---|---|---|---|
A[i] | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 |
F[i] | 100 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
2.差分数组特性
计算数列各项的值
:数列第i项的值是可以用差分数组的前i项和计算得到,即前缀和。
A
[
i
]
=
F
[
i
]
+
A
[
i
−
1
]
A[i] = F[i] + A[i-1]
A[i]=F[i]+A[i−1]
快速执行区间的加减操作
:比如数组A的1~5项都增加1:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
---|---|---|---|---|---|---|---|---|
A[i] | 101 | 102 | 103 | 104 | 105 | 106 | 106 | 107 |
F[i] | 100 | 2 | 1 | 1 | 1 | 1 | 1 | 1 |
可以发现规律了,差分数组F只改变了两边端点的值,在左闭右开的区间内,即上面的例子是:[1,6),起始端点加1,结尾端减1。
3.差分数组应用
结合此题来进行说明:我们要为每一个日期进行安排,每个日期安排的数组数量表示为数组A,F表示差分数组。
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
---|---|---|---|---|---|---|---|---|
A[i] | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
F[i] | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
执行A(1,5)后,根据题意start=1,end=5:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
---|---|---|---|---|---|---|---|---|
A[i] | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
F[i] | 1 | 0 | 0 | 0 | -1 | 0 | 0 | 0 |
可以发现规律了,差分数组F只改变了两边端点的值,在左闭右开的区间内,即上面的例子是:[1,5),起始端点加1,结尾端减1。
-
2、895. 最大频率栈:🔥🔥🔥🔥 用两个表,一个存放数据出现的频率,另一个存放每个频率下面的栈。
-
3、352. 将数据流变为多个不相交区间:🔥🔥🔥🔥🔥
三、源码剖析
// 729. 我的日程安排表 I
class MyCalendar {
map<int, int> cnt;
public:
MyCalendar() {
cnt.clear();
}
bool book(int start, int end) {
cnt[start]++;
cnt[end]--;
int sum = 0;
for(auto iter = cnt.begin(); iter != cnt.end(); ++iter) {
sum += iter->second;
if(sum > 1) {
cnt[start]--;
cnt[end]++;
return false;
}
}
return true;
}
};
// 731. 我的日程安排表 II
class MyCalendarTwo {
map<int, int> cnt;
public:
MyCalendarTwo() {
cnt.clear();
}
bool book(int start, int end) {
++cnt[start];
--cnt[end];
int sum = 0;
for(auto i : cnt) {
sum += i.second;
if(sum > 2) {
--cnt[start];
++cnt[end];
return false;
}
}
return true;
}
};
// 732. 我的日程安排表 III
class MyCalendarThree {
map<int, int> cnt;
public:
MyCalendarThree() {
cnt.clear();
}
int book(int start, int end) {
++cnt[start];
--cnt[end];
int sum = 0, maxv = 0;
for(auto i : cnt) {
sum += i.second;
maxv = max(maxv, sum);
}
return maxv;
}
};
- 1、看思路详解。
// 895. 最大频率栈
class FreqStack {
unordered_map<int, int> freq;
unordered_map<int , stack<int>> freq2stk;
int maxfreq;
public:
FreqStack() {
freq.clear();
freq2stk.clear();
maxfreq = 0;
}
void push(int val) {
freq[val]++;
if(freq[val] > maxfreq) {
maxfreq = freq[val];
}
freq2stk[freq[val]].push(val);
}
int pop() {
int val = freq2stk[maxfreq].top();
freq2stk[maxfreq].pop();
freq[val]--;
if(!freq2stk[maxfreq].size()) {
maxfreq--;
}
return val;
}
};
- 1、看思路详解。
// 352. 将数据流变为多个不相交区间
- 1、