Leetcode C++ 查找表(Set & Map)

Leetcode 349

349… 两个数组的交集
给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。

  • 思路:
    利用set的元素唯一性。
    注意这里set与vector的互转操作;
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
    set<int> set_nums1; // 存储nums1的set
    for (int i = 0; i < nums1.size(); ++i) {
        set_nums1.insert(nums1[i]);
    }
    set<int> set_result; //存储结果的set
    // 判断num2中的第j个元素是否在nums1_set中,
    // 如果在那么就将该值加入到set_result中
    for (int j = 0; j < nums2.size(); ++j) {
        if (set_nums1.find(nums2[j]) != set_nums1.end()) {
            set_result.insert(nums2[j]);
        }
    }
    // 将set_result转存到vector中并返回
    vector<int> res;
    for (set<int>::iterator iter = set_result.begin();
        iter != set_result.end();
        ++iter) {
            res.push_back(*iter);
        }
    return res;
}

因为vector和set都拥有迭代器构造函数,因此可以如下实现:

vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
    set<int> set_nums1(nums1.begin(), nums1.end());
    set<int> set_result;
    for (int i = 0; i < nums2.size(); ++i) {
        if (set_nums1.find(nums2[i]) != set_nums1.end()) {
            set_result.insert(nums2[i]);
        }
    }
    vector<int> res(set_result.begin(), set_result.end());
    return res;
}

Leetcode 350

350…两个数组的交集 II
给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。

  • 思路:
    与349的区别是这里要求保存两个集合中出现次数的最小值,可以利用map记录每个元素的频次信息,线用加法增加频次,再用减法减掉的频次就是两个集合的最小频次;
    这里注意map使用时最好先判断一下元素是否存在,因为在STL中如果直接调用find方法会自动添加元素;
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
    map<int,int> num1_to_count;
    for (int i = 0; i < nums1.size(); ++i) {
        if (num1_to_count.find(nums1[i]) != num1_to_count.end()) {
            num1_to_count[nums1[i]]++;
        } else {
            num1_to_count.insert(make_pair(nums1[i],1));
        }
    }
    vector<int> results;
    for (int j = 0; j < nums2.size(); ++j) {
        if (num1_to_count.find(nums2[j]) != num1_to_count.end() 
        && num1_to_count[nums2[j]] > 0) {
            results.push_back(nums2[j]);
            num1_to_count[nums2[j]]--;
        }
    }
    return results;
}

Leetcode 290

290. Word Pattern
Given a pattern and a string s, find if s follows the same pattern.
Here follow means a full match, such that there is a bijection between a letter in pattern and a non-empty word in s.
Example 1:
Input: pattern = “abba”, s = “dog cat cat dog”
Output: true

  • 思路:
    使用pattern做key,使用s做value构造一个map,判断相同key对应的value是否一致,如果遇到不存在的key那么插入对应value,此时要注意判断该value之前是否已经有key对应了。例如:pattern="aab"; s="hello hello hello" 最后一个hello在插入时要判断之前已有a=>hello。
    程序中遇到的字符串分割方法可参考连接
bool wordPattern(string pattern, string s) {
    istringstream iss(s);
    unordered_map<char, string> s_map;
    int id = 0;
    vector<string> v_str;
    string temp_str;
    // 以空格为标记,分割字符串
    while (iss >> temp_str)
        v_str.push_back(temp_str);
    if (v_str.size() != pattern.length())
        return false;
    for (int id = 0; id < v_str.size(); ++id) {
        if (s_map.find(pattern.at(id)) != s_map.end()) {
            if (s_map[pattern.at(id)] != v_str[id])
                return false;
        } else {
            // 此处要判断v_str[id]是否在之前已经有其他key对应
            for (unordered_map<char, string>::iterator iter = s_map.begin();
                iter != s_map.end(); ++iter) {
                if (iter->second == v_str[id])
                    return false;
            }
            s_map[pattern.at(id)] = v_str[id];
        }
    }
    return true;
}

Leetcode 451

451. Sort Characters By Frequency
Given a string, sort it in decreasing order based on the frequency of characters.
Example 1:
Input:
“tree”
Output:
“eert”
Explanation:
‘e’ appears twice while ‘r’ and ‘t’ both appear once.
So ‘e’ must appear before both ‘r’ and ‘t’. Therefore “eetr” is also a valid answer.

  • 思路:
    首先使用map对象对字符串中字符数量进行统计,然后对map对象进行以value为基础的排序(可参考连接),最后按照排序结果输出。
string frequencySort(string s) {
    unordered_map<char, int> s_map;
    for (int id = 0; id < s.length(); ++id) {
        s_map[s.at(id)]++;
    }
    // sort
    vector<pair<char, int>> s_pairs(s_map.begin(), s_map.end());
    sort(s_pairs.begin(), s_pairs.end(),
    	[](const pair<char, int>& p1, const pair<char, int>& p2) -> bool {
        	return p1.second > p2.second;
    });
    // output
    string res;
    for (int id = 0; id < s_pairs.size(); ++id)
        for (int count = 0; count < s_pairs[id].second; ++count)
            res += s_pairs[id].first;
    return res;
}

