目录
前言
一、 暴力求解
二、 二分查找
三、相向双指针
前言
题目描述:
给你一个下标从 1 开始的整数数组 numbers,该数组已按非递减顺序排列(即从小到大排列,中间可以有数字重复),请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2],则 1 <= index1 < index2 <= numbers.length。
以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。
你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
你所设计的解决方案必须只使用常量级的额外空间。
示例 1:
输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
示例 2:
输入:numbers = [2,3,4], target = 6
输出:[1,3]
解释:2 与 4 之和等于目标数 6 。因此 index1 = 1, index2 = 3 。返回 [1, 3] 。
示例 3:
输入:numbers = [-1,0], target = -1
输出:[1,2]
解释:-1 与 0 之和等于目标数 -1 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
提示:
-
2 <= numbers.length <= 3 * 10^4
-
-1000 <= numbers[i] <= 1000
-
numbers
按 非递减顺序 排列 -
-1000 <= target <= 1000
-
仅存在一个有效答案
一、 暴力求解
/*** Note: The returned array must be malloced, assume caller calls free().*/int* twoSum(int* numbers, int numbersSize, int target, int* returnSize)
{*returnSize = 2;int* returnArray = (int*)malloc(sizeof(int) * 2);int i = 0;int j = 0;for (i = 0; i < numbersSize - 1; i++){for (j = i + 1; j < numbersSize; j++){if (numbers[i] + numbers[j] == target){returnArray[0] = i + 1;returnArray[1] = j + 1;goto end; // 跳出两层 for 循环}}}
end:return returnArray;
}
注意:虽然在题目描述中整数数组 numbers 的下标是从 1 开始的,但是实际上数组的下标是从 0 开始的,所以当从数组中找到满足相加之和等于目标数 target 的两个数时,要把这两个数对应的数组下标加 1。
二、 二分查找
暴力解法中并没有利用到数组已按非递减顺序排列这一已知条件。
/*** Note: The returned array must be malloced, assume caller calls free().*/int* twoSum(int* numbers, int numbersSize, int target, int* returnSize)
{*returnSize = 2;int* returnArray = (int*)malloc(sizeof(int) * 2);int i = 0;for (i = 0; i < numbersSize - 1; i++){int left = i + 1;int right = numbersSize - 1;while (left <= right){int mid = (left + right) / 2;int sum = numbers[i] + numbers[mid];if (sum > target){right = mid - 1;}else if (sum < target){left = mid + 1;}else{returnArray[0] = i + 1;returnArray[1] = mid + 1;goto end; // 跳出 while 循环和 for 循环}}}
end:return returnArray;
}
三、相向双指针
/*** Note: The returned array must be malloced, assume caller calls free().*/int* twoSum(int* numbers, int numbersSize, int target, int* returnSize)
{*returnSize = 2;int* returnArray = (int*)malloc(sizeof(int) * 2);int left = 0;int right = numbersSize - 1;while (left < right){int sum = numbers[left] + numbers[right];if (sum > target){right--;}else if (sum < target){left++;}else{returnArray[0] = left + 1;returnArray[1] = right + 1;break; // 跳出 while 循环}}return returnArray;
}
示例:
输入:numbers = [2,3,4,6,8],target = 9
输出:[2,4]
分析:
-
numbers[0] + numbers[4] = 2 + 8 = 10 > target,由于数组已按非递减顺序排列,所以 numbers[4] 和数组中其他任意数字的和都大于 target,因此删除这种可能,即让 right--。
-
numbers[0] + numbers[3] = 2 + 6 = 8 < target,由于数组已按非递减顺序排列,所以numbers[0] 和数组中其他任意数字的和都小于 target,因此删除这种可能,即让 left++。
-
numbers[1] + numbers[3] = 3 + 6 = 9 = target。