记录一下该容器。主要是在做题时不想写太多代码。
set&multiset
一、作用和本质
[简介]:
所有元素都会在插入时自动被排序(默认为从小到大)
[本质]:
set/multiset属于关联式容器,底层结构是用二叉树实现。
[set和multiset区别]:
set不允许容器中有重复的元素
multiset允许容器中有重复的元素
二、封装的方法
1、头文件
#include<set>
2、方法展示
#include <set>
begin()/end()
begin():第一个元素的地址
rbegin():最后一个元素的地址
end(): 最后一个元素【再】后一个"位置"的地址
rend():第一个元素的地址
//打印输出
void printSet(set<int> & s)
{
for (set<int>::iterator it = s.begin(); it != s.end(); it++)
cout << *it << " ";
cout << endl;
}
【下面的api展示数据皆是看这里的内容】
insert(elem); //在容器中插入元素。
set<int> s1; s1.insert(10); s1.insert(30); s1.insert(20); //插入值
//自动排序 10 20 30
【下面的api展示数据皆是看这里的内容】
//拷贝构造
set<int>s2(s1); printSet(s2); //将s1的值全部克隆到s2
//赋值
set<int>s3; s3 = s2;
size(); //返回容器中元素的数目
s1.size(); //3
empty(); //判断容器是否为空
s1.empty();//false
swap(st); //交换两个集合容器
set<int>s2;s2.swap(s1);
clear(); //清除所有元素
s1.clear();//size()==0;
erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。
//想要删除s1中的10
s1.erase(s1.begin());//s1:20 30
erase(beg, end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
s1.erase(s1.begin(),s1.begin()+1);//s1: 30
erase(elem); //删除容器中值为elem的元素。
s1.erase(20);//s1:10 30
upper_bound(elem)//返回比elem大的元素的迭代器。
s1.upper_bound(5);//s1.begin()
find(key); //查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回
s1.find(10);//s1.begin()
count(key); //统计key的元素个数
s1.count(10);//1
3、改变自动排序的顺序(从大到小)
class test {
public:
bool operator()(int v1, int v2) //二元仿函数
{
return v1 > v2;
}
};
void main() {
set<int> s1;
s1.insert(10); s1.insert(40);
s1.insert(20); s1.insert(30);
s1.insert(50);
//默认从小到大
for (set<int>::iterator it = s1.begin(); it != s1.end(); it++)
{
cout << *it << " ";
}cout << endl;
//指定排序规则
set<int,test> s2; //利用仿函数排序
s2.insert(10);
s2.insert(40); s2.insert(20);
s2.insert(30); s2.insert(50);
for (set<int, test>::iterator it = s2.begin(); it != s2.end(); it++)
{
cout << *it << " ";
}
cout << endl;
system("pause");
return 0;
}
三、练习题
1)leetcode剑指 Offer 59 - I. 滑动窗口的最大值
给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。
示例:
输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
【我的思路】
用固定大小为k的窗口罩住,用数组放好子数组的元素。移动一步就将右边的元素替换左边的元素,并找到到最大的那个元素。
时间复杂度的高低基本在子数组中的最大元素的寻找。双队列,或是用数组循环判断(时间复杂度太高),又或是用三个int变量记录前三个最大的数并用遍历修正。但是我太懒了,想到了几行代码就可以的实现的容器multiset(自动排序,存储最后一个元素即可).
vector<int> maxSlidingWindow(vector<int> &nums, int k)
{
if (nums.size() == 0 || k == 0)
return nums;
int l = 0, r = k; //窗口的左右边界
multiset<int> ms;
vector<int> res;
for (int i = 0; i < r; i++) //预装ms,开始找第一组
ms.insert(nums[i]);
res.push_back(*ms.rbegin());
while (r < nums.size())
{
ms.insert(nums[r++]);
ms.erase(ms.find(nums[l++]));
res.push_back(*ms.rbegin());
}
return res;
}
2)456. 132 模式
给你一个整数数组 nums ,数组中共有 n 个整数。132 模式的子序列 由三个整数 nums[i]、nums[j] 和 nums[k] 组成,并同时满足:i < j < k 和 nums[i] < nums[k] < nums[j] 。
如果 nums 中存在 132 模式的子序列 ,返回 true ;否则,返回 false 。
示例 1:
输入:nums = [1,2,3,4]
输出:false
解释:序列中不存在 132 模式的子序列。
示例 2:
输入:nums = [3,1,4,2]
输出:true
解释:序列中有 1 个 132 模式的子序列: [1, 4, 2] 。
示例 3:
输入:nums = [-1,3,2,0]
输出:true
解释:序列中有 3 个 132 模式的的子序列:[-1, 3, 2]、[-1, 3, 0] 和 [-1, 2, 0] 。
提示:
n == nums.length
1 <= n <= 10^4
-10^9 <= nums[i] <= 10^9
将数组分为三个区域,分别是‘1’区域、‘2’区域、‘3’区域;‘1’区域中就找到最小的那个数为‘1’,‘3’区域慢慢一个一个遍历得到,‘2’区域即是出去’1‘、’2‘区域后的所有元素存进set容器中得到最大’1‘且小于’3‘的数.数组至少有三个元素,第一个元素先设为’1‘,第二个为’3‘,第三个到最后一个的元素的中得到’2‘;
bool find132pattern(vector<int> &nums)
{
if (nums.size() < 3)
return false;
int index = 1, left = nums[0];
multiset<int> ringht;
for (int i = index + 1; i < nums.size(); i++)
ringht.insert(nums[i]);
while (index < nums.size() - 1)
{
if (ringht.upper_bound(left) != ringht.end() && *ringht.upper_bound(left) < nums[index])
return true;
else
{
left = min(left, nums[index++]);
ringht.erase(ringht.find(nums[index]));
}
}
return false;
}
【回见】