题意:给你一个包含n个数的数组,要求找出两个数,使得他们的和等于指定的数target。
思路:先在[1,n]之间确定一个index1,然后再在[index1+1,n]之间找index2,使得nums[index1]+num[index2]==target.按照这种思路不做任何优化,时间复杂度为O(n^2).
优化:先将数组排序,这样在找index2的时候就可以用二分查找了.时间复杂度O(nlogn)
排序后改变了原数组元素的位置,所以我的做法是先保存原数组,最后再根据找到的两个数反过去去找对应在原数组的位置。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
int n=nums.size();
vector<int>nums_back=nums;//保存原数组
Sort(nums,n);
int index1,index2=-1;
long low,mid,up;
vector<int>ans;
for(index1=1;index1<=n;index1++)
{
if(index2!=-1)
break;
low=index1+1;up=n;
while(low<=up)
{
mid=(low+up)>>1;
if(nums[mid-1]==target-nums[index1-1])
{
index2=mid;
index1--;
break;
}
else if(nums[mid-1]<target-nums[index1-1])
low=mid+1;
else
up=mid-1;
}
}
//找在原数组中对应的位置
for(int i=0;i<n;i++)
if(nums_back[i]==nums[index1-1]||nums_back[i]==nums[index2-1])
ans.push_back(i+1);
return ans;
}
//堆排序
void Sort(vector<int>& nums,int n)
{
int i;
for(i=n>>1;i;i--)
Adjust(nums,i,n);
for(i=n-1;i;i--)
{
swap(nums[0],nums[i]);
Adjust(nums,1,i);
}
}
void Adjust(vector<int>& nums,int i,int n)
{
int lchild=i<<1;
int rchild=lchild+1;
int max=i;
if(lchild<=n&&nums[max-1]<nums[lchild-1])
max=lchild;
if(rchild<=n&&nums[max-1]<nums[rchild-1])
max=rchild;
if(i!=max)
{
swap(nums[max-1],nums[i-1]);
Adjust(nums,max,n);
}
}
};