题目
题意
给一个int型数组无序,从数组中选出两数字,使得这两数字之和为target,将这两数字的下标作为数组返回。(一定存在一个解)
注意:对代码进行优化,可能会超时。
思路
因为要输出原来数组的下标,就要先将原来的数组的顺序进行保存,即另外申请一片空间将这个数组拷贝过去,然后再对这个数组进行升序排序,声明两个指针low,和high,分别指向数组的第一个元素和最后一个元素,从两边开始向中间判断,两个数相加是否为target,再根据具体情况移动指针,low++或者high–;因为必有一解,所以就不用考虑指针越界了。直到找到符合要求的两个目标数据,这时可以通过low指针和high指针知道这两个数据的值,再在原来的数组中遍历寻找这两个数,记下他的数组下标即可。
代码
int* twoSum(int* nums, int numsSize, int target) {
int i, j, temp, *num2;
num2 = (int *)malloc(sizeof(int)*numsSize);//原来的数组排序后数组目标数据的下标将会改变,但又需要返回原来的位置,因此需要用另一个数组将原来数组的顺序保存下来
for (i = 0; i < numsSize; i++)
{
num2[i] = nums[i];//拷贝数据
}
//将原来的数组先利用冒泡排序进行升序排序
for (i = 0; i < numsSize - 1; i++)
{
for (j = 0; j < numsSize - 1 - i; j++)
{
if (nums[j] > nums[j + 1])
{
temp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = temp;
}
}
}
int *low = nums, *high = &nums[numsSize - 1];//声明两个指针,low指向数组第一个元素,high指向数组最后一个元素
int *r = (int*)malloc(sizeof(int) * 2);
while (*low + *high != target)//循环找到两个目标数据的值
{
if (*low + *high < target)
{
low++;
}
if (*low + *high > target)
{
high--;
}
}
int k = 0;//为了防止两个数相同,防止将两个数的下标都记在r[0]中
for (i = 0; i < numsSize; i++)//通过目标数据的值从原来的数组中遍历找到目标数据原来的位置
{
if (num2[i] == *low && k!=1)
{
r[0] = i;
k = 1;
}
if (num2[i] == *high)
{
r[1] = i;
}
}
return r;
}
注意
代码经过了很多次修改才终于通过,每一次换了不同测试数据就又发现一点小错误。
1.最开始的时候没有将原来的数组保存,直接用原来的数组遍历,得到的就是已经排序后的数组的下标,后改正。
2.后来测试时有个数组中有重复的数据,nums={0,2,4,0},target=0;于是在遍历的时候,两个零的数组下标都存入了r[0]中,且后一个更新了前一个的下标,使得r[0]=3,r[1]中没有存入任何下标,输出了一个错误的值,所以,为了防止r[0]的重复记录,我声明了一个变量k来记录r[0]是否已经记录了数组下标。