15. 3Sum
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.
Note: The solution set must not contain duplicate triplets.
Solution: 去重之后使用二分查找Code:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> answer;
sort(nums.begin(),nums.end());
for(int i=0; i<nums.size(); i++){
if(i>0 && nums[i-1]==nums[i]) continue;//用于去重
for(int t=i+1; t<nums.size()-1; t++){
if(t>i+1 && nums[t-1]==nums[t]) continue; //用于去重
vector<int>::iterator it;
it = lower_bound (nums.begin()+t+1, nums.end(), -1*(nums[i]+nums[t]));
//注意:find函数并不是使用二分法进行查找
//二分查找的函数为:lower_bound 和 upper_bound
if (it!=nums.end() && *it == -1*(nums[i]+nums[t])){
vector<int> a;
a.push_back(nums[i]);
a.push_back(nums[t]);
a.push_back(*it);
answer.push_back(a);
}
}
}
return answer;
}
};
81. Search in Rotated Sorted Array II
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7
might become 4 5 6 7 0 1 2
).
Write a function to determine if a given target is in the array.
The array may contain duplicates.
Solution(1): 直接查找并不超时
Code:
class Solution {
public:
bool search(vector<int>& nums, int target) {
for(int i=0; i<nums.size(); i++){
if(nums[i]==target)
return true;
}
return false;
}
};
Code:
class Solution {
public:
bool search(vector<int>& nums, int target) {
int start = 0;
int end = nums.size();
int mid = (start+end)/2;
//使用循环实现的二分查找
while(start<end){
if(nums[mid]==target)
return true;
else if(nums[mid]<nums[end-1]){
if(target==nums[end-1])
return end-1;
else if(nums[mid]<target && target<nums[end-1])
start = mid+1;
else
end = mid;
}
else if(nums[start]<nums[mid]){
if(target==nums[start])
return true;
else if(nums[start]<target && target<nums[mid])
end = mid;
else
start = mid+1;
}
else{
mid = mid+1;
if(mid>=end){
end = (start+end)/2;
mid = (start+end)/2;
}
continue;
}
mid = (start+end)/2;
}
return false;
}
};
4. Median of Two Sorted Arrays
There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
Solution(1): 归并(merge)之后输出中位数
Code:
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
vector<int> newnums;
int i,j;
for(i=0,j=0; i<nums1.size()&&j<nums2.size(); ){
if(nums1[i]<nums2[j]){
newnums.push_back(nums1[i]);
i++;
}
else{
newnums.push_back(nums2[j]);
j++;
}
}
//注意边界的情况
for(int t=i; t<nums1.size(); t++){
newnums.push_back(nums1[t]);
}
for(int t=j; t<nums2.size(); t++){
newnums.push_back(nums2[t]);
}
if(newnums.size()%2==1){
return newnums[newnums.size()/2];
}else{
return (newnums[newnums.size()/2]+newnums[newnums.size()/2-1])*1.0/2;
}
}
};
Solution(2): 二分,这个题可以一般化为:找到两个有序数组中,第k小的元素。
首先这两个数组分别贡献出一部分的数据,组合成一个大小为k的新数组。如果两个数组比k/2要大的话,就各提供k/2个数,否则size小与k/2的数组将所有数据加入,不足的部分由大一些的数组提供。
然后比较a(nums[k/2-1])和b(nums[k/2-1])的大小,此时分为三种情况:
(1)a>b:
此时比b小的数据一定在a之前,因此nums2[0]至nums2[k/2-1](b) 一定不包含我们需要找到的目标数,即第k小的数,如图所示:
此外,nums1[k/2]至nums1[size-1]中也一定不存在目标数:
因此我们可以排除掉一半的数据:nums1[k/2]-nums1[size-1] 和 nums2[0]至nums2[k/2-1]
(2)a<b: 同理,此情况可以排除掉nums2[k/2]-nums2[size-1] 和 nums1[0]至nums1[k/2-1];
(3)a==b: a和b一定是第k小的数,比a和b小的只有它们之前的k-2个数。
因为nums1和nums2中排除掉了一个用于比较的数据(即a或者b),因此无法继续排除的情况等同于无法选出a和b的情况,此时即为递归的边界条件:
(1)nums1和nums2中有一个数组为空,此时即全部数据有序,可以直接选出第k小的数;
(2)k==1,此时直接选出两个数组中最小的数据进行比较,更小的即为全局最小。
注意:因为除去了比目标数小的数据(nums1[0]-nums1[k/2-1]或者nums2[0]-nums2[k/2-1]),因此在下一次递归时要注意将k减掉这么多。
Code:
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int size = nums1.size() + nums2.size();
if(size%2!=0)
return find_kth(nums1.begin(), nums1.size(), nums2.begin(), nums2.size(), (size/2)+1);
else
return (find_kth(nums1.begin(), nums1.size(), nums2.begin(), nums2.size(), size/2)
+ find_kth(nums1.begin(), nums1.size(), nums2.begin(), nums2.size(), (size/2)+1))/2;
}
private:
double find_kth(vector<int>::iterator it1, int size1, vector<int>::iterator it2, int size2, int k){
//cout<<size1<<" "<<size2<<" k="<<k<<endl;
if(size1>size2) return find_kth(it2, size2, it1, size1, k);//避免分类讨论
//递归终止条件
if(size1==0) return *(it2+(k-1));
if(k==1) return min(*it1, *it2);
int p1 = min(size1, k/2);//避免数组越界
int p2 = k - p1;
int value1 = *(it1+(p1-1));
int value2 = *(it2+(p2-1));
if(value1<value2) return find_kth(it1+p1, size1-p1, it2, p2, k-p1);
if(value1>value2) return find_kth(it1, size1, it2+p2, size2-p2, k-p2);
if(value1==value2) return value2;
}
};