题目
分析
看完题目首先可以考虑直接暴力破解,不过O(n*2)的时间复杂度会超时,需要降低时间复杂度。
1.先进行一个快排,两个指针分别指向首(i)尾(j),若和大于要求值则 j--,否则i++
2.先进行一个快排,再在数组中通过二分查找另一个数。
题解
1.
void swap(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
return;
}
void sort(int arr[],int ind[],int left,int right)
{
if(left>right)
return;
int i=left;
int j=right;
int mid=(left+right)/2;
swap(&arr[mid],&arr[left]);
swap(&ind[mid],&ind[left]);
int temp=arr[left];
while(i!=j)
{
while(arr[j]>=temp && i<j)
j--;
while(arr[i]<=temp && i<j)
i++;
if(i<j)
{
swap(&arr[i],&arr[j]);
swap(&ind[i],&ind[j]);
}
}
swap(&arr[i],&arr[left]);
swap(&ind[i],&ind[left]);
sort(arr,ind,left,i-1);
sort(arr,ind,i+1,right);
}
另外一个数组是为了在交换的时候将下标号也跟着交换。
int *twoSum(int numbers[], int n, int target) {
int *a=(int *)malloc(2*sizeof(int));
int *index=(int *)malloc(n*sizeof(int));
for(int i=0;i<n;i++)
index[i]=i+1;
a[0]=a[1]=-1;
sort(numbers,index,0,n-1);
int i=0;
int j=n-1;
while (i!=j) {
if(numbers[i]+numbers[j]==target)
{
if(index[i]>index[j])
{
a[0]=index[j];
a[1]=index[i];
}
else
{
a[0]=index[i];
a[1]=index[j];
}
break;
}
else if(numbers[i]+numbers[j]<target)
i++;
else
j--;
}
return a;
}
2.
int search(int arr[],int value,int left,int right)
{
if(left>right)
return -1;
int mid=(left+right)/2;
if(arr[mid]==value)
return mid;
else if (arr[mid]>value)
return search(arr,value,left,mid-1);
else
return search(arr,value,mid+1,right);
}
swap函数和sort函数同解1.
int *twoSum(int numbers[], int n, int target) {
int *a=(int *)malloc(2*sizeof(int));
int *index=(int *)malloc(n*sizeof(int));
for(int i=0;i<n;i++)
index[i]=i+1;
a[0]=a[1]=-1;
sort(numbers,index,0,n-1);
for(int i=0;i<n;i++)
{
int j=search(numbers,target-numbers[i],i+1,n-1);
if(j!=-1)
{
if(index[i]>index[j])
{
a[0]=index[j];
a[1]=index[i];
}
else
{
a[0]=index[i];
a[1]=index[j];
}
break;
}
}
return a;
}
再说说快排
int mid=(left+right)/2;
swap(&arr[mid],&arr[left]);
swap(&ind[mid],&ind[left]);
快排里面有这神奇的三句,是因为再没加之前是超时的,错误的例子是一个递增的长序列。
在这个递增的长序列中,不论是以最左边为参照还是以最右边为参照都会全部进行比较,时间复杂度为O(N*2)
这样还是过不去的(如果这样都能过,不如直接写两层for循环)
于是投机的把最中间的值先换到了左边,再也左边为参照,一次全部交换完毕才通过了测试。
不仅能写出算法,还
知道它最适合的情景和最不适合的情景 也是很重要的。
再试试桶排序
int *twoSum(int numbers[], int n, int target) {
int *a=(int *)malloc(2*sizeof(int));
int *index=(int *)malloc(40000*sizeof(int)); //定义40000个桶 默认值为-1
for(int i=0;i<40000;i++)
index[i]=-1;
for(int i=0;i<n;i++) //将元素的索引存在 值+1000 的地桶里
{
index[numbers[i]+1000]=i;
}
int temp,j;
for(int j=0;j<n;j++)
{
temp=index[target-numbers[j]+1000]; // 查找另一个数时,查找该数值+1000的桶里有没有不为-1的排号
if(temp!=-1 && temp!=j) // 不为-1的排号 且与第一个数索引不同 则为另一个值的索引
{
if(j>temp)
{
a[0]=temp+1;
a[1]=j+1;
}
else
{
a[0]=j+1;
a[1]=temp+1;
}
return a;
}
}
}
加1000是为了使得下标值都为正数
试试C++
class Solution {
public:
vector<int> twoSum(vector<int> &numbers, int target) {
vector<int> results;
multimap<int, int> iimmap;
for(int i=0; i<numbers.size(); i++){
iimmap.insert(pair<int, int>(numbers[i], i));
}
for(int i=0;i<numbers.size();i++)
{
if(iimmap.count(target-numbers[i]))
{
int n=iimmap.find(target-numbers[i])->second;
if(n<i)
{
results.push_back(n+1);
results.push_back(i+1);
return results;
}
else if(n>i)
{
results.push_back(i+1);
results.push_back(n+1);
return results;
}
}
}
}
};
思路同桶排序一样,不过更简单,不用考虑数组下标为负时需要做的偏移。用到了:
1.multimap的插入,直接插入pair<int,int>类型的数据
2.通过multimap.count(key)来统计是否有key主键存入
3.multimap.find(key)得到指向key的iterator iterator->second获得了key对应的value值,也就是我们需要的索引值。
简单点
class Solution {
public:
vector<int> twoSum(vector<int> &numbers, int target) {
map<int, int> iimmap;
vector<int> results;
for(int i=0; i<numbers.size(); i++){
if(iimmap.count(target-numbers[i])){
int n=iimmap.find(target-numbers[i])->second;
results.push_back(n+1);
results.push_back(i+1);
return results;
}
iimmap.insert(pair<int, int>(numbers[i], i));
}
return results;
}
};
用JAVA的Hashmap
public class Solution {
public int[] twoSum(int[] numbers, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < numbers.length; i++) {
if (map.containsKey(target - numbers[i])) {
return new int[] { map.get(target - numbers[i]) + 1, i + 1 };
}
map.put(numbers[i], i);
}
throw new IllegalArgumentException("No two sum solution");
}
}
其实上面的两次for循环只是为了看起来理解更方便,实际上一次for循环就能解决。