查找表问题(c++)

来源:互联网 发布:java函数调用关系图 编辑:程序博客网 时间:2024/05/21 06:37

分类

  • 查找有无
    查找’a’是否存在?使用集合:set,unordered_set

  • 查找对应关系(键值对应)
    元素’a’出现了几次?使用字典:map,unordered_map

set & map基本用法

  • insert
  • find
  • erase
  • change (map)

举例说明(LeetCode)

349. Intersection of Two Arrays

求两个集合的交集元素,相同元素只记录一次。

#include <iostream>#include <vector>#include <unordered_set>using namespace std;// 求两个集合的交集vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {    unordered_set<int> record(nums1.begin(), nums1.end());    unordered_set<int> ret;    for (int i = 0; i < nums2.size(); i++){        if (record.find(nums2[i]) != record.end()){            ret.insert(nums2[i]);        }    }    return vector<int>(ret.begin(), ret.end());}

350. Intersection of Two Arrays II

求两个集合的交集元素,相同元素需要记录次数。

vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {    unordered_map<int, int> record;    for (vector<int>::size_type i = 0; i < nums1.size(); i++){        record[nums1[i]]++;    }    vector<int> resultVec;    for (vector<int>::size_type i = 0; i < nums2.size(); i++){        if (record[nums2[i]]>0){            resultVec.push_back(nums2[i]);            record[nums2[i]]--;        }    }    return resultVec;}

202. Happy Number

Write an algorithm to determine if a number is “happy”.

A happy number is a number defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy numbers.

Example: 19 is a happy number

1^2 + 9^2 = 828^2 + 2^2 = 686^2 + 8^2 = 1001^2 + 0^2 + 0^2 = 1

经过上面的循环,能得到1的就是happy number,否则就不是,什么情况下不是呢?实际上是算出的结果在前面已经出现,也就是循环了这是明显查找有无的问题。

class Solution {public:    bool isHappy(int n) {        unordered_set<int> record;        while (n != 1){            if (record.find(n) != record.end())                return false;            else                record.insert(n);            int sum = 0;            while (n != 0){                sum += pow(n % 10, 2);                n /= 10;            }            n = sum;        }        // n==1 退出while,happy num        return true;    }};

290. Word Pattern

点击这里看问题描述,这是一个双向查找问题,不能只从一个方向到另一个方向,两者是11对应的,因此这类问题需要建立两个字典进行验证,正/反向查找。

输入输出示例:

pattern = "abba", str = "dog cat cat dog" should return true.pattern = "abba", str = "dog cat cat fish" should return false.pattern = "aaaa", str = "dog cat cat dog" should return false.pattern = "abba", str = "dog dog dog dog" should return false.

编码如下:

#include <iostream>#include <string>#include <sstream>#include <vector>#include <unordered_map>using namespace std;bool wordPattern(string pattern, string str) {    stringstream ss(str);    vector<string>  vec;    string temp;    unordered_map<char, string> table_to;    unordered_map<string, char> table_from;    while (ss >> temp){        vec.push_back(temp);    }    if (pattern.size() != vec.size())return false;    for (int i = 0; i < vec.size(); i++){        // 两个方向都有        if (table_to.find(pattern[i]) != table_to.end() &&            table_from.find(vec[i]) != table_from.end()){            if (table_to[pattern[i]] == vec[i] && table_from[vec[i]] == pattern[i])                continue;            else                return false;        }        // 两个方向都没有        else if (table_to.find(pattern[i]) == table_to.end() &&            table_from.find(vec[i]) == table_from.end()){            table_to.insert(make_pair(pattern[i], vec[i]));            table_from.insert(make_pair(vec[i], pattern[i]));        }        else{            return false;        }    }    return true;}

对上述问题进行优化

上述问题求解,虽然思路比较清晰,但代码编写起来比较繁琐,有时候为了表示两个方向的一一对应关系,不一定就需要用对方作为自己映射过去的值,我们可以用一个统一的索引来表示这种一一对应关系,比如我们可以将两个方向的值都对应为他们所在的位置索引。优化后,我们可以写出如下的代码:

bool wordPattern(string pattern, string str) {    stringstream ss(str);    vector<string>  vec;    string temp;    while (ss >> temp){        vec.push_back(temp);    }    if (pattern.size() != vec.size())return false;    unordered_map<char, int> p2w;    unordered_map<string, int> w2p;    for (int i = 0; i < vec.size(); i++){        if (p2w[pattern[i]] != w2p[vec[i]])  // 是否在同一位置,刚开始都为0            return false;        p2w[pattern[i]] = w2p[vec[i]] = i + 1; //更新他们的标识,用i+1唯一标识    }    return true;}

以上代码变得更加优雅,用i+1这个位置作为唯一标识,显得非常巧妙。

205. Isomorphic Strings

Given two strings s and t, determine if they are isomorphic.

Two strings are isomorphic if the characters in s can be replaced to get t.

All occurrences of a character must be replaced with another character while preserving the order of characters. No two characters may map to the same character but a character may map to itself.

For example,

Given "egg", "add", return true.Given "foo", "bar", return false.Given "paper", "title", return true.

同样,leetcode205号问题,也可以采用这个思路:

#include <iostream>#include <string>#include <unordered_map>using namespace std;bool isIsomorphic(string s, string t) {    if (s.size() != t.size())return false;    unordered_map<char, int> s2t, t2s;    for (int i = 0; i < s.size(); i++){        if (s2t[s[i]] != t2s[t[i]])return false;        s2t[s[i]] = t2s[t[i]] = i + 1;    }    return true;}

451. Sort Characters By Frequency

按照频率排列字符串。

1.Two Sum

class Solution {public:    vector<int> twoSum(vector<int>& nums, int target) {        unordered_map<int,int> record;        for( int i = 0 ; i < nums.size() ; i ++ ){            int complement = target - nums[i];            if( record.find(complement) != record.end() ){                int res[] = {i, record[complement]};                return vector<int>(res, res + 2);            }            record[nums[i]] = i;        }        throw invalid_argument("the input has no solution");    }};
原创粉丝点击