Leetcode 1

1. Two Sum
Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
You can return the answer in any order.
Example 1:
Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Output: Because nums[0] + nums[1] == 9, we return [0, 1].

  • 思路:
    构建map<num, index>对象,在构建的过程中不断查找构建好的map中是否包含target - nums[id]元素。注意:因为此题只需要寻找到两个数字的和,因此map中可以覆盖相同num值的index。
vector<int> twoSum(vector<int>& nums, int target) {
    unordered_map<int, int> n_map;
    for (int id = 0; id < nums.size(); ++id) {
        if (n_map.find(target - nums[id]) != n_map.end()) {
            return {n_map[target - nums[id]], id};
        } else {
            n_map[nums[id]] = id;
        }
    }
    return {};
}

Leetcode 15

15. 3Sum
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Notice that the solution set must not contain duplicate triplets.
Example 1:
Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]

  • 思路:
  1. 为了避免重复,首先对数组排序;
  2. 固定一个数字,计算target,转化为其余两个数字之和为target的问题,使用hash表求解;
  3. 为避免重复,有两处处理,见代码注释处。使用例子-4, -4, -2, -2, -1, -1, 0, 0, 1, 1, 2, 2, 4, 4
vector<vector<int>> threeSum(vector<int>& nums) {
    vector<vector<int> > res = {};
    if (nums.size() < 3)
        return res;
    sort(nums.begin(), nums.end());
    unordered_set<int> num_set;
    for (int i = 0; i < nums.size(); ++i) {
        // 此处处理,为避免重复
        if (i != 0 && nums[i] == nums[i - 1]) {
            continue;
        }
        num_set.clear();
        int target = 0 - nums[i];
        for (int j = i + 1; j < nums.size(); ++j) {
            if (num_set.find(target - nums[j]) != num_set.end()) {
                res.push_back({nums[i], nums[j], target - nums[j]});
                // 此处处理,为避免重复
                while (j < nums.size() - 1 && nums[j] == nums[j + 1]) {
                    ++j;
                }
            } else {
                num_set.insert(nums[j]);
            }
        }
    }
    return res;
}

Leetcode 18

