【アルゴリズムシリーズ(3)】:検索

目次

 

1つ、ルックアップテーブル

1.1、アルゴリズムアプリケーション

349.2つのアレイの交差

350.2つのアレイの交差点II

242.有効な手紙エイリアンの言葉

202.ハッピー数

290.言葉の法則

451.文字の頻度に従って並べ替える


1つ、ルックアップテーブル

考慮される基本的なデータ構造は、主に次の状況に分けられます。

  • 最初のカテゴリ:存在の検索-セット

例:要素「a」が存在するかどうか、通常はset:set。セットにはキーのみが格納され、対応する値に対応する必要はありません。セット内のキーを繰り返すことはできません。

  • 2番目のカテゴリ:対応を見つける(キーと値の対応)-dict

要素「a」は数回出現します:dict-> dictionary。dictのキーを繰り返すことはできません。

  • 3番目のカテゴリ:マッピング関係の変更-マップ

他のように元のシーケンスの関係マッピングの統一された表現を通じて

1.1、アルゴリズムアプリケーション

349.2つのアレイの交差

  • タイトル説明

2つの配列numが与えられた場合、2つの配列の共通要素を見つけます。

如nums1 = [1,2,2,1],nums2 = [2,2]

结果为[2]
结果中每个元素只能出现一次
出现的顺序可以是任意的
  • 問題解決のアイデア

各要素は1回しか表示されないため、各要素の表示回数に注意する必要はなく、設定されたデータ構造を使用するだけです。要素の有無を記録します。

nums1をセットとして記録し、nums2の要素がセットに含まれているかどうかを判断します。含まれている場合は、パブリックセットに入れれば、最終的なパブリックセットが目的の結果になります。

  • C ++アルゴリズムの実装
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
    set<int> set1(nums1.begin(),nums1.end());
    set<int> set2(nums2.begin(),nums2.end());

    vector<int> res;

    for(auto i=set1.begin();i!=set1.end();++i){
        if(set2.find(*i)!=set2.end()){
            res.push_back(*i);
        }
    }

    return res;
}

350.2つのアレイの交差点II

  • タイトル説明

2つの配列が与えられた場合、それらの交点を計算する関数を記述します。

例1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
  • 問題解決のアイデア

要素の出現回数は有用であるため、ストレージの数にとって意味があります。したがって、データ構造を選択するときは、dictの構造を選択し、辞書を比較して判断する必要があります。

各要素の頻度を同時に記録します。

num1の辞書を記録し、nums2をトラバースし、nums1の辞書のnumsのキーがゼロより大きいかどうかを比較して判断します。

  • C ++アルゴリズムの実装
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
    vector<int> res;
            map<int,int> temp;
            for(int i=0;i<nums1.size();i++)
            {
                temp[nums1[i]]++;
            }
            for(int i=0;i<nums2.size();i++)
            {
                if(temp[nums2[i]]>0)
                {
                    res.push_back(nums2[i]);
                    temp[nums2[i]]--;
                }
            }
            return res;
}

242.有効な手紙エイリアンの言葉

  • タイトル説明

2つの文字列sとtが与えられた場合、tがsのアナグラムであるかどうかを判別する関数を記述します。

示例1:

输入: s = "anagram", t = "nagaram"
输出: true

示例 2:

输入: s = "rat", t = "car"
输出: false
  • 問題解決のアイデア

異所性の単語を判断するということは、変換位置の後の文字列が元の文字列と同じであるかどうかを判断することを意味し、要素を格納するだけでなく、要素の数も記録する必要があります。dictのデータ構造を選択し、文字列sとtの両方をdictに格納してから、2つのdictが同じであるかどうかを直接比較できます。

  • C ++アルゴリズムの実装
bool isAnagram(string s, string t) {
    if (s.size() != t.size())
            {
                return false;
            }
            int cNum[26] = {0};
            for (int i = 0; i < s.size(); ++i)
            {
                cNum[s[i] - 'a']++;
            }
            for (int i = 0; i < t.size(); ++i)
            {
                if (cNum[t[i] - 'a'] == 0)
                {
                    return false;
                }
                else
                {
                    cNum[t[i] - 'a']--;
                }
            }
            return true;
}

