查找,是使用計算機處理問題時的一個最基本的任務,所以也是面試中很是常見的一類問題。不少算法問題的本質,就是要可以高效查找。學會使用系統庫中的map和set,就已經成功了一半。c++
// 349. Intersection of Two Arrays
// 時間複雜度:O(nlogn)
// 空間複雜度:O(n)
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
//O(nlogn)
set<int> record;
for( int i = 0 ; i < nums1.size() ; i ++ )
record.insert(nums1[i]);
//O(nlogn)
set<int> resultSet;
for( int i = 0 ; i < nums2.size() ; i ++ )
if( record.find( nums2[i] ) != record.end() )
resultSet.insert( nums2[i] );
//o(n)
vector<int> resultVector;
for(set<int>::iterator iter = resultSet.begin() ; iter != resultSet.end() ; iter ++ )
resultVector.push_back( *iter );
return resultVector;
}
};
改寫程序:
// 349. Intersection of Two Arrays
class Solution {
public:
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] );
return vector<int>(resultSet.begin(), resultSet.end());
}
};
複製代碼
// 350. Intersection of Two Arrays II
// 時間複雜度:O(nlogn)
// 空間複雜度:O(n)
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
map<int, int> record;
//O(nlogn)
for( int i = 0 ; i < nums1.size() ; i ++ )
record[nums1[i]] += 1;
//o(nlogn)
vector<int> resultVector;
for( int i = 0 ; i < nums2.size() ; i ++ )
if( record[ nums2[i] ] > 0 ){
resultVector.push_back( nums2[i] );
record[nums2[i]] --;
}
return resultVector;
}
};
複製代碼
思考面試
insert算法
find數組
erasebash
change (map)微信
set和map能夠有不一樣的底層實現app
哈希表無論查找、插入、刪除都是O(1)的時間複雜度。性能
數據集中的最大值和最小值ui
某個元素的前驅和後繼spa
某個元素的floor和ceil
某個元素的排位rank
選擇某個排位的元素select
map和set的底層實現爲平衡二叉樹
unordered_map和unordered_set的底層實現爲哈希表
#include <unordered_set>
using namespace std;
// 349. Intersection of Two Arrays
// 時間複雜度:O(n)
// 空間複雜度:O(n)
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
// O(n)
unordered_set<int> record(nums1.begin(), nums1.end());
// O(n)
unordered_set<int> resultSet;
for( int i = 0 ; i < nums2.size() ; i ++ )
if( record.find( nums2[i] ) != record.end() )
resultSet.insert( nums2[i] );
// O(n)
return vector<int>(resultSet.begin(), resultSet.end());
}
};
//改寫過使用hash表實現底層的unorder_map
#include <unordered_map>
using namespace std;
/// 350. Intersection of Two Arrays II
// 時間複雜度:O(n)
// 空間複雜度:O(n)
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
// O(n)
unordered_map<int, int> record;
for( int i = 0 ; i < nums1.size() ; i ++ )
record[nums1[i]] += 1;
// O(n)
vector<int> resultVector;
for( int i = 0 ; i < nums2.size() ; i ++ )
if( record[ nums2[i] ] > 0 ){
resultVector.push_back( nums2[i] );
record[nums2[i]] --;
}
// O(n)
return resultVector;
}
};
複製代碼
Anagram:一個字符串中的字母調整順序後與原字符串一致。
空串
字符集
leetcode202 Happy Number
判斷一個數是否爲happy number。happy number是指,一個數,將其替換爲其各位數字的平方和,重複這個過程,若是最終能獲得1,這是happy number,若是這個過程陷入了一個不包含1的循環,則不是happy number
判斷一個數是否爲happy number。以19爲例:
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1 Happy Number!
複製代碼
給出一個模式(pattern)以及一個字符串,判斷這個字符串是否符合模式?
如pattern=「abba」,str=「dog cat cat dog」,返回true
如pattern=「abba」,str=「dog cat cat fish」,返回false
字符集?
空串符合任意模式?仍是不符合任意模式?
複製代碼
判斷兩個字符串是否同構?
若是咱們可以尋找到一個字符集到字符集的映射,使得經過這個字符集的映射,s能夠轉變爲t,則稱爲s和t同構。
如 egg 和 add,返回true
如 foo 和 bar,返回false
如 paper 和 title,返回true
複製代碼
注意
字符集?
空串
是否能夠一個字母映射到本身?
451 Sort Characters By Frequency
給定一個字符串,按照字母出現頻率的倒序重組整個字符串
如「tree」,返回「eert」
如「cccaaa」,返回「cccaaa」
如「Aabb」,返回「bbAa」
對於相同頻次的字母,順序任意。大小寫敏感。
複製代碼
注意
//時間複雜度:O(n)
//空間複雜度:O(n)
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");
}
};
複製代碼
給出一個整形數組,尋找其中的全部不一樣的三元組(a,b,c),使得a+b+c=0
如 nums = [-1, 0, 1, 2, -1, -4]
結果爲[ [-1, 0, 1], [-1,-1,2] ]
給出一個整形數組,尋找其中的全部不一樣的四元組(a,b,c,d),使得a+b+c+d 等於一個給定的數字target。
如 nums = [1, 0, -1, 0, -2, 2],target = 0
結果爲[ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]
給出一個整形數組,尋找其中的三個元素a,b,c,使得a+b+c的值最接近另一個給定的數字target
如 nums = [-1, 2, 1, -4],target = 1
結果爲2 ( -1 + 2 + 1 = 2 )
複製代碼
注意
若是有多個解,其和target值的接近程度同樣怎麼辦?
若是沒解?(可不可能沒解?)
500^4 = 625,0000,0000
500^3 = 1,2500,0000
//時間複雜度O(n^2)
//空間複雜度O(n^2)
class Solution {
public:
int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {
assert( A.size() == B.size() && B.size() == C.size() && C.size() == D.size() );
unordered_map<int,int> hashtable;
for( int i = 0 ; i < C.size() ; i ++ )
for( int j = 0 ; j < D.size() ; j ++ )
hashtable[C[i]+D[j]] += 1;
int res = 0;
for( int i = 0 ; i < A.size() ; i ++ )
for( int j = 0 ; j < B.size() ; j ++ )
if( hashtable.find(-A[i]-B[j]) != hashtable.end() )
res += hashtable[-A[i]-B[j]];
return res;
}
};
複製代碼
思考
給出一個字符串數組,將其中全部能夠經過顛倒字符順序產生相同結果的單詞進行分組。
如 [ 「eat」, 「tea」, 「tan」, 「ate」, 「nat」, 「bat」]
返回[ [「ate」, 「eat」, 「tea」], [「nat」, 「tan」], [「bat」] ]
複製代碼
注意
//時間複雜度:O(n^2)
//空間複雜度:O(n)
class Solution {
public:
int numberOfBoomerangs(vector<pair<int, int>>& points) {
int res = 0;
for( int i = 0 ; i < points.size() ; i ++ ){
// record中存儲 點i 到全部其餘點的距離出現的頻次
unordered_map<int, int> record;
for( int j = 0 ; j < points.size() ; j ++ )
if( j != i )
record[dis(points[i], points[j])] += 1;
for( unordered_map<int, int>::iterator iter = record.begin() ; iter != record.end() ; iter ++ )
res += (iter->second)*(iter->second-1);
}
return res;
}
private:
int dis( const pair<int,int> &pa, const pair<int,int> &pb){
return (pa.first - pb.first) * (pa.first - pb.first) +
(pa.second - pb.second) * (pa.second - pb.second);
}
};
複製代碼
給出2D平面上的n個點,求出最多有多少個點在一條直線上?
// 時間複雜度: O(n)
// 空間複雜度: O(k)
class Solution {
public:
bool containsNearbyDuplicate(vector<int>& nums, int k) {
if( nums.size() <= 1 )
return false;
if( k <= 0 )
return false;
unordered_set<int> record;
for( int i = 0 ; i < nums.size() ; i ++ ){
if( record.find( nums[i] ) != record.end() )
return true;
record.insert( nums[i] );
// 保持record中最多有k個元素
// 由於在下一次循環中會添加一個新元素,使得總共考慮k+1個元素
if( record.size() == k + 1 )
//刪除掉最左側元素
record.erase( nums[i-k] );
}
return false;
}
};
複製代碼
給出一個整形數組,若數組中存在相同的元素,則返回true,不然返回false.
維持滑動窗的大小爲k 遍歷每個元素,在活動窗口中尋找|v-nums[i]| < t, 即窗口中的元素範圍爲:[v-t...v+t]之間。採用ceil和floor能夠實現
// 時間複雜度: O(nlogn)
// 空間複雜度: O(k)
class Solution {
public:
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;
record.insert( nums[i] );
if( record.size() == k + 1 )
record.erase( nums[i-k] );
}
return false;
}
};
複製代碼
-------------------------華麗的分割線--------------------
看完的朋友能夠點個喜歡/關注,您的支持是對我最大的鼓勵。
想了解更多,歡迎關注個人微信公衆號:番茄技術小棧