[알고리즘 시리즈 (3)] : 검색

목차

 

하나, 조회 테이블

1.1, 알고리즘 적용

349. 두 배열의 교차

350. 두 배열의 교차 II

242. 유효한 문자 외계인 단어

202. 해피 넘버

290. 단어 법

451. 문자 빈도에 따라 정렬


하나, 조회 테이블

고려되는 기본 데이터 구조는 주로 다음과 같은 상황으로 나뉩니다.

  • 첫 번째 범주 : 존재 검색-세트

예 : 'a'요소의 존재 여부, 일반적으로 set : set. 세트는 키만 저장하며 해당 값과 일치 할 필요는 없습니다. 세트의 키는 반복 할 수 없습니다.

  • 두 번째 범주 : 대응 관계 찾기 (키-값 대응) --dict

'a'요소가 여러 번 나타납니다 : dict-> dictionary. dict의 키는 반복 할 수 없습니다.

  • 세 번째 범주 : 매핑 관계 맵 변경

다른 원본 시퀀스의 관계 매핑의 통합 표현을 통해

1.1, 알고리즘 적용

349. 두 배열의 교차

  • 제목 설명

두 개의 배열 번호가 주어지면 두 배열의 공통 요소를 찾으십시오.

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

结果为[2]
结果中每个元素只能出现一次
出现的顺序可以是任意的
  • 문제 해결 아이디어

각 요소는 한 번만 나타나므로 각 요소가 나타나는 횟수에 신경을 쓸 필요가 없으며 설정된 데이터 구조를 사용하면됩니다. 요소의 유무를 기록하십시오.

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. 두 배열의 교차 II

  • 제목 설명

두 개의 배열이 주어지면 교차를 계산하는 함수를 작성하십시오.

예 1 :

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
  • 문제 해결 아이디어

요소의 발생 횟수는 유용하므로 저장 횟수에 의미가 있으므로 데이터 구조를 선택할 때 dict의 구조를 선택하고 사전을 비교하여 판단해야합니다.

동시에 각 요소의 빈도를 기록하십시오.

num1의 사전을 기록하고 nums2를 순회하고 nums1의 사전의 nums 키가 0보다 큰지 비교하여 판단합니다.

  • 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. 유효한 문자 외계인 단어

  • 제목 설명

두 문자열 s와 t가 주어지면 t가 s의 애너그램인지 여부를 확인하는 함수를 작성하십시오.

示例1:

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

示例 2:

输入: s = "rat", t = "car"
输出: false
  • 문제 해결 아이디어

이소 성어를 판단하는 것은 변형 위치 이후의 문자열이 원래의 문자열과 동일한 지 판단하고 요소를 저장해야 할뿐만 아니라 요소의 개수도 기록해야한다는 것을 의미합니다. dict의 데이터 구조를 선택하고 dict에 문자열 s와 t를 모두 저장 한 다음 두 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. 해피 넘버

  • 제목 설명

숫자가 "행복한 숫자"인지 확인하는 알고리즘을 작성합니다.

"행복한 숫자"는 다음과 같이 정의됩니다. 양의 정수의 경우 숫자가 각 위치에있는 숫자의 제곱의 합으로 대체 될 때마다이 프로세스는 숫자가 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]와 같은 동일한 인덱스 아래의 값에 해당하면 두 개의 새 사전을 만들고 인덱스를 탐색하여 두 개의 새 사전에 값을 할당하고 값을 비교할 수 있습니다.

  • 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. 문자 빈도에 따라 정렬

  • 제목 설명

두 개의 문자열 s와 t가 주어지면 동형인지 확인합니다. s의 문자를 대체하여 t를 얻을 수 있다면 두 문자열은 동형입니다. 모든 문자는 문자 순서를 유지하면서 다른 문자로 대체되어야합니다. 두 문자는 동일한 문자에 매핑 될 수 없지만 해당 문자는 자신에게 매핑 될 수 있습니다.

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

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

示例 3:
输入: s = "paper", t = "title"
输出: true
  • 문제 해결 아이디어

아이디어는 이전 질문과 동일합니다. 두 개의 dict를 구성하여 차이점을 비교하는 방법을 고려할 수 있으며 차이점을 동일하게 변환 할 수도 있습니다.

  • 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