leetcode 数组类型题总结
1,removeDuplicates(I)
1 int removeDuplicatesI(vector<int>& nums){ // 重新组织数组,同 removeDuplicates2IV 2 int index = 0; 3 for(int i=0;i<nums.size();++i){ 4 if(i>0 && nums[i] == nums[i-1]) 5 continue; 6 nums[index++] = nums[i]; 7 } 8 return index; 9 } 10 int removeDuplicatesII(vector<int>& nums) { // 数组覆盖操作 11 if(nums.empty()) return 0; 12 int index = 1; 13 for(int i=1;i<nums.size();++i) { 14 if(nums[i-1] != nums[i]) 15 nums[index++] = nums[i]; 16 } 17 return index; 18 } 19 int removeDuplicatesIII(vector<int>& nums) { // STL::hashmap 20 map<int,int> mapping; 21 if(nums.empty()) return 0; 22 for(int i=0;i<nums.size();++i) { 23 if(mapping.find(nums[i]) != mapping.end()) 24 mapping[nums[i]] += 1; 25 else 26 mapping[nums[i]] = 1; 27 } 28 return mapping.size(); 29 } 30 int removeDuplicatesIV(vector<int>& nums) { // STL::set 31 set<int> myset; 32 for(int i=0;i<nums.size();++i) 33 myset.insert(nums[i]); 34 return myset.size(); 35 } 36 int removeDuplicatesV(vector<int>& nums) { // STL::unique,STL::distance 37 return distance(nums.begin(),unique(nums.begin(),nums.end())); 38 }
removeDuplicates(II)
1 int removeDuplicates2I(vector<int>& nums) { // STL::haspmap 2 map<int,int> mapping; 3 for(int i=0;i<nums.size();++i) { 4 if(mapping.find(nums[i]) != mapping.end()){ 5 if(mapping.find(nums[i])->second == 2) 6 mapping.find(nums[i])->second = 2; 7 else 8 mapping.find(nums[i])->second += 1; 9 } 10 else 11 mapping[nums[i]] = 1; 12 } 13 int result=0; 14 for(map<int,int>::iterator it = mapping.begin();it != mapping.end();++it) { 15 result += it->second; 16 } 17 return result; 18 } 19 int removeDuplicates2II(vector<int>& nums) { // 思路同 removeDuplicatesII,覆盖操作,扩展性好 20 if(nums.size()<3) return nums.size(); 21 int index = 2; // index表示将要覆盖的三个相同元素的最后一个元素位置 22 for(int i=2;i<nums.size();++i) { 23 if(nums[i] != nums[index-2]) 24 nums[index++] = nums[i]; // 覆盖三个相同元素的最后一个 25 } 26 return index; 27 } 28 int removeDuplicates2III(vector<int>& nums) { // STL::erase 函数 29 if(nums.size()<3) return nums.size(); 30 for(vector<int>::iterator it=nums.begin();it!=nums.end()-2;++it) 31 if(*it == *(it + 1) && *it == *(it + 2)) 32 it = nums.erase(it); 33 return nums.size(); 34 } 35 int removeDuplicates2IV(vector<int>& nums) { // 重新组织数组 36 int index = 0; // index 表示下次放元素的位置 37 for(int i=0;i<nums.size();++i){ 38 if(i>1 && i<nums.size()-1 && nums[i]==nums[i-1] && nums[i]==nums[i+1]) 39 continue; // 和左右两边相等的元素跳过(不放入重组数组中) 40 nums[index++] = nums[i]; 41 } 42 return index; 43 }
2, search(I)
1 int search1(const vector<int>& nums,int target) { 2 int first = 0; 3 int last = nums.size()-1; 4 while(first <= last) { 5 int mid = first + (last - first)/2; 6 if(nums[mid]==target) 7 return mid; 8 else if(nums[first]<=nums[mid]) { // mid在左半部分 9 if(nums[first]<=target && target<nums[mid]) 10 last = mid - 1; 11 else 12 first = mid + 1; 13 } 14 else { // mid在右半部分 15 if(nums[mid]<target && target<=nums[last]) 16 first = mid + 1; 17 else 18 last = mid - 1; 19 } 20 } 21 return -1; 22 }
search(II)
1 int search2(const vector<int>& nums,int target) { 2 int first = 0; 3 int last = nums.size()-1; 4 while(first <= last) { 5 int mid = first + (last - first)/2; 6 if(nums[mid]==target) 7 return mid; 8 9 if(nums[first]<=nums[mid]) { // mid 在左半部分 10 if(nums[first]<nums[mid]) { // nums[first] < nums[mid] 11 if(nums[first]<=target && target<nums[mid]) 12 last = mid - 1; 13 else 14 first = mid + 1; 15 } 16 else // nums[first] == nums[mid] 17 first++; // 缩短查找区间 18 } 19 else { // nums[first] > nums[mid],mid 在右半部分 20 if(nums[mid]<target && target<=nums[last]) 21 first = mid +1; 22 else 23 last = mid - 1; 24 } 25 } 26 return -1; 27 }
3,连续序列长度
1 int longestConsecutive(const vector<int>& nums) { 2 map<int,bool> mapping; 3 if(nums.empty()) return 0; 4 int longestLengths = 1; 5 for(int i=0;i<nums.size();++i) { 6 mapping[nums[i]] = false; // 用来表示该元素是否用过,因为同一连续序列的元素的连续序列长度相同,无序再计算 7 } 8 9 for(int i=0;i<nums.size();++i) { 10 int Lengths = 1; 11 if(mapping[nums[i]]) continue; 12 for(int j = 1;;++j) { // 从右边往左边找 13 map<int,bool>::iterator it = mapping.find(nums[i]-j); 14 if(it != mapping.end()){ 15 Lengths++; 16 it->second = true; 17 } 18 else 19 break; 20 } 21 for(int j=1;;++j) { // 从左往右找 22 map<int,bool>::iterator it = mapping.find(nums[i]+j); 23 if(it != mapping.end()) { 24 Lengths++; 25 it->second = true; 26 } 27 else 28 break; 29 } 30 longestLengths = max(longestLengths,Lengths); 31 } 32 return longestLengths; 33 }
4, 查询两个有序数组的第 K 个元素
1 int findMedianSortedArray(const vector<int>& A,const vector<int>& B) { 2 vector<int> result; 3 result.reserve(A.size()+B.size()); 4 merge(A.begin(),A.end(),B.begin(),B.end(),result.begin()); 5 return result[result.size()/2]; 6 7 }
5,twoSum
1 vector<int> twoSum1(vector<int>& nums,int target) { // STL::hashmap 2 map<int,int> mapping; 3 vector<int> result; 4 for(int i=0;i<nums.size();++i) 5 mapping[nums[i]] = i; 6 for(int i=0;i<nums.size();++i){ 7 if(mapping.find(target-nums[i])!=mapping.end() && mapping[target-nums[i]]>i){ 8 result.push_back(i+1); 9 result.push_back(target-nums[i]+1); 10 break; 11 } 12 return result; 13 } 14 } 15 16 vector<int> twoSum2(vector<int>& nums,int target) { // 先排序,再左右夹逼 17 vector<int> result; 18 int first = 0; // 保存元素下标 19 int last = nums.size()-1; 20 sort(nums.begin(),nums.end()); 21 while(first<last) { 22 if(nums[first] + nums[last] == target){ 23 result.push_back(first+1); 24 result.push_back(last+1); 25 break; 26 } 27 if(nums[first] + nums[last] > target) { 28 last--; 29 } 30 else { 31 first++; 32 } 33 } 34 return result; 35 }
6, threeSum
1 vector<vector<int> > threeSumI(vector<int>& nums) { //跳过重复的数 2 vector<vector<int> > result; 3 const int target = 0; 4 vector<int>::iterator it; 5 for(it=nums.begin();it<nums.end()-2;++it) { // 遍历第一个数,剩余两个数进行夹逼 6 vector<int>::iterator j=it+1; 7 vector<int>::iterator k=nums.end()-1; 8 if(it!=nums.begin() && *it == *(it-1)) continue; 9 while(j < k) { 10 if(*it + *j + *k == target){ 11 result.push_back({*it,*j,*k}); 12 ++j; 13 --k; 14 while(*j == *(j-1) && *k = *(k+1) && j < k) ++j; // 跳过重复的数 15 } 16 else if(*it + *j + *k < target){ 17 ++j; 18 while(*j == *(j-1) && j < k) ++j; // 跳过重复 19 } 20 else { 21 --k; 22 while(*k = *(k+1) && j < k) --k; // 跳过重复 23 } 24 } 25 } 26 return result; 27 } 28 29 vector<vector<int>> threeSumII(vector<int>& nums) { //不跳过重复的数 ,最后直接去重 30 vector<vector<int>> result; 31 const int target = 0; 32 vector<int>::iterator it; 33 for(it=nums.begin();it<nums.end()-2;++it) { 34 vector<int>::iterator j=it+1; 35 vector<int>::iterator k=nums.end()-1; 36 if(it!=nums.begin() && *it == *(it-1)) continue; 37 while(j < k) { 38 if(*it + *j + *k == target){ 39 result.push_back({*it,*j,*k}); 40 ++j; 41 --k; 42 } 43 else if(*it + *j + *k < target){ 44 ++j; 45 } 46 else { 47 --k; 48 } 49 } 50 } 51 sort(result.begin(),result.end(),less<int>()); // 去重 52 result.erase(unique(result.begin(),result.end()),result.end()); 53 return result; 54 } 55 56 vector<vector<int>> threeSumIII(vector<int>& nums) { // STL::hashmap 57 vector<vector<int>> result; 58 map<int,vector<pair<int,int>>> cache; 59 const int target = 0; 60 if(nums.size()<3) return result; 61 sort(nums.begin(),nums.end()); 62 for(int i=0;i<nums.size();++i){ 63 for(int j=i+1;j<nums.size();++j) { 64 cache[nums[i]+nums[j]].push_back(make_pair(i,j)); 65 } 66 } 67 for(int i=0;i<nums.size();++i) { 68 const int key = target - nums[i]; 69 if(cache.find(key)==cache.end()) continue; 70 71 for(int j=0;j<cache[key].size();++j) { 72 if(i<=cache[key].second) //不会出现 [1,2,3],[1,3,2] [2,1,3]都被加入的情况,如果这行不写,最后需要对每个新加入的 vector 排序,然后加入,最后判重。 73 continue; 74 vector<pair<int,int>>& vec = cache[key]; 75 result.push_back({nums[vec[i].first],nums[vec[i].second],nums[i]}); 76 } 77 } 78 sort(result.begin(),result.end()); // 可能有重复值,必须去重!比如:nums=[0,0,0,0,0,0],target=0 79 result.erase(unique(result.begin(),result.end()),result.end()); 80 return result; 81 }
7, threeSumClose
1 int threeSumClose(vector<int>& nums,int target) { 2 int result = 0; 3 int minGap = INT_MAX; 4 sort(nums.begin(),nums.end()); 5 for(int i=0;i<nums.size()-2;++i) { 6 int j=i+1; 7 int k=nums.size()-1; 8 while(j<k) { 9 int sum = nums[i]+nums[j]+nums[k]; 10 int gap = abs(target-sum); 11 if(gap<minGap) { 12 result = sum; 13 minGap = gap; 14 } 15 if(sum<target) ++j; 16 else --k; 17 } 18 } 19 return result; 20 }
8, fourSum
1 vector<vector<int>> fourSum(vector<int>& nums,int target) { //先排序,在两边夹逼 2 vector<vector<int>> result; 3 if(nums.size()<4) return result; 4 sort(nums.begin(),nums.end()); 5 for(int a=0;a<nums.size()-3;++a) { 6 for(int b=a+1;b<nums.size()-2;++b) { 7 int c=b+1; 8 int d=nums.size()-1; 9 while(c < d) { 10 int sum = nums[a]+nums[b]+nums[c]+nums[d]; 11 if(sum==target) { 12 result.push_back({nums[a],nums[b],nums[c],nums[d]}); // 每次加入的 vector 都是升序的,hashmap 则不一定,需要判断!!! 13 ++c; 14 --d; 15 } 16 else if(sum < target) { 17 ++c; 18 } 19 else { 20 --d; 21 } 22 } 23 } 24 } 25 sort(result.begin(),result.end()); 26 result.erase(unique(rusult.begin(),result.end()),result.end()); 27 return result; 28 } 29 30 31 vector<vector<int>> fourSum(vector<int>& nums,int target) { // STL::hashmap 32 vector<vector<int>> result; 33 if(nums.size()<4) return result 34 sort(nums.begin(),nums.end()); 35 36 map<int,vector<pair<int,int>>> cache; 37 for(int a=0;a<nums.size();++a) { 38 for(int b=a+1;b<nums.size();++b) { 39 cache[nums[a]+nums[b]].push_back(make_pair(a,b)) 40 } 41 } 42 43 for(int c=0;c<nums.size();++c) { 44 for(int d=c+1;d<nums.size();++c) { 45 int key = target - nums[c] - nums[d]; 46 if(cache.find(key)==cache.end()) continue; 47 48 for(int i=0;i<cache[key].size();++i) { 49 if(c<=cache[key].second) continue; // 有重叠 50 vector<pair<int,int>>& vec = cache[key]; 51 result.push_back({nums[vec[i].first],nums[vec[i].second],nums[c],nums[d]}); 52 } 53 } 54 } 55 sort(result.begin(),result.end()); 56 result.erase(unique(result.begin(),result.end()),result.end()); 57 return result; 58 } 59
9, removeElement
1 int removeElement1(vector<int>& nums,int target) { // 重组 2 int index=0; 3 for(int i=0;i<nums.size();++i) { 4 if(nums[i]!=target) 5 nums[index++]=nums[i]; 6 } 7 return index; 8 } 9 10 int removeElement2(vector<int>& nums,int target) { // 覆盖 11 int index=0; 12 for(int i=0;i<nums.size();++i) { 13 if(nums[i]==target) 14 continue; 15 nums[index++]=nums[i]; 16 } 17 return index; 18 } 19 20 int removeElement3(vector<int>& nums,int target) { // STL::erase 21 vector<int>::iterator it=nums.begin(); 22 while(it!=nums.end()){ 23 if(*it==target) 24 it = nums.erase(it); 25 else 26 ++it; 27 } 28 return nums.size(); 29 } 30 31 int removeElement4(vector<int>& nums,int target) { // STL::distance STL::remove(类似于 unique函数) 32 return distance(nums.begin(),remove(nums.begin(),nums.end(),target)); 33 }
10, trapWater
1 int trapWater1(const vector<int>& heights) { // 左右扫描,动态规划思想 2 int result = 0; 3 const int n = heights.size(); 4 5 vector<int> maxLefts(n,0); 6 int maxLeftValue = 0; 7 for(int i=0;i<n;++i) { // 从左向右扫描,注意这种赋值方法 ,保持左边的最大值 8 maxLefts[i] = maxLeftValue; 9 maxLeftValue = max(maxLeftValue,heights[i]); 10 } 11 vector<int> maxRights(n,0); // 从右向左扫描,相同的赋值方法 ,保持右边的最大值 12 int maxRightValue = 0; 13 for(int j=n-1;j>=0;--j) { 14 maxRights[j] = maxRightValue; 15 maxRightValue = max(maxRightValue,heights[j]); 16 } 17 for(int k=0;k<n;++k) { 18 int diff = min(maxLefts[k],maxRights[k]); 19 if(diff>heights[k]) { 20 result += diff - heights[k]; 21 } 22 } 23 return result; 24 } 25 26 int trapWater2(const vector<int>& heights) { // 左右夹逼思想 27 int result=0; 28 int l=0,r=heights.size()-1; 29 while(l < r) { 30 int mn = min(heights[l],heights[r]); 31 if(mn == heights[l]) { 32 ++l; 33 while(mn>heights[l] && l < r) 34 result += mn - heights[l++]; 35 } 36 else { 37 --r; 38 while(mn > heights[r] && l < r) 39 result += mn - heights[r--]; 40 } 41 } 42 return result; 43 } 44 45 int trapWater3(const vector<int>& heights) { // 对每个可能存水的柱子进行讨论,动态规划用的数组类似缓存的作用 46 int result = 0; 47 const int n = heights.size()-1; 48 int maxLeft = 0; 49 int maxRight = 0; 50 for(int i=1;i<n-1;++i) { // 每一个可能存雨的柱子 51 for(int j=0;j<i;++j) { // 找左边最大的柱子 52 maxLeft = max(heights[j-1],heights[j]); 53 } 54 for(int k=i+1;k<n-1;++k) { // 找右边最大的柱子 55 maxRight = max(heights[k],heights[k+1]); 56 } 57 int diff = min(maxLeft,maxRight); 58 if(diff > heights[i]) 59 result += diff - heights[i]; 60 } 61 return result; 62 }
11, climbStairs
1 int climbStairs1(int n) { // 迭代 2 int prev = 0; 3 int curr = 1; 4 for(int i=1;i<=n;++i) { 5 int temp = curr; 6 curr = prev + curr; 7 prev = temp; 8 } 9 return curr; 10 } 11 12 int climbStairs2(int n) { // 递归(效率低) 13 if(n==1 || n==2) return n; 14 return climbStairs2(n-1) + climbStairs2(n-2); 15 } 16 17 int climbStairs3(int n) { // 数学公式法 18 const double s = sqrt(5); 19 return floor((pow((1+s)/2,n+1) + pow((1-s)/2,n+1))/s + 0.5); // 数学公式 20 }
12, grayCode
1 vector<int> grayCode1(int n){ // 数学公式方式 2 int size = 1 << n; //2^n 3 vector<int> result; 4 result.reserve(size); 5 for (int i = 0; i < size; ++i) 6 result.push_back(i ^ (i >> 1)); 7 return result; 8 } 9 10 vector<int> grayCode2(int n) { // 暂时未看懂 11 vector<int> result; 12 result.reserve(1 << n); 13 result.push_back(0); 14 for (int i = 0; i < n; ++i) { 15 const int highest_bit = 1 << i; 16 for (int j = result.size() - 1; j >= 0; --j) { 17 result.push_back(highest_bit | result[j]); 18 } 19 } 20 return result; 21 }
13, candy
1 int candy(vector<int>& ratings){ 2 const int n = ratings.size(); 3 vector<int> nums(n, 1); 4 for (int i = 0; i < n-1; ++i){ 5 if (ratings[i] < ratings[i+1]) 6 nums[i+1] = nums[i] + 1; 7 } 8 for (int j = n - 1; j>0; --j){ 9 if (ratings[j] < ratings[j - 1]) 10 nums[j - 1] = max(nums[j - 1], nums[j] + 1); 11 } 12 return accumulate(nums.begin(), nums.end(),0); 13 } 14 15 int candyII(vector<int>& ratings) { //思路同 上面 trapWater 的两次扫描 16 if (ratings.size() == 0) return 0; 17 vector<int> minLeft(ratings.size(), 1); 18 for (unsigned int i = 1; i<ratings.size(); ++i){ 19 if (ratings[i]>ratings[i - 1]) 20 minLeft[i] = minLeft[i - 1] + 1; 21 } 22 vector<int> minRight(ratings.size(), 1); 23 for (unsigned int j = ratings.size() - 2; j >= 0; --j){ 24 if (ratings[j]>ratings[j + 1]) //如果左边的等级高,而且左边的糖果又少的话 25 minRight[j] = max(minLeft[j], (minRight[j + 1] + 1)); 26 } 27 int result = 0; 28 for (unsigned int k = 0; k<ratings.size(); ++k) 29 result += max(minLeft[k], minRight[k]); //取从左边和右边都最小的值中的最大值,这样就满足所有条件了。 30 return result; 31 }
14,singleNumber(I)
1 #include<functional> //bit_xor<int>() 2 3 int singleNumber1(vector<int>& nums){ 4 int x = 0; 5 for (unsigned int i = 0; i < nums.size(); ++i) 6 x ^= nums[i]; 7 return x; 8 } 9 10 int singleNumber2(vector<int>& nums) { 11 return accumulate(nums.begin(), nums.end(), 0, bit_xor<int>()); 12 }
singleNumber(II)
1 int singleNumberII(vector<int>& nums) { 2 int result = 0; 3 for (int i = 0; i < 32; ++i){ 4 int sum = 0; 5 for (unsigned int j = 0; j < nums.size(); ++j){ 6 sum += (nums[j] >> i) & 1; // 求所有数的某一位是 1 的个数 7 } 8 result += (sum % 3) << i; // result |= (sum % 3) << i; 9 } 10 return result; 11 }
int singleNumberII2(vector<int>& nums) { const int W = sizeof(int)* 8; // 一个整数的位数 int count[W]; // count[i] 表示在第 i 位出现 1 的个数 for (size_t i = 0; i < nums.size(); ++i) { for (int j = 0; j < W; ++j) { count[j] += (nums[i] >> j) & 1; count[j] %= 3; } } int result = 0; for (int i = 0; i < W; ++i) { // 最后把唯一出现的数字计算出来 result += (count[i] << i); } return result; }
博客中的题目来源于:https://github.com/soulmachine/leetcode (leetcode-cpp.pdf)
所有博文均为原著,如若转载,请注明出处!