18. 4Sum
Given an array nums of n integers and an integer target, are there elements a, b, c, and d in nums such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Notice that the solution set must not contain duplicate quadruplets.
Example 1:
Input: nums = [1,0,-1,0,-2,2], target = 0
Output: [[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]

  • 思路:
    可以仿照3Sum问题的解法,将4Sum转化为2Sum问题来解决。但是该解法 在Leetcode平台上会出现超时错误,修改方法为将2Sum问题使用对撞指针方法来解决(应为此数字已经过排序)。
    set方法(超时):
vector<vector<int>> fourSum(vector<int>& nums, int target) {
    vector<vector<int> > res = {};
    if (nums.size() < 4)
        return res;
    unordered_set<int> nums_set;
    sort(nums.begin(), nums.end());
    for (int i = 0; i < nums.size(); ++i) {
        if (i > 0 && nums[i] == nums[i - 1])
            continue;
        for (int j = i + 1; j < nums.size(); ++j) {
            if (j > i + 1 && nums[j] == nums[j - 1])
                continue;
            // 将问题转化为2Sum,然后通过set来解决
            nums_set.clear();
            int sub_target = target - nums[i] - nums[j];
            for (int k = j + 1; k < nums.size(); ++k) {
                if (nums_set.find(sub_target - nums[k]) != nums_set.end()) {
                    res.push_back({nums[i], nums[j], nums[k], sub_target - nums[k]});
                    while (k < nums.size() - 1 && nums[k + 1] == nums[k]) ++k;
                } else {
                    nums_set.insert(nums[k]);
                }
            }
        }
    }
    return res;
}

对撞指针方法:

vector<vector<int>> fourSum(vector<int>& nums, int target) {
    vector<vector<int> > res = {};
    if (nums.size() < 4)
        return res;
    sort(nums.begin(), nums.end());
    for (int i = 0; i < nums.size(); ++i) {
        if (i > 0 && nums[i] == nums[i - 1])
            continue;
        for (int j = i + 1; j < nums.size(); ++j) {
            if (j > i + 1 && nums[j] == nums[j - 1])
                continue;
            int sub_target = target - nums[i] - nums[j];
            int left = j + 1, right = nums.size() - 1;
            while (left < right) {
                if (nums[left] + nums[right] == sub_target) {
                    res.push_back({nums[i], nums[j], nums[left], nums[right]});
                    // 去重
                    while (left < right && nums[left + 1] == nums[left]) ++left;
                    while (left < right && nums[right - 1] == nums[right]) --right;
                    // 注意此处还需要再移动一下指针
                    ++left; --right; 
                } else if(nums[left] + nums[right] < sub_target) {
                    ++left;
                } else {
                    --right;
                }   
            }
        }
    }
    return res;
}

Leetcode 49

49. Group Anagrams
Given an array of strings strs, group the anagrams together. You can return the answer in any order.
An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.
Example 1:
Input: strs = [“eat”,“tea”,“tan”,“ate”,“nat”,“bat”]
Output: [[“bat”],[“nat”,“tan”],[“ate”,“eat”,“tea”]]

  • 思路
    本题目标对字符串找到合适的编码方法,使得错位词具有相同的编码。这里使用对字符串进行排序后生成的新字符串作为编码。
vector<vector<string>> groupAnagrams(vector<string>& strs) {
    vector<vector<string>> res;
    unordered_map<string, vector<string> > s_map;
    for (int id = 0; id < strs.size(); ++id) {
        string key = strs[id];
        sort(key.begin(), key.end());
        s_map[key].push_back(strs[id]);
    }
    for (unordered_map<string, vector<string> >::iterator iter = s_map.begin();
        iter != s_map.end();
        ++iter) {
        res.push_back(iter->second);
    }
    return res;
}

Leetcode 447

447. Number of Boomerangs
You are given n points in the plane that are all distinct, where points[i] = [xi, yi]. A boomerang is a tuple of points (i, j, k) such that the distance between i and j equals the distance between i and k (the order of the tuple matters).
Return the number of boomerangs.
Example 1:
Input: points = [[0,0],[1,0],[2,0]]
Output: 2
Explanation: The two boomerangs are [[1,0],[0,0],[2,0]] and [[1,0],[2,0],[0,0]].

  • 思路:
    通过一个双循环,以两点距离为key,相同距离的点的数量为value,构造map对象,然后迭代map对象计算所有满足条件的tuple数量。
int distance(const vector<int>& point1, const vector<int>& point2) {
    int dist = 0;
        dist += (point1[0] - point2[0]) * (point1[0] - point2[0]) +
            (point1[1] - point2[1]) * (point1[1] - point2[1]);
    return dist;
}
int numberOfBoomerangs(vector<vector<int>>& points) {
    if (points.size() < 3)
        return 0;
    int res = 0;
    unordered_map<int, int> dist_to_num;
    for (int i = 0; i < points.size(); ++i) {
        dist_to_num.clear();
        for (int j = 0; j < points.size(); ++j) {
            if (j == i)
                continue;
            dist_to_num[distance(points[i], points[j])]++;
        }
        for (unordered_map<int, int>::iterator iter = dist_to_num.begin();
        iter != dist_to_num.end(); ++iter) {
        if (iter->second > 1)
            res += (iter->second - 1) * iter->second;
        }
    }
    
    return res;
}

Leetcode 149

149. Max Points on a Line
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
Example 1:
Input: [[1,1],[2,2],[3,3]]
Output: 3
Explanation:
^
|
| o
| o
| o
±------------>
0 1 2 3 4

  • 思路:
    这个题目最简单的方法就是使用一个三重循环暴力求解,然而借助map对象,对中间结果进行存储,可以实现双重循环求解。具体方法是逐点便利,求与该点构成的所有斜率相同的点的数量,使用map对象存储,key为斜率,value为该斜率的点的数量,然后获得map中value的最大值,即为通过该点的拥有最多点数的直线上的点的数量。遍历完所有点后,最终再球的一个最大值即可。
    注意1:其中一个问题的斜率为有理数,因此作为map的key不合适,所以使用pair对象存储两个整数来表示,这样就不能使用unordered_map对象,只能使用map对象。
    注意2:为了得到唯一的pair对象数组,需要对两个整数标识的分数进行化简,这里就要求最大公约数,使用的是欧几里得算法。
    注意3:对于斜率的分类讨论,分为三种情况:1)重合点情况、2)斜率为正无穷情况、3)正常情况。2)、3)两中情况的点数中要加入1)情况的点数。
int GCD(int a, int b) {
    if (b == 0)
        return a;
    return GCD(b, a%b); 
}
int maxPoints(vector<vector<int>>& points) {
    if (points.size() < 2)
        return points.size();
    int max_num = 0;
    map<pair<int, int>, int> k_to_count;
    for (int i = 0; i < points.size(); ++i) {
        k_to_count.clear();
        for (int j = i + 1; j < points.size(); ++j) {
            int delta_x = points[j][0] - points[i][0];
            int delta_y = points[j][1] - points[i][1];
            if (delta_x == 0 && delta_y == 0)
                k_to_count[{0, 0}]++; // overlap
            else if (delta_x == 0)
                k_to_count[{0, 1}]++; // k = infinity
            else {
                int gcd = GCD(delta_x, delta_y);
                int key_x = delta_x / gcd;
                int key_y = delta_y / gcd;
                k_to_count[{key_x, key_y}]++;
            }
            for (auto item : k_to_count) {
            	// 对于斜率是无穷和正常情况的直线的点数中加入重合情况的点数
                if(item.first.first || item.first.second)
                     item.second += k_to_count[{0, 0}];
                if (max_num < item.second)
                    max_num = item.second;
            }
            
        }
    }
    return max_num + 1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值