《慕课网玩转算法面试》笔记及习题解答4
来源:互联网 发布:论文查重软件 编辑:程序博客网 时间:2024/05/16 07:56
查找问题
查找有无
-元素‘a’是否存在?set;集合
查找对应关系(键值对应)
-元素‘a’出现了几次?map;字典
set和map常见操作:
insert
find
erase
change (map)
LeetCode 349
Given two arrays, write a function to compute their intersection.
思路:判断是否有相同,直接用set就行
vector<int> intersection(vector<int>& nums1, vector<int>& nums2){ set<int> record(nums1.begin(), nums1.end()); set<int> resultSet; for(int i = 0; i < nums2.size();i++) { if( record.find(nums2[i]) != record.end() ) resultSet.insert(nums2[i]); } vector<int> resVec(resultSet.begin(), resultSet.end()); return resVec;}
LeetCode 350
Given two arrays, write a function to compute their intersection.
Example:
Given nums1 = [1, 2, 2, 1]
, nums2 = [2, 2]
, return [2, 2]
.
思路:寻找交集,可以有相同元素 ,如 因此可以使用map
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) { map<int,int> record; for(int i = 0; i < nums1.size(); i++) record[nums1[i]]++; vector<int> res; for(int i = 0; i < nums2.size(); i++) if( record[nums2[i]] > 0 ) { res.push_back(nums2[i]); record[nums2[i]]--; } return res; }
注意 set 和 map这两个数据结构的 find方法返回值为 .end()时为没找到。
其次,set 和 map 的底层实现为平衡二叉树,它的一次查找,增添,删除时间复杂度都是 O(logn ), 存储n个元素的空间复杂度为O(n)。
对于查找问题,哈希表非常优秀,它的增删查复杂度都是O(1)。
但是哈希表的缺点在于打乱了数据的顺序性。
unordered_map和 unordered_set 底层实现为哈希表。
对于一般的查找问题,哈希表就能解决, 但是对于 需要顺序关系的问题,比如前驱后继,最大最小等问题, 平衡二叉树更好。
练习题:
LeetCode 242
Given two strings s and t, write a function to determine if t is an anagram of s.
For example,
s = "anagram", t = "nagaram", return true.
s = "rat", t = "car", return false.
bool isAnagram(string s, string t) { unordered_map<char,int> char_count; for(int i = 0; i < s.length(); i++) char_count[s[i]]++; for(int j = 0; j < t.length(); j++) char_count[t[j]]--; for(unordered_map<char,int>::iterator iter = char_count.begin(); iter!= char_count.end(); iter++ ) if(iter->second != 0) return false; return true;}
LeetCode 202
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.
bool isHappy(int n) { if( 1 == n ) return true; unordered_map<int,int> exist_num; while( !exist_num[n] ) { exist_num[n]++; int sum = 0; while( n ) { sum += (n % 10) * (n % 10); n /= 10; } if( 1 == sum ) return true; n = sum; } return false;}
LeetCode 290
Given a pattern
and a string str
, find if str
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 str
.
Examples:
- 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.
思路:因为必须是一一对应关系,所以应该使用两个哈希表,一个从string映射到char,一个从char 映射到 string,如果给定一个(string,pair)对,两个哈希表的key / val都为空,则赋值;如果都存在,则判断是否和之前的赋值一样,不一样则return false; 如果一个哈希表存在,一个不存在,则有可能是("abba","dog dog dog dog")形式,不满足条件,直接返回false。 注意循环终止时候
bool wordPattern(string pattern, string str) { int slice_start = 0; int i = 0; map<char, string> char2string; map<string, char> string2char; while( i < pattern.length() && slice_start < str.length()){ int slice_end = str.find(" ", slice_start); if(slice_end == string::npos) slice_end = str.length(); string slice = str.substr(slice_start, slice_end - slice_start); slice_start = slice_end+1; if(char2string[pattern[i]].empty() && !string2char[slice] ) { char2string[pattern[i]] = slice; string2char[slice] = pattern[i++]; } else if(!char2string[pattern[i]].empty() && string2char[slice] ) if( char2string[pattern[i]] != slice || string2char[slice] != pattern[i] ) { return false; } else i++; else { return false; } } if( (i < pattern.length() && slice_start < str.length()) || i >= pattern.length() && slice_start >= str.length()) return true; else return false;}
LeetCode 205
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.
思路:同构可以用一一映射来表示,一一映射的问题都可以用两个哈希表来解决
bool isIsomorphic(string s, string t) { if(s.empty() ||s.length() <1) return true; unordered_map<char, char> s2t; unordered_map<char, char> t2s; int n = s.length(); for( int i = 0; i < n; i++ ) { if( !s2t[s[i]] && !t2s[t[i]] ){ s2t[s[i]] = t[i]; t2s[t[i]] = s[i]; } else{ if( s2t[s[i]] != t[i] || t2s[t[i]] != s[i] ) return false; } } return true;}
LeetCode 451
思路:使用哈希表计数,使用sort和lambda表达式对s排序
string frequencySort(string s) { unordered_map<char, int> charCount; for(int i = 0; i < s.length(); i++) { charCount[s[i]]++; } auto compare = [&charCount] (char a, char b) { return charCount[a] > charCount[b] || (charCount[a] == charCount[b] && a > b);}; sort(s.begin(), s.end(),compare); return s; }
LeetCode 15
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
思路:因为不需要输出index,可以先排序,循环第一个数 i ,在[ i+1,......]中使用对撞指针。但是此题需要输出所有的组合。因此需要注意去重, 每次找到一组数都必须将i ,j ,k移动到与当前找到的组合值不同的 i, j, l,r上,注意不能越界
class Solution {public: 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()-3; i++){ //固定 i,j for(int j = i+1; j < nums.size() - 2; j++) { int l = j+1; int r = nums.size() - 1; while(l < r) { if(nums[i] + nums[j] + nums[l] + nums[r] == target) { vector<int> temp(4,-1); temp[0] = nums[i]; temp[1] = nums[j]; temp[2] = nums[l]; temp[3] = nums[r]; res.push_back(temp); while( l+1 < r && nums[l+1] == nums[l]) l++; //去掉重复的数字 while( l < r-1 && nums[r-1] == nums[r]) r--; //去掉重复的数字 l++; } if(nums[i] + nums[j] + nums[l] + nums[r] < target) l++; if(nums[i] + nums[j] + nums[l] + nums[r] > target) r--; } while(j+1 < nums.size() - 2 && nums[j+1] == nums[j] ) j++; //去掉重复的数字 } while(i+1 < nums.size() - 3 && nums[i+1] == nums[i] ) i++; //去掉重复的数字 } return res; }};
LeetCode 18
思路:将前两个变量固定进行循环,在最右区域使用对撞指针,主要问题还是避免重复的组合,下面的结果还是有点问题,暂时找不到在哪,思路应该是这样,其实主要是c++不能用vector作为哈希表的key , 如果用python做这题很简单。。。
vector<vector<int> > fourSum(vector<int>& nums, int target) { sort(nums.begin(), nums.end()); vector<vector<int> > res; vector<int> quadruplets(4); int n = nums.size(); for(int i = 0; i < n - 3; i++){int target3 = target - nums[i];for( int j = i+1; j < n -2 ;j++ ){ int target2 = target3 - nums[j]; int l = j+1, r = n-1; while( l < r) {if( nums[l] + nums[r] < target2 ) l++;if( nums[l] + nums[r] > target2 ) r--;else if( nums[l] + nums[r] == target2 ){ quadruplets[0] = nums[i]; quadruplets[1] = nums[j]; quadruplets[2] = nums[l]; quadruplets[3] = nums[r]; res.push_back(quadruplets); while(l < n-1 && nums[l] == quadruplets[2]) l++; while(2 < r && nums[r] == quadruplets[3] ) r--;} } while( j < n-2 && nums[j+1] == nums[j] ) j++;} while( i < n-3 && nums[i+1] == nums[i] ) i++; } return res;}
LeetCode 454
Given four lists A, B, C, D of integer values, compute how many tuples (i, j, k, l)
there are such that A[i] + B[j] + C[k] + D[l]
is zero.
To make problem a bit easier, all A, B, C, D have same length of N where 0 ≤ N ≤ 500. All integers are in the range of -228 to 228 - 1 and the result is guaranteed to be at most 231 - 1.
思路: 因为有四个数组且每个数组的长度不大,数据规模其实暗示了可以用空间换时间且级别可以在O(n^2), 我们考虑将 C[i] + D[ j ]的结果存入哈希表, 遍历 A[i] + B[j] 看是否存在鱼哈希表中。
int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) { unordered_map<int, int> record; for(int i = 0; i < C.size(); i++)for(int j = 0; j < D.size(); j++) record[ C[i] + D[j] ]++; int res = 0; for(int i = 0; i < A.size(); i++)for(int j = 0; j < B.size(); j++){ if( record.find( 0 - A[i] - B[j] ) != record.end() )res += record[ 0 - A[i] - B[j] ];} return res;}
LeetCode 49
思路:将每个string排序以后可以很容易判断是否为Anagrams,将排序后的string放入哈希表中
vector<vector<string>> groupAnagrams(vector<string>& strs) { map<string, int> record; int j = 0; vector<vector<string> > res; for(int i = 0; i < strs.size(); i++){ string str_cp(strs[i]); sort(str_cp.begin(), str_cp.end()); if( record.find(str_cp) != record.end() ){ res[ record[ str_cp] ].push_back( strs[i] ); } else{ record[str_cp] = j++; vector<string> temp; temp.push_back(strs[i]); res.push_back(temp); } } return res; }
LeetCode 16
Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
思路:和3sum差不多,只要注意划分区间即可
int threeSumClosest(vector<int>& nums, int target) { int n = nums.size(); if(n < 3)return target; int closest = nums[0] + nums[1] + nums[2] ; int min_dist = abs( closest - target); sort( nums.begin(), nums.end()); for( int i = 0; i < n; i++ ){int l = i+1;int r = n-1;int target_2 = target - nums[i];while( l < r ){ int sum = nums[l] + nums[r]; if( sum + min_dist < target_2 ) // 三者之和在target-min_dist的左边,这时显然应该l++增大和l++; else if( target_2 + min_dist < sum ) // 三者之和在target+min_dist的右边,这时显然应该r--减小和r--; else{ // 三者之和在 (target-min_dist,target+min_dist)之间,这时满足条件,通过判断是在target的左右两边选择移动l还是rclosest = sum + nums[i];min_dist = abs( target - closest );if( target - closest > 0) l++;else if (target -closest < 0) r--;else return closest; } } } return closest;}
LeetCode 447
Given n points in the plane that are all pairwise distinct, a "boomerang" is a tuple of points (i, j, k)
such that the distance betweeni
and j
equals the distance between i
and k
(the order of the tuple matters).
思路:对于任意一个点 i ,记录与它不同的所有点的距离并以距离为key, 相同距离的点的个数为value构建哈希表, 对于所有value > 2的key,求它所有的两两组合即 , 其中n为value值。
int dist( const pair<int, int>& p1, const pair<int, int>& p2 ) //为了避免根号产生浮点数,可以直接用距离的平方代替距离{ return ( (p1.first - p2.first) * (p1.first - p2.first) + (p1.second - p2.second) * (p1.second - p2.second) ) ;} int numberOfBoomerangs(vector<pair<int, int> >& points) { int n_p = points.size(); int res = 0; for(int i = 0; i < n_p; i ++){ map<int, int> record;for(int j = 0; j < n_p; j++) if( i != j){record[ dist(points[i], points[j])]++; } for( map<int, int>::iterator iter = record.begin(); iter != record.end(); iter++ ) {//cout << iter->second << endl;res +=( iter->second * (iter->second -1) ); } } return res;}
LeetCode 149
感觉边界条件一堆坑,好难,暂时跳过吧
LeetCode 219
Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the absolute difference between i and j is at most k.
思路:遍历数组,用一个大小不超过k的set保存前k个不同元素,对于遍历到的元素,查看set中是否存在重复元素,存在则返回true,否则将该元素存入set中,并移除掉第i - k个元素保持set的大小不超过k
bool containsNearbyDuplicate(vector<int>& nums, int k) { unordered_set<int> record; for(int i = 0; i < nums.size(); i++){ if( record.find( nums[i] ) != record.end() ) { return true; } else{ record.insert( nums[i] ); if(record.size() > k) record.erase(nums[i - k]); } } return false; }
LeetCode 220
Given an array of integers, find out whether there are two distinct indices i and j in the array such that the absolute difference between nums[i] and nums[j] is at most t and the absolute difference between i and j is at most k.
思路:主要是要知道set里面存在lower_bound和upper_bound这样的函数可以返回set中大于等于某个数的最小值,然后判断这个值是否在 [ nums[i]-t , nums[i] +t ]之间,还要注意的是int的越界问题,可以用long long
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) { set<long long> record; for(int i = 0; i < nums.size(); i++){ if( record.lower_bound( (long long)nums[i] - (long long) t ) != record.end() && *record.lower_bound( (long long)nums[i] - (long long)t ) <= (long long) nums[i] + (long long)t ) { return true; } else{ record.insert( nums[i] ); if(record.size() > k) record.erase(nums[i - k]); } } return false; }
- 《慕课网玩转算法面试》笔记及习题解答4
- 《慕课网玩转算法面试》笔记及习题解答1
- 《慕课网玩转算法面试》笔记及习题解答2
- 《慕课网玩转算法面试》笔记及习题解答3.5~3.6
- 《慕课网玩转算法面试》笔记及习题解答3.1 ~3.4
- 《慕课网玩转算法面试》笔记及习题解答3.7 ~3.8
- 《慕课网玩转算法面试》笔记及习题解答5.1.~5.3
- 《慕课网玩转算法面试》笔记及习题解答5.4.~5.6
- 《慕课网玩转算法面试》笔记及习题解答6.4.~6.6
- 《慕课网玩转算法面试》笔记及习题解答6.7
- 《慕课网玩转算法面试》笔记及习题解答7.1~7.3
- 《慕课网玩转算法面试》笔记及习题解答7.4~7.6
- 《慕课网玩转算法面试》笔记及习题解答8.1~8.3
- 《慕课网玩转算法面试》笔记及习题解答8.4~8.5
- 《慕课网玩转算法面试》笔记及习题解答9.3
- 《慕课网玩转算法面试》笔记及习题解答9.4
- 《慕课网玩转算法面试》笔记及习题解答9.8
- Introduction to Algorithms 算法导论 第4章 递归式 学习笔记及习题解答
- CSU 1808 地铁(Dijkstra变形+构图)
- 状态栏渐变
- SSM框架(spring+springMVC+Mybatis) pom.xml文件
- POJ 1552 Doubles
- Git Repo 的一些问题
- 《慕课网玩转算法面试》笔记及习题解答4
- window安装memcache
- 单链表
- java调试过程中使用日志输出
- 三种方法实现js跨域访问(转载)
- JavaSE—java.math.BigDecimal中的setSCale函数的使用
- hosts文件修改
- Oracle之索引/视图/游标及PL/SQL编程
- 背景透明问题 rgba