Two Sum(初谈双指针)

来源:互联网 发布:excel两个表格数据对比 编辑:程序博客网 时间:2024/05/22 13:06

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

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,当然收获也是良多的,这道题也有哈希的做法,现在还不是很懂,在后面的学习中会慢慢补上这一部分,也会谈一下对栈、堆的理解。新手上路,错误之处,还望指正!

4 3