关于multimap的练习和two sum

本文介绍了一种利用C++ STL中的multimap来高效解决数组中寻找两个数使其和为目标值的问题的方法。通过使用multimap,可以将查找时间从O(n^2)降低到接近O(n log n)。文章提供了完整的代码示例,并展示了如何遍历和操作multimap。
#include <iostream>
#include <vector>
#include <stdio.h>
#include <map>
using namespace std;

class Solution {
public:
    vector<int> twoSum(vector<int> &numbers, int target)
    {
        vector<int> ret(2,0);

    }
};
int main()
{
    multimap<int,char*> m;
    //multimap的插入只能用insert()不能用数组
    //muiltmap 初始化操作和insert操作
    m.insert(pair<int,char*>(1,"apple"));
    m.insert(pair<int,char*>(1,"pear"));//apple和pear的价钱完全有可能是一样的
    m.insert(pair<int,char*>(2,"banana"));
    //m[1]="orange";  multimap没有下标运算
    //multimap的遍历只能用迭代器方式不能用数组
    cout<<"***************************************"<<endl;
    multimap<int,char*>::iterator i,iend;
    iend=m.end();
    for(i=m.begin();i!=iend;i++)
    {
        cout<<(*i).second<<"的价钱是"<<(*i).first<<"元/斤\n";
    }
    cout<<"***************************************"<<endl;
    //元素的反相遍历
    multimap<int,char*>::reverse_iterator j,jend;
    jend=m.rend();
    for(j=m.rbegin();j!=jend;j++)
    {
        cout<<(*j).second<<"的价钱是"<<(*j).first<<"元/斤\n";
    }
    cout<<"***************************************"<<endl;
 //元素的搜索find(),pair<iterator,iterator>equal_range(const key_type &k)const
    //和multiset的用法一样
    multimap<int,char*>::iterator s;
    s=m.find(1);//find()只要找到一个就行了,然后立即返回。
    cout<<(*s).second<<"    "<<(*s).first<<endl;
    cout<<"键值等于1的元素个数是:"<<m.count(1)<<endl;
    cout<<"***************************************"<<endl;
    //输出所以匹配项
    pair<multimap<int,char*>::iterator,multimap<int,char*>::iterator> range;
    range = m.equal_range(1);
    for(multimap<int,char*>::iterator it = range.first;it!=range.second;it++)
    cout<<it->second<<endl;
    cout<<"***************************************"<<endl;
    //删除 erase(),clear()
    m.erase(1);
    for(i=m.begin();i!=iend;i++)
    {
        cout<<(*i).second<<"的价钱是"<<(*i).first<<"元/斤\n";
    }
    return 0;
}


/*Given an array of integers, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.

You may assume that each input would have exactly one solution.*/
#include <iostream>
#include <vector>
#include <map>
#include<stdlib.h>
#include <algorithm>
using namespace std;

int numrand(int num)
{
    return rand()%num;
}
class Solution {
public:
    vector<int> twoSum(vector<int> &numbers, int target)
    {
        vector<int> ret(2,0);
        multimap<int,int> num;
        vector<int>::iterator vit;
        multimap<int,int>::iterator mmit,findn,it;
        int temp = 0;
        for(vit=numbers.begin();vit!=numbers.end();vit++,temp++)
        {
            num.insert(pair<int,int>(*vit,temp));
        }
        for(mmit=num.begin();mmit!=num.end();mmit++)
        {
            if((findn = num.find(target-(*mmit).first))!=num.end())
            {
                    if((*findn).first == (*mmit).first)
                    {
                        if(num.count((*mmit).first)>1)
                        {
                            pair<multimap<int,int>::iterator,multimap<int,int>::iterator> range;
                            range = num.equal_range((*mmit).first);
                            int i=0;
                            for(it=range.first;it!=range.second;it++)
                            {
                                ret[i]=it->second+1;
                                i=1;
                            }

                        }
                    }
                    else
                    {
                        ret[0]= mmit->second+1;
                        ret[1]= findn->second+1;
                    }

            }
        }
        if(ret[0]>ret[1])
        {
            temp=ret[0];
            ret[0]=ret[1];
            ret[1]=temp;
        }

        return ret;
    }
};
int main()
{
    vector<int> nrand(5,0);
    vector<int> ret;
    //for(int i=0;i<5;i++)
     //   nrand[i]=numrand(5);
   // for(int j=0;j<5;j++)
    //    cout<<nrand[j]<<" ";
    //cout<<endl;
    nrand[0]=0;
    nrand[1]=4;
    nrand[2]=3;
    nrand[3]=0;
    Solution *sou = new Solution;
    ret=sou->twoSum(nrand,0);
    cout<<ret[0]<<" "<<ret[1];
    return 0;
}
回顾:最开始用循环遍历的方法,复杂度为O(n*n),现在改用map的find函数,find是用二叉树实现的,所以复杂度为log(n);
遍历multimap,已自动按key的大小排序。



                
<think>好的,我现在需要回答用户关于multimapmultiset的底层实现原理及区别的问题。首先,我得仔细看看用户提供的引用内容,看看有没有相关的信息可以引用。 根据引用[2]引用[3],提到multimapmultiset属于树型结构的关联容器,底层使用红黑树实现。红黑树是一种平衡二叉搜索树,能够自动调整结构以保持平衡,这样插入、删除查找操作的时间复杂度都是O(log n)。multimapmultiset允许键重复,而mapset不允许,这也是它们的主要区别之一。 接下来,关于multimap的具体实现,引用[4]提到map中的键值对通过value_type绑定为pair类型,而multimap作为其允许重复键的版本,应该也是类似的实现。multiset则set类似,但允许重复元素存在。引用[5]还提到multimap的操作,如insert、erase等,这些操作在红黑树结构下如何实现可能需要进一步解释。 用户还问到底层实现的区别。需要强调两者虽然都是红黑树,但multimap存储的是键值对,而multiset只存储单个值。另外,两者的应用场景不同,比如multimap适合需要按键排序且允许重复键的情况,如事件调度;multiset适合需要有序且允许重复元素的集合,如成绩统计。 在用法上,引用[3]中的代码示例展示了如何使用multimap来按出现次数排序字符串,这可以作为一个例子说明multimap的插入遍历方法。而multiset的用法可能更直接,比如统计元素出现的次数,或者维护一个有序的重复元素集合。 需要注意用户可能对红黑树的具体实现细节不太熟悉,所以需要以简明的方式解释,避免过于技术化。同时,结合引用中的内容,确保信息准确,并适当标注引用来源。 最后,生成相关问题时要围绕底层原理、操作方法使用场景展开,帮助用户进一步理解这两个容器的特点应用。</think>### multimap与multiset的底层实现原理及区别 #### 一、底层实现原理 1. **数据结构基础** multimapmultiset均基于**红黑树**(平衡二叉搜索树)实现[^2]。红黑树通过自动平衡机制(颜色标记、旋转操作)保证插入、删除、查找操作的时间复杂度为$O(\log n)$,同时维护元素的有序性。 2. **multimap的实现特点** - 存储键值对`pair<const Key, Value>`,允许**重复的键**存在[^4]。 - 内部按键(Key)进行排序,排序规则可通过自定义比较函数指定。 - 示例:`multimap<int, string>`会将键相同的多个键值对按插入顺序排列[^3]。 3. **multiset的实现特点** - 存储单一元素(Value),允许**重复元素**存在。 - 元素本身即为排序依据,默认按升序排列。 - 示例:`multiset<int> {3,1,2,2}`会存储为有序序列`{1,2,2,3}`[^2]。 #### 二、核心区别 | 特性 | multimap | multiset | |---------------------|-----------------------------------|-------------------------| | **存储内容** | 键值对(Key-Value) | 单一元素(Value) | | **排序依据** | 键(Key) | 元素本身(Value) | | **重复性支持** | 允许重复键 | 允许重复元素 | | **典型操作** | 插入键值对、范围查询(equal_range)| 插入元素、统计出现次数 | #### 三、具体用法示例 1. **multimap的插入与遍历** ```cpp multimap<string, int> mmp; mmp.insert({"apple", 3}); mmp.insert({"apple", 5}); // 允许重复键 for (auto it = mmp.begin(); it != mmp.end(); ++it) { cout << it->first << ":" << it->second << endl; // 输出有序键值对 } ``` 2. **multiset的统计与删除** ```cpp multiset<int> ms = {2, 2, 3, 1}; ms.erase(2); // 删除所有值为2的元素 int count = ms.count(3); // 返回元素3的出现次数(1次) ``` #### 四、应用场景 - **multimap**:适用于需要按键排序且允许重复键的场景,如**事件调度系统**(同一时间点多个事件)[^3]。 - **multiset**:适合需要有序且允许重复元素的场景,如**成绩排名统计**(允许相同分数存在)[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值