連想コンテナ
map と setがデータを格納する場合、要素のキー (キー) が繰り返されないことを保証する必要があり、キーは昇順 (小さいものから大きいものへ) で並べ替えられます。要素を格納します。
セット内のキーと値が同じ (key=value)
. "キーと値のペア" は通常のデータ型ではありません. C++ STL 標準ライブラリはペア クラス テンプレートを提供します.これは 2 つの通常の要素を結合するために特別に使用されます. first と second (C++ 基本データ型、構造体、クラス定義型のいずれか) を使用して、新しい要素 <first, second> を作成します。ペア クラス テンプレートはヘッダー ファイルで定義されるため、クラス テンプレートを使用する前にこのヘッダー ファイルをインポートする必要があります。
C++ マップ コンテナーを作成するいくつかの方法:
1) 空のマップ コンテナーは、マップ コンテナー クラスの既定のコンストラクターを呼び出すことによって作成できます。次に例を示します。
std::map<std::string, int>myMap;
プログラムで std コマンド空間がデフォルトで指定されている場合、std:: はここで省略できます。
2) もちろん、マップ コンテナーの作成中に、次のように初期化することもできます。
std::map<std::string, int>myMap{
{
"C语言教程",10},{
"STL教程",20} };
したがって、myMap コンテナーには、初期状態で 2 つのキーと値のペアが含まれています。
繰り返しになりますが、マップ コンテナーに格納されているキーと値のペアは、基本的にペア クラス テンプレートによって作成されたペア オブジェクトです。したがって、次のプログラムでもまったく同じ myMap コンテナーを作成できます。
std::map<std::string, int>myMap{
std::make_pair("C语言教程",10),std::make_pair("STL教程",20)};
さらに、一部のシナリオでは、以前に作成したマップ コンテナーを使用して、新しいマップ コンテナーを作成できます。例えば:
std::map<std::string, int>newMap(myMap);
したがって、マップ コンテナーのコピー (複製) コンストラクターを呼び出すことで、myMap とまったく同じ newMap コンテナーを正常に作成できます。
もちろん、上記のマップ コンテナーの作成に基づいて、マップ コンテナーの並べ替えルールを手動で変更できます。デフォルトでは、マップ コンテナーは std::less ルールを呼び出して、コンテナー内の各キーと値のペアのキー サイズに従って、すべてのキーと値のペアを昇順に並べ替えます。
http://c.biancheng.net/view/7173.html
#include <iostream>
#include <map> // map
#include <string> // string
using namespace std;
int main() {
//创建空 map 容器,默认根据个键值对中键的值,对键值对做降序排序
std::map<std::string, std::string, std::greater<std::string>>myMap;
//调用 emplace() 方法,直接向 myMap 容器中指定位置构造新键值对
myMap.emplace("C语言教程","http://c.biancheng.net/c/");
myMap.emplace("Python教程", "http://c.biancheng.net/python/");
myMap.emplace("STL教程", "http://c.biancheng.net/stl/");
//输出当前 myMap 容器存储键值对的个数
cout << "myMap size==" << myMap.size() << endl;
//判断当前 myMap 容器是否为空
if (!myMap.empty()) {
//借助 myMap 容器迭代器,将该容器的键值对逐个输出
for (auto i = myMap.begin(); i != myMap.end(); ++i) {
cout << i->first << " " << i->second << endl;
}
}
return 0;
}
キーに対応する値を取得するための C++ STL マップのいくつかの方法:
マップ コンテナーは、ペア型のキーと値のペアを格納しますが、マップ コンテナーが使用されるほとんどすべてのシナリオで、指定された値を検索しないことがよくあります。ペア オブジェクト (キーと値の右) ですが、そのコンテナーからキーの値を見つけます。
- [ ] 演算子はマップ クラス テンプレートでオーバーロードされています。つまり、配列添字を使用して配列内の要素に直接アクセスするのと同様に、指定されたキーを通じてマップ コンテナー内のキーに対応する値を簡単に取得できます。
#include <iostream>
#include <map> // map
#include <string> // string
using namespace std;
int main() {
//创建并初始化 map 容器
std::map<std::string, std::string>myMap{
{
"STL教程","http://c.biancheng.net/stl/"},
{
"C语言教程","http://c.biancheng.net/c/"},
{
"Java教程","http://c.biancheng.net/java/"} };
string cValue = myMap["C语言教程"];
cout << cValue << endl;
return 0;
}
http://c.biancheng.net/c/
指定されたキーを含むキーと値のペアがマップ コンテナーにある場合にのみ、オーバーロードされた [ ] 演算子を使用してキーに対応する値を正常に取得できることに注意してください。現在のマップ コンテナの値のペアにキーを追加すると、この時点で [ ] 演算子を使用すると、コンテナ内の要素にアクセスできなくなりますが、マップ コンテナにキーと値のペアが追加されます。このうち、キーと値のペアのキーは [] 演算子で指定されたキーを使用し、それに対応する値は、マップ コンテナーで指定されたキーと値のペアの値のデータ型に依存します。データ型の場合、値は 0 です。値が "" の文字列型の場合、これは空の文字列です (つまり、型の既定値をキーと値のペアの値として使用します)。
#include <iostream>
#include <map> // map
#include <string> // string
using namespace std;
int main() {
//创建空 map 容器
std::map<std::string, int>myMap;
int cValue = myMap["C语言教程"];
for (auto i = myMap.begin(); i != myMap.end(); ++i) {
cout << i->first << " "<< i->second << endl;
}
return 0;
}
C语言教程 0
- [ ] 演算子を使用して、マップ コンテナー内の指定されたキーに対応する値を取得するだけでなく、at() メンバー メソッドを使用することもできます。前のメソッドと比較すると、at() メンバー メソッドは、指定されたキーに従って、コンテナからキーに対応する値を見つける必要もあります; 違いは、現在のコンテナで検索が失敗した場合、このメソッドは値を送信しないことです。コンテナー 新しいキーと値のペアを追加しますが、out_of_range 例外を直接スローします。
#include <iostream>
#include <map> // map
#include <string> // string
using namespace std;
int main() {
//创建并初始化 map 容器
std::map<std::string, std::string>myMap{
{
"STL教程","http://c.biancheng.net/stl/"},
{
"C语言教程","http://c.biancheng.net/c/"},
{
"Java教程","http://c.biancheng.net/java/"} };
cout << myMap.at("C语言教程") << endl;
//下面一行代码会引发 out_of_range 异常
//cout << myMap.at("Python教程") << endl;
return 0;
}
3) 指定されたキーに対応する値を直接取得するだけでなく、find() メンバー メソッドを使用して間接的にこの目的を達成することもできます。上記の 2 つのメソッドとの違いは、このメソッドが反復子を返すことです。つまり、検索が成功した場合、反復子は見つかったキーと値のペアを指し、それ以外の場合は、最後のキーと値のペアの後の位置を指します。マップ コンテナー (および end() 成功メソッドは同じ反復子を返します)。
#include <iostream>
#include <map> // map
#include <string> // string
using namespace std;
int main() {
//创建并初始化 map 容器
std::map<std::string, std::string>myMap{
{
"STL教程","http://c.biancheng.net/stl/"},
{
"C语言教程","http://c.biancheng.net/c/"},
{
"Java教程","http://c.biancheng.net/java/"} };
map< std::string, std::string >::iterator myIter = myMap.find("C语言教程");
cout << myIter->first << " " << myIter->second << endl;
return 0;
}
C语言教程 http://c.biancheng.net/c/
このプログラムで find() が失敗すると、13 行目のコードの実行でエラーが発生することに注意してください。find() メソッドが検索に失敗した場合、返された反復子はコンテナー内の最後のキーと値のペアの後の位置を指します。つまり、意味のあるキーと値のペアを指していないため、そうではありません。ファーストメンバー、セカンドメンバーと呼ばれる。 .
. . .
C++ STL map insert() データを挿入する 4 つの方法 (省略)
multimap コンテナー
multimap コンテナーは、ペア <const K, T> 型のキーと値のペアを格納するためにも使用されます (K はキーの型を表し、T は各キーと値のペアのキー値は変更できません。さらに、コンテナは、キーのサイズに従って、保存されているすべてのキーと値のペアも並べ替えます。マップ コンテナーとの違いは、同じキーを持つ複数 (2 つ以上) のキーと値のペアを同時にマルチマップ コンテナーに格納できることです。
C++ STL 順不同連想コンテナー
ハッシュ コンテナーとも呼ばれる順序付けられていない連想コンテナー。連想コンテナーと同様に、このタイプのコンテナーもキーと値のペアの要素を格納します。違いは、連想コンテナーは格納された要素を既定で昇順に並べ替えますが、順不同の連想コンテナーはそうしないことです。
連想コンテナの基盤となる実装は、ツリー ストレージ構造、より正確には赤黒ツリー構造を採用しています。
順不同コンテナの基盤となる実装は、ハッシュ テーブルストレージ構造を採用しています。
unordered_map と unodered_set がデータを格納する場合、要素のキー (キー) が繰り返されないことを保証する必要があり、キーは順不同で格納されます; 実際のシナリオでは、コンテナーのトラバースを伴う多数の操作が含まれる場合
、連想コンテナを優先することをお勧めします。反対に、対応する値を取得するためにキーを渡す操作が増える場合は、順序付けされていないコンテナを優先する必要があります。
#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;
int main()
{
//创建并初始化一个 unordered_map 容器,其存储的 <string,string> 类型的键值对
std::unordered_map<std::string, std::string> my_uMap{
{
"C语言教程","http://c.biancheng.net/c/"},
{
"Python教程","http://c.biancheng.net/python/"},
{
"Java教程","http://c.biancheng.net/java/"} };
//查找指定键对应的值,效率比关联式容器高
string str = my_uMap.at("C语言教程");
cout << "str = " << str << endl;
//使用迭代器遍历哈希容器,效率不如关联式容器
for (auto iter = my_uMap.begin(); iter != my_uMap.end(); ++iter)
{
//pair 类型键值对分为 2 部分
cout << iter->first << " " << iter->second << endl;
}
return 0;
}
程序执行结果为:
str = http://c.biancheng.net/c/
C语言教程 http://c.biancheng.net/c/
Python教程 http://c.biancheng.net/python/
Java教程 http://c.biancheng.net/java/
#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;
int main()
{
//创建空 umap 容器
unordered_map<string, string> umap;
//向 umap 容器添加新键值对
umap.emplace("Python教程", "http://c.biancheng.net/python/");
umap.emplace("Java教程", "http://c.biancheng.net/java/");
umap.emplace("Linux教程", "http://c.biancheng.net/linux/");
//输出 umap 存储键值对的数量
cout << "umap size = " << umap.size() << endl;
//使用迭代器输出 umap 容器存储的所有键值对
for (auto iter = umap.begin(); iter != umap.end(); ++iter) {
cout << iter->first << " " << iter->second << endl;
}
return 0;
}
程序执行结果为:
umap size = 3
Python教程 http://c.biancheng.net/python/
Linux教程 http://c.biancheng.net/linux/
Java教程 http://c.biancheng.net/java/
#include <iostream>
#include <unordered_map>
using namespace std;
int main()
{
//创建 umap 容器
unordered_map<int, int> umap;
//向 umap 容器添加 50 个键值对
for (int i = 1; i <= 50; i++) {
umap.emplace(i, i);
}
//获取键为 49 的键值对所在的范围
auto pair = umap.equal_range(49);
//输出 pair 范围内的每个键值对的键的值
for (auto iter = pair.first; iter != pair.second; ++iter) {
cout << iter->first <<" ";
}
cout << endl;
//手动调整最大负载因子数
umap.max_load_factor(3.0);
//手动调用 rehash() 函数重哈希
umap.rehash(10);
//重哈希之后,pair 的范围可能会发生变化
for (auto iter = pair.first; iter != pair.second; ++iter) {
cout << iter->first << " ";
}
return 0;
}
程序执行结果为:
49
49 17
他の人はあまり詳細に立ち入らず、より多くのプログラムを読み、一般的な使用法を習得します
ハッシュテーブルの演習
ハッシュ テーブルは、ハッシュ テーブルとも呼ばれます. ハッシュ テーブルは、高速な挿入および検索操作を提供するデータ構造です. ハッシュ テーブルにデータがいくつあっても、挿入および検索の時間計算量は O. (1 )ハッシュ テーブルの検索速度は非常に高速であるため、ハッシュ テーブルはピンイン チェッカーなどの多くのプログラムで使用されます。
ハッシュテーブルにも独自の欠点があります. ハッシュテーブルは配列に基づいています. 作成後の配列の拡張コストが比較的高いことがわかっているため、ハッシュテーブルがいっぱいになると、パフォーマンスが大幅に低下します.
ハッシュテーブルは変換の考え方を採用しており、重要な概念の 1 つは、「キー」または「キーワード」を配列の添え字に変換する方法です。ハッシュテーブルでは、このプロセスはハッシュ関数によって完了しますが、ハッシュ関数を介してすべての「キー」または「キーワード」を配列添え字に変換する必要はありません。一部の「キー」または「キーワード」単語」は直接変換できます。配列の添え字として使用されます。
1. 整数配列 nums と整数ターゲット値 target が与えられた場合、その合計が配列内のターゲット値 target である 2 つの整数を見つけ、それらの配列添え字を返します。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
map<int,int> a;//建立hash表存放数组元素
vector<int> b(2,-1);//存放结果
for(int i=0;i<nums.size();i++)
a.insert(map<int,int>::value_type(nums[i],i));//建立哈希表
for(int i=0;i<nums.size();i++)
{
if(a.count(target-nums[i])>0&&(a[target-nums[i]]!=i))//在容器中查找以 key 键的键值对的个数。判断是否找到目标元素且目标元素不能是本身
{
b[0]=i;
b[1]=a[target-nums[i]];
break;
}
}
return b;
};
};
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int>hashtable;//创建空哈希表
for(int i=0;i<nums.size();i++){
//固定第一个值
auto it=hashtable.find(target-nums[i]);//在哈希表中查找第二个值,nums[i]数本身为键,i为键值<nums[i],i>;
//find(key)查找以 key 为键的 键值对,如果找到,则返回一个指向该键值对的正向迭代器;
//反之,则返回一个指向容器中最后一个键值对之后位置的迭代器(如果 end() 方法返回的迭代器)。
if(it!=hashtable.end()){
return {
it->second,i};//哈希表是在访问每一个i之后增加建立的,因此i的值靠后
}
hashtable[nums[i]]=i;//将每一个i以及nums[i]添加到哈希表中
}
return {
};
}
};
217. 整数配列 nums を与えてください。いずれかの値が配列内で少なくとも 2 回出現する場合は true を返し、配列内の各要素が異なる場合は false を返します
class Solution {
public:
bool containsDuplicate(vector<int>& nums) {
sort(nums.begin(), nums.end());//排序
int n = nums.size();
for (int i = 0; i < n - 1; i++) {
if (nums[i] == nums[i + 1]) {
return true;
}
}
return false;
}
};
class Solution {
public:
bool containsDuplicate(vector<int>& nums) {
unordered_map<int,int>hashtable;
for(int i=0;i<nums.size();i++){
auto it=hashtable.find(nums[i]);
if(it!=hashtable.end()){
return true;
}
hashtable[nums[i]]=i;
}
return false;
}
};
class Solution {
public:
bool containsDuplicate(vector<int>& nums) {
unordered_set<int>hashtable;
for(int i=0;i<nums.size();i++){
auto it=hashtable.find(nums[i]);
if(it!=hashtable.end()){
return true;
}
hashtable.insert(nums[i]);
}
return false;
}
};
36. 9×9の数独が有効かどうか判断してください。次のルールに従って、入力された数字が有効かどうかを確認するだけで済みます。
sizeof(array[0][0]): 1 つの要素が占めるスペース
sizeof(array[0]): 要素の行が占めるスペース
sizeof(array): 配列全体が占めるスペース
行数 = sizeof(array)/sizeof(array[0]);
列数 = sizeof(array[0])/sizeof(array[0][0]);
public:
bool isValidSudoku(vector<vector<char>>& board) {
vector<unordered_set<char>> row(9);
vector<unordered_set<char>> col(9);
vector<unordered_set<char>> bor(9);
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
if(board[i][j]=='.')continue;
if(row[i].count(board[i][j])<=0) row[i].insert(board[i][j]);
else return false;
if(col[j].count(board[i][j])<=0) col[j].insert(board[i][j]);
else return false;
if(bor[(i/3)*3+(j/3)].count(board[i][j])<=0) bor[(i/3)*3+(j/3)].insert(board[i][j]);
else return false;
}
}
return true;
}
};
128. ソートされていない整数配列 nums を指定して、連続する数の最長シーケンスの長さを見つけます (シーケンス要素が元の配列で連続している必要はありません)。
この問題を解決するには、O(n) 時間の計算量を持つアルゴリズムを設計して実装してください。
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
sort(nums.begin(),nums.end());
int n=nums.size();
int ans=1,t=1;
if(n==0){
return 0;
}
for(int i=1;i<n;i++){
if(nums[i-1]==nums[i]-1){
t++;
ans<t?ans=t:ans;
}
else if(nums[i-1]==nums[i]){
continue;
}
else{
t=1;
}
}
return ans;
}
};
//考虑现将数组排序,然后遍历数组,如果中断则记录对应的长度,每次的长度都要与上一次对比
//注意特殊情况,数组中有相等的元素,数组为空
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
unordered_set<int> num_set;
for (const int& num : nums) {
//遍历将数组中的元素插入哈希表中
num_set.insert(num);
}
int longestStreak = 0;
for (const int& num : num_set) {
//遍历哈希表
if (!num_set.count(num - 1)) {
//当前元素的前一个元素(num-1)不存在时
int currentNum = num;
int currentStreak = 1;
while (num_set.count(currentNum + 1)) {
//当前元素的后一个元素存在
currentNum += 1;
currentStreak += 1;
}
longestStreak = max(longestStreak, currentStreak);
}
}
return longestStreak;
}
};
73. 与えられた mxn 行列で、要素が 0 の場合、その行と列のすべての要素を 0 に設定します。インプレース アルゴリズムを使用してください。
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int m=matrix.size();//行数
int n=matrix[0].size();//列数
int flag_row0=false,flag_col0=false;
for(int i=0;i<m;i++){
//验证第一列是否含零,如果含零则标记为置1
if(!matrix[i][0]){
flag_col0=true;
}
}
for(int j=0;j<n;j++){
//验证第一行是否含零,如果含零则标记为置1
if(!matrix[0][j]){
flag_row0=true;
}
}
for(int i=1;i<m;i++){
//从第二行、第二列开始遍历矩阵
for(int j=1;j<n;j++){
if(!matrix[i][j]){
matrix[i][0]=matrix[0][j]=false;//矩阵中存在零,则将对应的第一行和第一列中的元素置零
}
}
}
for(int i=1;i<m;i++){
//从第二行、第二列开始遍历矩阵
for(int j=1;j<n;j++){
if(!matrix[i][0]||!matrix[0][j]){
//检验矩阵中的第一行和第一列中标记的零位,对应行列全部置零
matrix[i][j]=0;
}
}
}
if(flag_col0){
//第一列中如果有零元素,则第一列置零
for(int i=0;i<m;i++){
matrix[i][0]=0;
}
}
if(flag_row0){
//第一行中如果有零元素,则第一行置零
for(int j=0;j<n;j++){
matrix[0][j]=0;
}
}
}
};
//时间复杂度O(mn),空间负载度O(1);
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int m = matrix.size();//矩阵的行数
int n = matrix[0].size();//矩阵的列数
vector<int> row(m,0);//定义含有m个元素的全零数组
vector<int> col(n,0);//定义含有n个元素的全零数组
for (int i = 0; i < m; i++) {
//遍历矩阵
for (int j = 0; j < n; j++) {
if (!matrix[i][j]) {
//如果下标为[i][j]的元素为零
row[i] = col[j] = true;//则将定义的行和列数组对应位置1,对其进行标记
}
}
}
for (int i = 0; i < m; i++) {
//遍历矩阵
for (int j = 0; j < n; j++) {
if (row[i] || col[j]) {
//如果是标记过的行列
matrix[i][j] = 0;//则将对应元素置0
}
}
}
}
};
//时间复杂度为O(mn);空间复杂度为O(m+n);
この記事は、質問をブラッシングするためのメモの一部にすぎません。間違いがあれば指摘してください。
この記事は次のように引用しています。
https://leetcode-cn.com/
http://c.biancheng.net/view/7166.html