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;
    }

【回见】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值