您的位置:首页 > 其它

Two Sum(初谈双指针)

2016-04-10 12:59 405 查看
昨天晚上遇到这么一个题目,然后听到了关于“双指针”的使用。好了,言归正传,先来看一看这个题目:

Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because
nums[0] + nums[1] = 2 + 7 = 9, return [0, 1].

1. 嵌套循环解法

首先说一下我自己在面向这个题的时候的解法:首先,我认为对该无序数组进行排序,目的是为了减少遍历时间。以题目给的数据为例:

sort(nums, nums + numsSize);
int *Result = (int*)malloc(sizeof(int)* 2);
for (int i = 0; i < numsSize - 1; i++){
for (int j = i + 1; j < numsSize; j++){
if (nums[i] + nums[j] == target){    //写入
Result[0] = nums[i];
Result[1] = nums[j];
}
if (nums[i] + nums[j] > target)    //跳出判断
break;
}
}

return Result;


但是,在通过第一组测试数据之后,出现了新的问题:

Example:
Given nums = [3, 2, 4], target = 6,
Because
nums[1] + nums[2] = 2 + 4 = 6, return [1, 2].
但是由于在前面经过了排序,数组元素的下标已经改变,所以,最后的输出结果变成了[0, 2]。

于是,不得不采用最原始的解决办法,嵌套循环全部遍历,虽然大大增加了运算时间,但是总算解决了问题,当然,代码实现也就更简单了,具体代码如下:

int *Result = (int*)malloc(sizeof(int)* 2);
for (int i = 0; i < numsSize - 1; i++){
for (int j = i + 1; j < numsSize; j++){
if (nums[i] + nums[j] == target){
Result[0] = i;
Result[1] = j;
}
}
}

return Result;


这里还有一个细节的问题,就是这个:int *Result = (int)malloc(sizeof(int)* 2);

一开始的时候,返回的这个数组我是直接定义的:int Result[2];

但是发现返回后在主函数内打印是不可行的,虽然后来改为了动态分配解决了这个问题,但是并不知道原因所在,现在了解到:

函数内开辟的这个数组空间,是存在于栈当中的,函数在完成功能后,当时使用的内存空间是拒绝再被访问的,你返回的那个数组的首地址—Result,也是毫无意义,然后动态分配的空间是存在于堆当中的,是一个共享的空间,大家都可以使用,所以,即使函数完成了功能,也是可以被主函数访问的。

关于堆和栈的更多详细的内容,我借鉴前辈的经验,也写了一点,有兴趣的可以到这里去看看关于堆和栈(直接点我)

2.双指针解法

双指针解法的优化之处在于仅需要一次遍历就可以达到目的。好,直接进入主题:

首先对该无序数组进行排序,随后用两个变量指向数组的开头和结尾:这里我们使用low和high,分别指向nums[0]和nums[numsSize];因为已经进行过排序,如果nums[low]+nums[high] < target,则说明low指向的数太小,需要往后移动;反之,则是high指向的数太大,需要前移,当两者相等,遍历结束 。

完全代码如下:

int compi(const void *a, const void *b){    //C的qsort要用的函数
return (*(int*)a - *(int*)b);
}

int* twoSum(int* nums, int numsSize, int target){
bool flag = true;
int* Result = (int*)malloc(sizeof(int)* 2);
int* temp = (int*)malloc(sizeof(int)*numsSize);  //复制数组来找真正的下标

for (int i = 0; i < numsSize; i++)
temp[i] = nums[i];

qsort(nums, numsSize,sizeof(nums[0]),compi);
int low = 0;
int high = numsSize - 1;

while (low < high){
if (nums[low] + nums[high] < target)
low++;
else if (nums[low] + nums[high] > target)
high--;
else
break;
}
//flag用于解决nums[low]和nums[high]相等造成无法给Result[1]赋值的情况
for (int i = 0; i < numsSize; i++){
if (temp[i] == nums[low] && flag==true)
{
Result[0] = i;
flag = false;
}
if (temp[i] == nums[high])
{
Result[1] = i;
}
}
//如果返回数组的数值大小不正确,交换
if (Result[0] > Result[1]){
int temp = Result[0];
Result[0] = Result[1];
Result[1] = temp;
}

return Result;
}


修改了好一阵子,终于给了AC,当然收获也是良多的,这道题也有哈希的做法,现在还不是很懂,在后面的学习中会慢慢补上这一部分,也会谈一下对栈、堆的理解。新手上路,错误之处,还望指正!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: