当前位置: 首页 > news >正文

STL——map和set【map和set的介绍和使用】【multimap和multiset】

目录

  • map和set
    • 1.关联式容器
    • 2.键值对
    • 3.树形结构的关联式容器
      • 3.1set
        • 3.1.1set的介绍
        • 3.1.2set的使用
          • 3.1.2.1set的模版参数列表
          • 3.1.2.2set的构造
          • 3.1.2.3set的迭代器
          • 3.1.2.4set基本接口的使用
          • 3.1.2.5set使用案例
      • 3.2map
        • 3.2.1map介绍
        • 3.2.2map的使用
          • 3.2.2.1map的构造
          • 3.2.2.2map的迭代器
          • 3.2.2.3map的容量与访问
            • []的使用和原理
          • 3.2.2.4map的基础接口的使用
          • 3.2.2.5map的使用案例
          • 3.2.2.6map的总结
      • 3.3multiset
        • 3.3.1multiset的介绍
        • 3.3.2multiset的使用
      • 3.4multimap
        • 3.4.1multimap的介绍
        • 3.4.2multimap的使用
    • 4.有关map和set的oj
      • 4.1前K个高频单词
      • 4.2两个数组的交集

map和set

在学习map和set之前,要先铺垫一下二叉搜索树。算是有个小基础。

1.关联式容器

STL中的部分容器,比如:vector、list、deque、forward_list(C++11)等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。

那什么是关联式容器?它与序列式容器有什么区别?

关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是<key, value>结构的键值对,在数据检索时比序列式容器效率更高

2.键值对

用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息

在前面学习二叉搜索树的时候,已经接触过KV模型的二叉搜索树了。

SGI-STL中关于键值对的定义:

template <class T1, class T2>
struct pair
{typedef T1 first_type;typedef T2 second_type;T1 first;T2 second;pair(): first(T1()), second(T2()){}pair(const T1& a, const T2& b): first(a), second(b){}
};

3.树形结构的关联式容器

3.1set

3.1.1set的介绍

set的文档介绍

主要使用的一些成员函数,迭代器,接口

image-20240924183305651

image-20240924183325546

image-20240924183336339

总结:

  1. set是按照一定次序存储元素的容器

  2. 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。

  3. 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序。

  4. set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代。

  5. set在底层是用二叉搜索树(红黑树)实现的。

注意:

  1. 与map/multimap不同,map/multimap中存储的是真正的键值对<key, value>,set中只放value,但在底层实际存放的是由<value, value>构成的键值对。

  2. set中插入元素时,只需要插入value即可,不需要构造键值对。

  3. set中的元素不可以重复(因此可以使用set进行去重)。

  4. 使用set的迭代器遍历set中的元素,可以得到有序序列

  5. set中的元素默认按照小于来比较

  6. set中查找某个元素,时间复杂度为:O(log_2 n)

  7. set中的元素不允许修改(为什么?)[二叉搜索树不允许数据重复]

  8. set中的底层使用二叉搜索树(红黑树)来实现

3.1.2set的使用
3.1.2.1set的模版参数列表

image-20240924211804476

T: set中存放元素的类型,实际在底层存储<value, value>的键值对。

Compare:set中元素默认按照小于来比较

Alloc:set中元素空间的管理方式,使用STL提供的空间配置器管理

注意:

前面已经学习过很多的容器了,对其构造函数,迭代器,基本接口的使用都很熟悉了,这里不再一个一个详细的说明如何使用了

3.1.2.2set的构造

image-20240924211927155

3.1.2.3set的迭代器

image-20240924212119940

3.1.2.4set基本接口的使用

image-20240924212240912

这里要特别说明的是find:

iterator find ( const key_type& x ) const

功能:找到set中 x的位置。

这里除了set容器自带的find,在算法部分还有一个find,这两个find都能直线找到x的位置,但是不一样的是时间复杂度

set容器的find接口,时间复杂度是O(logN)

算法模块里的find接口,时间复杂度是O(N)

3.1.2.5set使用案例

这里使用的都是一些需要注意的,其他接口都是大差不差的。

