01 配列 (ハッシュ) の注意事項

連想コンテナ


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 マップのいくつかの方法:
マップ コンテナーは、ペア型のキーと値のペアを格納しますが、マップ コンテナーが使用されるほとんどすべてのシナリオで、指定された値を検索しないことがよくあります。ペア オブジェクト (キーと値の右) ですが、そのコンテナーからキーの値を見つけます。

  1. [ ] 演算子はマップ クラス テンプレートでオーバーロードされています。つまり、配列添字を使用して配列内の要素に直接アクセスするのと同様に、指定されたキーを通じてマップ コンテナー内のキーに対応する値を簡単に取得できます。
#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
  1. [ ] 演算子を使用して、マップ コンテナー内の指定されたキーに対応する値を取得するだけでなく、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

Supongo que te gusta

Origin blog.csdn.net/weixin_42370166/article/details/123416998
Recomendado
Clasificación