202.ハッピー数

  • タイトル説明

数が「ハッピー数」であるかどうかを判断するアルゴリズムを記述します。

「ハッピー数」は次のように定義されます。正の整数の場合、数値が各位置の数値の2乗の合計に置き換えられるたびに、このプロセスが数値が1になるまで繰り返されます。無限ループですが、常に1未満しか変化しません。1に変更できる場合、この番号はハッピー数です。

示例: 
输入: 19
输出: true
解释: 
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1
  • 問題解決のアイデア

あるかどうかを判断するだけで、回数を記録する必要がないので、セットのデータ構造を使用します。合計された数値が追加されるたびに、新しい合計された値がセットに存在する場合、falseを返します。

  • C ++アルゴリズムの実装
bool isHappy(int n) {
    set<int> sets;
    while(n!=1){
        int sum=0;
        while(n>0){
            sum+=pow((n%10),2);
            n=n/10;
        }        
        if(sets.find(sum)!=sets.end()){
            return false;
        }

        sets.insert(sum);
        n=sum;

    }

    return true;
}

290.言葉の法則

  • タイトル説明

パターンと文字列を指定して、文字列がパターンに準拠しているかどうかを判断します

示例1:
输入: pattern = "abba", 
str = "dog cat cat dog"
输出: true

示例 2:
输入:pattern = "abba", 
str = "dog cat cat fish"
输出: false

示例 3:
输入: pattern = "aaaa", str = "dog cat cat dog"
输出: false

示例 4:
输入: pattern = "abba", str = "dog dog dog dog"
输出: false
  • 問題解決のアイデア

dict1 [index] = dict2 [index]など、同じインデックスの下の値に対応して、2つの新しいディクショナリを作成し、インデックスをトラバースして2つの新しいディクショナリに値を割り当て、値を比較できます。

  • C ++アルゴリズムの実装
bool wordPattern(string pattern, string str) {
    int n = pattern.size();
    unordered_map<int, string> m;
    vector<string> vec;//保存单词
    string s;
    for(const auto &c : str){
        if(isspace(c)){
            vec.push_back(s);
            s.clear();
            continue;
        }
        s += c;
    }
    vec.push_back(s);
    if(n != vec.size()) return false;

    for(int i = 0; i < n; ++i){
        if(m.count(pattern[i])){
            if(m[pattern[i]] != vec[i]) return false;
        }else{
            for(auto v : m){//此处可以优化,多一个哈希表set就可以免去查找
                if(v.second == vec[i])  return false;
            }
            m[pattern[i]] = vec[i];
        }
    }
    return true;
}

451.文字の頻度に従って並べ替える

  • タイトル説明

2つの文字列sとtが与えられた場合、それらが同型であるかどうかを判別します。sの文字を置き換えてtを取得できる場合、2つの文字列は同型です。文字の順序を維持しながら、出現するすべての文字を別の文字に置き換える必要があります。2つの文字を同じ文字にマップすることはできませんが、文字をそれ自体にマップすることはできます。

示例 1:
输入: s = "egg", t = "add"
输出: true

示例 2:
输入: s = "foo", t = "bar"
输出: false

示例 3:
输入: s = "paper", t = "title"
输出: true
  • 問題解決のアイデア

考え方は前の質問と同じです。2つの辞書を作成して違いを比較する方法を検討できます。また、違いを同じものに変換することもできます。

  • C ++アルゴリズムの実装
string frequencySort(string s) {
    map<char,int> m;

    for(auto c:s){
        if(m.count(c)){
            m[c]++;
        }else{
            m[c]=1;
        }
    }

    vector<pair<char,int>> vec(m.begin(),m.end());

    sort(vec.begin(),vec.end(),[](const pair<char, int>& a, const pair<char, int>& b){return a.second>b.second;});
    string res="";
    for(auto it=vec.begin();it!=vec.end();++it){
        while(it->second>0){
            res+=it->first;
            it->second--;
        }
    }

    return res;
}

 

おすすめ

転載: blog.csdn.net/wxplol/article/details/108203123