void test_set01()
{set<int> s;s.insert(1);s.insert(2);s.insert(5);s.insert(7);s.insert(5); // 这个5是无法插入set的,因为二叉搜索树不允许数据重复。// 这个迭代的过程其实就是中序遍历set<int>::iterator it = s.begin();while (it != s.end()){cout << *it << ' '; // 1 2 5 7  ++it;}cout << endl;// 这里这个find如果找不到返回的是迭代器的末尾 也就是 s.end()//set<int>::iterator pos = find(s.begin(), s.end(), 2); // 时间复杂度O(N)set<int>::iterator pos = s.find(20); // 这个是set容器的接口,时间复杂度是O(logN)if (pos != s.end()){s.erase(pos);}s.erase(5);s.erase(9); // 找不到不会进行操作// 只要支持迭代器,就可以支持范围forfor (auto& e : s){cout << e << " ";}cout << endl;
}

3.2map

3.2.1map介绍

map文档介绍

总结:

  1. map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素。

  2. 在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型value_type绑定在一起,为其取别名称为pair: typedef pair<const key, T> value_type;

  3. 在内部,map中的元素总是按照键值key进行比较排序的。

  4. map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。

  5. map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。

  6. map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))。

3.2.2map的使用

image-20240925000829839

key: 键值对中key的类型

T: 键值对中value的类型

Compare: 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)

**Alloc:**通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器

3.2.2.1map的构造

image-20240925000949387

3.2.2.2map的迭代器

这里迭代器也是以中序遍历来迭代map的

image-20240925001006200

3.2.2.3map的容量与访问

image-20240925001033792

[]的使用和原理

先来看一个[]的应用场景——统计次数

// 统计次数还有更简洁的写法
void test_map04()
{string strArr[] = { "苹果", "苹果", "苹果", "苹果", "苹果", "橘子", "橘子", "橘子", "香蕉" };map<string, int> countMap;for (auto& str : strArr){// 找str这个key是否存在,存在就让对应的value++,找不到就插入countMap[str]++; // 这里用方括号可以直接实现,相当于调用的下面那句话//(*((this->insert(make_pair(str, mapped_type()))).first)).second}// 输出统计好的次数for (auto& e : countMap){cout << e.first << "出现次数的" << ":" << e.second << endl;}cout << endl;
}

在调用[]的时候实际上是调用(*((this->insert(make_pair(k, mapped_type()))).first)).second

image-20240925120935960

因此要想搞懂[]的使用就要先搞定insert的使用:

image-20240925122807565

插入的时候要给一个value_type,这个类型是键值对类型,mapped_type才是value的类型

image-20240925122632309

除了看函数参数列表,还得看返回值,这里有一个返回值是pair<iterator,bool>,插入失败不应该返回false,成功返回true吗,给一个pair类型是什么意思呢?

返回值的解释如下:

image-20240925123536420

意思就是这里返回的pair类型,first是key,这里设置成iterator类型,意味着,这里的迭代器要不指向新插入的节点,要不指向已经存在于map的那个节点。second是value,这里设置成bool类型,代表是否成功插入,成功插入就是true,插入失败就是false。【这个时候迭代器就指向map中已经存在的节点,因为插入失败代表map,已经存在所要插入的数据的】

现在我们尝试调用insert来实现上面[]实现的功能:

// 统计次数还有更简洁的写法
void test_map04()
{string strArr[] = { "苹果", "苹果", "苹果", "苹果", "苹果", "橘子", "橘子", "橘子", "香蕉" };map<string, int> countMap;for (auto& str : strArr){// 找str这个key是否存在,存在就让对应的value++,找不到就插入//countMap[str]++; // 这里用方括号可以直接实现,相当于调用的下面那句话//(*((this->insert(make_pair(str, mapped_type()))).first)).second// 了解如何调用insert实现的pair<map<string, int>::iterator, bool> ret = countMap.insert(make_pair(str, 1));// 这里这个insert的过程自动就帮我们筛选了 str这个key是否存在于map中,insert返回一个pair类型// 我们通过pair这个类型来获取,str是否插入map中if (ret.second == false) {// bool为假说明插入失败,key已经存在于map中//(*ret.first).second++; // 就通过迭代器找到该节点,在将该节点的second++,也就是出现的次数++ret.first->second++; // 等价于(*ret.first).second++;}else{// bool为真,说明插入成功,不做处理。这个else分支不写都行,这里写出来方便理解}}// 输出统计好的次数for (auto& e : countMap){cout << e.first << "出现次数的" << ":" << e.second << endl;}cout << endl;
}

image-20240925125957116

在了解了insert的返回值pair的使用之后,我们就能理解[]的原理了:

mapped_type& operator[] (const key_type& k)
{(*((this->insert(make_pair(k, mapped_type()))).first)).second
}

image-20240925132739419

了解了[]的原理之后,我们来解析一下统计次数场景中使用的[]是如何实现统计次数的:

// 解析[]如何实现需求
void test_map05()
{string strArr[] = { "苹果", "苹果", "苹果", "苹果", "苹果", "橘子", "橘子", "橘子", "香蕉" };map<string, int> countMap;for (auto& str : strArr){countMap[str]++; // 1. 如果str这个k不存在于countMap中,那就插入pair<str, int()>,也就是pair<str, 0>// 在通过insert返回的pair类型,拿到插入的节点的迭代器,通过迭代器拿到出现的次数,进行++,此时存储的就是pair<str, 1>// 2. 如果str这个k存在于countMap中,就通过insert返回的pair类型,拿到该k的节点的迭代器// 在通过该迭代器拿到节点的value。也就是出现次数进行++。}// 输出统计好的次数for (auto& e : countMap)// 这里的auto是pair<const string, int>{cout << e.first << "出现次数的" << ":" << e.second << endl;}cout << endl;
}

总结:

  • map的operator[]的三层作用:
  1. 插入不存在的k和v
  2. 查找k对应的映射对象
  3. 修改k对应的映射对象

这也能解释为什么[]的底层原理是用insert来实现的。因为这样才能实现这三层作用

注意:在元素访问时,有一个与operator[]类似的操作at()(该函数不常用)函数,都是通过key找到与key对应的value然后返回其引用,不同的是:当key不存在时,operator[]用默认value与key构造键值对然后插入,返回该默认value,at()函数直接抛异常

3.2.2.4map的基础接口的使用

image-20240925002645275

这里需要讲一下map和set的区别。

在使用insert的时候要注意,因为map是KV模型的平衡二叉搜索树,因此,插入的时候要插入一个键值对。在cpp是一个类型,pair类型,是一个类模版。

image-20240925002827513

为什么呢?

其实结合迭代器会更好的理解。cpp函数仅支持一个返回值,意味着迭代器只能返回一个键值对pair。不能返回一个key和一个value。

void test_map01()
{map<int, int> m;//m.insert(1, 1); // 这样是不行的。 m.insert(pair<int, int>(1, 4));// 这里是通过匿名对象,调用构造函数m.insert(pair<int, int>(3, 3));m.insert(pair<int, int>(2, 2));m.insert(make_pair(5, 8)); // 通过函数模版,构造一个pair类型的对象map<int, int>::iterator it = m.begin();while (it != m.end()){//cout << *it << " "; // 这样也是不行的,因为map是KV模型的搜索二叉树// 返回一个节点的内容应该是既有key,也有value,但是cpp只支持返回值是一个// 这样也解释了为什么insert的时候要插入pair类型//cout << (*it).first << ":" << (*it).second << endl; // 实际不怎么用这个cout << it->first << ":" << it->second << endl; // 实际更用这个,这个编译器进行特殊处理了。本来是it->->second的++it;}cout << endl;map<int, int>::iterator pos = m.find(1); // 这里找的是key,而不是valueif (pos != m.end()){m.erase(pos);}// 支持迭代器就支持范围forfor (auto& e : m)// 这里的auto是pair<const string, int>{cout << e.first << ":" << e.second << endl;}cout << endl;
}

实际中更喜欢用make_pair来构造键值对参数,因为这里不需要传模版参数。会自动推导模版参数

image-20240925005028656

3.2.2.5map的使用案例

这里来一个模拟工程环境的代码:

// 这里来一个模拟工程的场景
void test_map02()
{std::map<std::string, std::string> dict;dict.insert(pair<std::string, std::string>("sort", "排序"));dict.insert(make_pair("string", "字符串"));std::map<std::string, std::string>::iterator it = dict.begin();while (it != dict.end()){cout << it->first << ":" << it->second << endl;++it;}cout << endl;}

image-20240925011051714

再来一个map的应用场景————统计次数:

// 再来一个map的应用场景————统计次数
void test_map03()
{string strArr[] = { "苹果", "苹果", "苹果", "苹果", "苹果", "橘子", "橘子", "橘子", "香蕉" };map<string, int> countMap;for (auto& str : strArr){// 找str这个key是否存在,存在就让对应的value++,找不到就插入map<string, int>::iterator pos = countMap.find(str);if (pos == countMap.end()){// 找不到就插入countMap.insert(make_pair(str, 1));}else{// 找到了就让出现次数++++pos->second;}}// 输出统计好的次数for (auto& e : countMap)// 这里的auto是pair<const string, int>{cout << e.first << "出现次数的" << ":" << e.second << endl;}cout << endl;
}

除了用上述方法,我们还可以直接使用[]来实现该场景.

[]的原理上面有讲

void test_map04()
{string strArr[] = { "苹果", "苹果", "苹果", "苹果", "苹果", "橘子", "橘子", "橘子", "香蕉" };map<string, int> countMap;for (auto& str : strArr){// 找str这个key是否存在,存在就让对应的value++,找不到就插入countMap[str]++; // 输出统计好的次数for (auto& e : countMap)// 这里的auto是pair<const string, int>{cout << e.first << "出现次数的" << ":" << e.second << endl;}cout << endl;
}

image-20240925011102987

3.2.2.6map的总结

对于map来说,是可以进行增删查改的,当然改的是v不是k

  1. 增 insert或者operator[]
  2. 删 erase
  3. 查 find 【也可以用[],但是不用[]。因为如果key不存在就会插入map中】
  4. 改 operator[]
  5. 遍历 iterator 或者范围for

map的总结:

  1. map中的的元素是键值对pair<key, value>,访问的时候要注意。

  2. map中的key是唯一的,并且不能修改

  3. 默认按照小于的方式对key进行比较

  4. map中的元素如果用迭代器去遍历,可以得到一个有序的序列

  5. map的底层为平衡搜索树(红黑树),查找效率比较高 O ( l o g 2 N ) O(log_2 N) O(log2N)

  6. 支持[]操作符,operator[]中实际进行插入查找

3.3multiset

3.3.1multiset的介绍

multiset的文档介绍

总结:

  1. multiset是按照特定顺序存储元素的容器,其中元素是可以重复的。

  2. 在multiset中,元素的value也会识别它(因为multiset中本身存储的就是<value, value>组成的键值对,因此value本身就是key,key就是value,类型为T). multiset元素的值不能在容器中进行修改(因为元素总是const的),但可以从容器中插入或删除。

  3. 在内部,multiset中的元素总是按照其内部比较规则(类型比较)所指示的特定严格弱排序准则进行排序。

  4. multiset容器通过key访问单个元素的速度通常比unordered_multiset容器慢,但当使用迭代器遍历时会得到一个有序序列。

  5. multiset底层结构为二叉搜索树(红黑树)。

注意:

  1. 与set的区别是,multiset中的元素可以重复(键值冗余),set是中value是唯一的

  2. 并且使用find在寻找相同的key的时候,会按照中序遍历的顺序去寻找

3.3.2multiset的使用

multiset和set的使用非常相似,这里就看看multiset和set不同的地方的使用就好了。

// 使用一下multiset
void test_multiset()
{// 和set区别就是允许键值冗余multiset<int> ms;ms.insert(3);ms.insert(1);ms.insert(4);ms.insert(2);ms.insert(6);ms.insert(3); //允许键值冗余// 再查找的时候,如果查找的数据是重复的,那找到的是中序遍历顺序的第一个。multiset<int>::iterator pos = ms.find(3); // 这里找到3是中序遍历顺序的第一个3multiset<int>::iterator it = ms.begin();while (it != ms.end()){cout << *it << " "; // 1 2 3 3 4 6it++;}cout << endl;set<int> s;s.insert(3);s.insert(1);s.insert(4);s.insert(2);s.insert(6);s.insert(3); //不允许键值冗余for (auto& e : s){cout << e << " "; // 1 2 3 4 6}cout << endl;
}

3.4multimap

3.4.1multimap的介绍

multimap的文档介绍

总结:

  1. Multimaps是关联式容器,它按照特定的顺序,存储由key和value映射成的键值对<key, value>,其中多个键值对之间的key是可以重复的。

  2. 在multimap中,通常按照key排序和惟一地标识元素,而映射的value存储与key关联的内容。key和value的类型可能不同,通过multimap内部的成员类型value_type组合在一起,value_type是组合key和value的键值对:typedef pair<const Key, T> value_type;

  3. 在内部,multimap中的元素总是通过其内部比较对象,按照指定的特定严格弱排序标准对key进行排序的。

  4. multimap通过key访问单个元素的速度通常比unordered_multimap容器慢,但是使用迭代器直接遍历multimap中的元素可以得到关于key有序的序列。

  5. multimap在底层用二叉搜索树(红黑树)来实现。

注意:

  1. multimap和map的区别就是map的key不能重复,multimap允许重复
  2. 还有一个multimap没有operator[]的存在,因为如果存在多个key,不知道返回那个key的value
3.4.2multimap的使用

同理,multimap和map的使用也是非常相似的,这里就只使用不同的地方、

void test_multimap()
{// multimap和map的区别和上面是一样的,也是允许键值冗余// 还有就是multimap没有operator[],因为当有多个key的时候,不知道返回那个key的valuemultimap<string, int> mmap;mmap.insert(pair<string, int>("苹果", 1));mmap.insert(pair<string, int>("苹果", 2));mmap.insert(make_pair("苹果", 3));for (auto& e : mmap){cout << e.first << ":" << e.second << endl;}cout << endl;
}

4.有关map和set的oj

4.1前K个高频单词

前K个高频单词

image-20240925204021342

思路1:

  • 优先级队列

先用一个map统计单词出现的次数,然后通过优先级队列搞一个小堆,转换为TopK问题。

注意:

这里在用优先级队列的时候,优先级队列要存储一个pair<string, int>类型,容器是vector<pair<string, int>>,并且由于pair类型无法进行大小比较,在插入进队列的时候无法保持堆的逻辑,因此需要为它专门弄个仿函数。

auto cmp = [](const pair<string, int>& a, const pair<string, int>& b) {return a.second == b.second ? a.first < b.first : a.second > b.second;};priority_queue<pair<string, int>, vector<pair<string, int>>, decltype(cmp)> que(cmp);

思路2:

  • 用map和multimap解决

思路在代码中有讲述:

class Solution {
public:vector<string> topKFrequent(vector<string>& words, int k) {vector<string> ret;// 通过map来统计单词出现的次数map<string, int> countMap;// 统计各单词出现的次数for(auto& str : words){countMap[str]++;              }/* // 方便调试for(auto& e : countMap){cout << e.first << ":" << e.second << endl;            }cout << endl;*/// 将单词出现的次数用multimap放起来,因为可能有多个重复key存在,用multimapmultimap<int, string, greater<int>> countSort;  // greater<int>导致中序遍历的结果是倒序。出现次数多的往左走,少的往右走for(auto& kv : countMap) //auto是pair<const string, int>{// 将各单词出现的次数进行排序countSort.insert(make_pair(kv.second, kv.first));//这里在插入的时候,是大的往左走}/* // 方便调试for(auto& e : countSort){cout << e.first << ":" << e.second << endl;            }cout << endl;*///将前k个出现次数最多的单词放到ret中for(auto& e : countSort) // pair<const int, const string>{ret.push_back(e.second);k--;if(k == 0)break;}return ret;}
};

4.2两个数组的交集

两个数组的交集 - (LeetCode)

image-20240925204128111

思路1:

将nums1和nums2分别装在一个set中,这里叫s1、s2、通过依次取出s1中的元素,去s2中寻找该元素是否存在,找到了就是交集元素

class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {vector<int> ret;// 用set解决, set的key不能重复set<int> s1; // s1用来装nums1中出现过的数字set<int> s2; // s2用来装nums2中出现过的数字for(int& e : nums1){s1.insert(e);}for(int& e : nums2){s2.insert(e);}// 这个时候s1装着nums1中出现过的数字,s2装着nums2出现过的数字for(auto& e : s1){// 取出s1中的元素,依次去寻找在s2中是否存在set<int>::iterator pos = s2.find(e);// 如果s2中存在。就说明是交集元素,放进ret中if(pos != s2.end()) // pos == s2.end()就说明没找到{ret.push_back(e);}}// 此时ret就装着交集元素return ret;}
};

思路2:

和思路1一样,但是在判断是否是交集元素的时候思路不一样。思路1通过寻找,这里我们通过比较的方式。我们让s1的元素去和s2的比较,只要发现相等的元素就一定是交集元素。

class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {vector<int> ret;// 用set解决, set的key不能重复set<int> s1; // s1用来装nums1中出现过的数字set<int> s2; // s2用来装nums2中出现过的数字for(int& e : nums1){s1.insert(e);}for(int& e : nums2){s2.insert(e);}// 除了寻找也可以通过比较的方式判断是否是交集元素// set排过序,依次比较,小的一定不是交集,相等的是交集auto it1 = s1.begin(); // auto就是set<int>::iteratorauto it2 = s2.begin();while(it1 != s1.end() && it2 != s2.end()){if(*it1 < *it2){it1++;}else if(*it2 < *it1){it2++;}else{ret.push_back(*it1);it1++;it2++;}}// 此时ret就装着交集元素return ret;}
};
    set<int> s2; // s2用来装nums2中出现过的数字for(int& e : nums1){s1.insert(e);}for(int& e : nums2){s2.insert(e);}// 除了寻找也可以通过比较的方式判断是否是交集元素// set排过序,依次比较,小的一定不是交集,相等的是交集auto it1 = s1.begin(); // auto就是set<int>::iteratorauto it2 = s2.begin();while(it1 != s1.end() && it2 != s2.end()){if(*it1 < *it2){it1++;}else if(*it2 < *it1){it2++;}else{ret.push_back(*it1);it1++;it2++;}}// 此时ret就装着交集元素return ret;}

};


相关文章:

STL——map和set【map和set的介绍和使用】【multimap和multiset】

目录 map和set1.关联式容器2.键值对3.树形结构的关联式容器3.1set3.1.1set的介绍3.1.2set的使用3.1.2.1set的模版参数列表3.1.2.2set的构造3.1.2.3set的迭代器3.1.2.4set基本接口的使用3.1.2.5set使用案例 3.2map3.2.1map介绍3.2.2map的使用3.2.2.1map的构造3.2.2.2map的迭代器…...

【笔记】神领物流配置本地hosts无法访问域名(排除DNS 排除文件编码问题)已解决

第一次看着文档准备项目 踩坑不少 一遇到问题总是想着先自己解决 其实文档里就有解决方法 看文字总是喜欢跳过 导入虚拟机的时候忘记了给它设置ip地址 按照文档来就好了 配置完之后立刻就可以通过域名访问了 以防万一写一个本地hosts文件的路径在这里 通常来说都是&#xff…...

Java | Leetcode Java题解之第424题替换后的最长重复字符

题目&#xff1a; 题解&#xff1a; public class Solution {public int characterReplacement(String s, int k) {int len s.length();if (len < 2) {return len;}char[] charArray s.toCharArray();int left 0;int right 0;int res 0;int maxCount 0;int[] freq n…...

Xcode 16 Pod init 报错

pod init failed in Xcode 16 Issue #12583 CocoaPods/CocoaPods GitHub 根据你提供的步骤&#xff0c;以下是详细的操作指南来解决 CocoaPods 的问题&#xff1a; ### 步骤 1&#xff1a;在 Xcode 中转换项目文件夹为组 1. 打开你的 Xcode 项目。 2. 在左侧的项目导航器…...

【数据结构】Java的HashMap 和 HashSet 大全笔记,写算法用到的时候翻一下,百度都省了!(实践篇)

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…...

Docker 教程:如何查看容器的最后 300 行实时日志

Docker 教程&#xff1a;如何查看容器的最后 300 行实时日志 文章目录 Docker 教程&#xff1a;如何查看容器的最后 300 行实时日志Docker 日志简介查看容器日志的基本命令查看最后 300 行实时日志的具体命令参数解释 实际案例演示示例输出 常见问题解答如何退出实时日志的查看…...

Qwen2-VL论文阅读笔记

第1章介绍 论文亮点&#xff1a; 1、 the Naive Dynamic Resolution mechanism 2、Multimodal Rotary Position Embedding (M-RoPE) 2D Rotary Position Embedding 3、统一图片和视频的处理范式、增i强视觉感知能力 4、LVLMs的scaling laws&#xff1a;2B、8B、72B 5、 dynamic…...

APScheduler、Django实现定时任务,以及任务动态操作

环境&#xff1a;Windows 11、python 3.12.3、Django 4.2.11、 APScheduler 3.10.4 背景&#xff1a;工作需要使用且用法较为复杂&#xff0c;各种功能基本都使用了 事件&#xff1a;20240920 说明&#xff1a;记录&#xff0c;方便后期自己查找 1、搭建基础环境 文件结构图…...

SpringBoot开发——整合Apache POI轻松生成精美的Excel报表

文章目录 1、准备工作2、编写代码2.1 创建实体类2.2 创建Excel生成服务2.3 创建控制器 3、测试4、结论 在许多企业应用程序中&#xff0c;导出数据到Excel表格是一项常见的需求。Spring Boot提供了许多库来简化这个过程&#xff0c;其中包括Apache POI和Spring Boot的相关模块。…...

海信智能电视的使用心得

买了海信智能电视(型号:32E2F)有一段时间了&#xff0c;要使用这个智能电视还真能考验你的智商。海信电视有很多优点&#xff0c;它的屏幕比较靓丽&#xff0c;色彩好看&#xff0c;遥控器不用对着屏幕就能操作。但也有不少缺点。 1. 海信智能电视会强迫自动更新操作系统&…...

【YashanDB知识库】客户端字符集与数据库字符集兼容问题

本文转自YashanDB官网&#xff0c;具体内容请见https://www.yashandb.com/newsinfo/7352675.html?templateId1718516 问题现象 客户端yasql配置字符集为GBK&#xff0c;服务端yasdb配置字符集为UTF8&#xff0c;之后执行语句&#xff1a; 会发现&#xff1a; 期望是两个都…...

Session和Cookie是什么?有什么区别?分布式Session问题又是什么?

Session和Cookie是什么&#xff1f;有什么区别&#xff1f;分布式Session问题又是什么&#xff1f; Cookie&#xff1a;是服务器发送到浏览器并保存在本地的数据。在浏览器下一次向同一服务器再次发送请求时&#xff0c;将Cookie也发送给服务器&#xff0c;并以此来判定这个请…...

项目实战:Qt+OSG爆破动力学仿真三维引擎测试工具v1.1.0(加载.K模型,子弹轨迹模拟动画,支持windows、linux、国产麒麟系统)

若该文为原创文章&#xff0c;转载请注明出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/142454993 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、Op…...

CSS开发全攻略

目录 一、CSS基础入门&#xff08;一&#xff09;CSS概述1.CSS的定义与作用2.CSS的历史与发展3.CSS的核心概念&#xff08;1&#xff09;选择器&#xff08;Selector&#xff09;&#xff08;2&#xff09;声明&#xff08;Declaration&#xff09;&#xff08;3&#xff09;规…...

OpenCV运动分析和目标跟踪(3)计算图像序列的加权平均值函数accumulateWeighted()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 更新一个运行平均值。 该函数计算输入图像 src 和累积器 dst 的加权和&#xff0c;使得 dst 成为帧序列的运行平均值&#xff1a; dst ( x , y…...

vue3中echarts柱状图横轴文字太多放不下怎么解决

问题&#xff1a;在做数据展示的时候&#xff0c;使用的是echarts&#xff0c;遇到了个问题&#xff0c;就是数据过多&#xff0c;但是设置的x轴的文字名称又太长&#xff0c;往往左边第一个或右边最后一个的名称展示不全&#xff0c;只有半个。 从网上找到了几种办法&#xff…...

Web 开发安全与最佳实践:MVC、会话管理与常见攻击防御

1. 引言 随着 Web 应用的普及&#xff0c;安全问题变得尤为重要。从小型个人网站到复杂的企业级系统&#xff0c;安全漏洞可能导致数据泄露、服务中断甚至经济损失。因此&#xff0c;在 Web 开发中&#xff0c;采用良好的架构设计、会话管理和安全防护机制至关重要。本文将探讨…...

Segformer双显卡推理速度测试

1、4080单显卡和双显卡同步并行推理平均耗时分别为360ms、600ms;双显卡速度明显比单显卡的速度快 2、两个相机间隔500ms的并行推理耗时&#xff0c;单双显卡推理平均耗时为340ms 3、4080双显卡和4070双显卡同步并行推理平均耗时分别为360ms、380ms;4080比4070的速度快20ms...

使用在线电子模拟器 Wokwi 运行 ESP32 示例(Arduino IDE、ESP32C3)

文章目录 Wokwi安装客户端&#xff08;Mac/Linux&#xff09;创建 Token ESP32C3 示例demo.ino创建模拟器运行模拟器 Wokwi Wokwi 是一款在线电子模拟器。您可以使用它来模拟 Arduino、ESP32、STM32 以及许多其他流行的主板、部件和传感器。 Github&#xff1a; https://gith…...

vue3+element-plus icons图标选择组件封装

一、最终效果 二、参数配置 1、代码示例 <t-select-icon v-model"selectVlaue" />2、配置参数&#xff08;Attributes&#xff09;继承 el-input Attributes 参数说明类型默认值v-model绑定值string-prefixIcon输入框前缀iconstringSearchisShowSearch是否显…...

Spring validation校验框架

第1步&#xff1a;导入依赖 <!-- 校验框架--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId> </dependency> 第2步&#xff1a;为需要校验的参数&…...

UBUNTU20.04安装CH384串口卡驱动

继续上文&#xff1a;统信UOS安装CH384串口卡驱动-CSDN博客 统信UOS系统成功安装CH384串口驱动后&#xff0c;继续在ubuntu20.04下安装驱动&#xff0c;发现一直报错&#xff0c;原因是内核驱动不一致。 解决办法&#xff1a; 1. 下载最新的驱动。CH35XCH384驱动源文件资源-C…...

JWT(JSON Web Tokens) 详细介绍

文章目录 什么是JWT?JWT的组成部分JWT的使用场景优点缺点 Java中如何实现JWT编解码引入JJWT依赖编码JWT解码JWT使用示例 什么是JWT? JWT&#xff08;JSON Web Tokens&#xff09;是一种用于双方之间安全传输信息的简洁的、URL安全的令牌标准。JWT可以传递信息&#xff0c;这…...

数据结构练习题————(二叉树)——考前必备合集!

今天在牛客网和力扣上带来了数据结构中二叉树的进阶练习题 1.二叉搜索树与双向链表———二叉搜索树与双向链表_牛客题霸_牛客网 (nowcoder.com) 2.二叉树遍历————二叉树遍历_牛客题霸_牛客网 (nowcoder.com) 3.二叉树的层序遍历————102. 二叉树的层序遍历 - 力扣&am…...

一天认识一个硬件之鼠标

今天来给大家分享一下鼠标的相关内容&#xff0c;先来分享一下什么是鼠标&#xff1a; 鼠标是一种计算机输入设备&#xff0c;用于控制屏幕上的光标移动和进行各种操作。它最早由道格拉斯恩格尔巴特在1963年发明&#xff0c;并在1968年12月9日制成了世界上第一个鼠标。介绍完了…...

Django 请求配置

http请求配置 请求流程 urls.py配置 from first_app import viewsurlpatterns [path(admin/, admin.site.urls),path(test/,views.first_test), ] views.py配置 from django.shortcuts import render,HttpResponse# Create your views here. def first_test(request):prin…...

轮播图组件更加完善版

依然是基于微博语法开发&#xff0c;使用时请注意标签替换 优化了滑动的效果&#xff0c;默认的索引&#xff0c;滑动距离等&#xff0c; 使用方式和以前一样没变&#xff0c;主要修改了组件内部 <template><wbx-view class"" style"width: 100vw;heig…...

cpu路、核、线程

路&#xff1a;主板插口实际插入的 CPU 个数&#xff0c;也可以理解为主板上支持的CPU的数量。每个CPU插槽可以插入一个物理处理器芯片。例如&#xff0c;一台服务器可能有2路或4路插槽&#xff0c;这意味着它最多可以安装2个或4个物理处理器。 核&#xff1a;单块 CPU 上面能…...

鸿蒙开发(NEXT/API 12)【硬件(注册出行业务事件监听)】车载系统

注册出行业务事件监听&#xff0c;用于接收业务发送事件的通知。 接口说明 接口名描述[on] (type: ‘smartMobilityEvent’, smartMobilityTypes: SmartMobilityType[],callback: Callback): void应用注册出行业务事件监听。 开发步骤 导入Car Kit模块。 import { smartMobi…...

安卓中有main函数吗?

在标准的Android应用程序开发中&#xff0c;并不直接使用类似于传统Java或C程序中的main函数入口点。Android应用程序是基于组件的架构&#xff0c;它依赖于几个关键组件来执行不同的任务&#xff0c;这些组件包括Activity、Service、Broadcast Receiver和Content Provider。 …...