167. 两数之和 II - 输入有序数组(暴力+二分查找+相向双指针)
迪丽瓦拉
2024-05-02 09:43:41
0

目录

前言

一、 暴力求解

二、 二分查找

三、相向双指针



前言

题目描述

给你一个下标从 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]

分析

  1. numbers[0] + numbers[4] = 2 + 8 = 10 > target,由于数组已按非递减顺序排列,所以 numbers[4] 和数组中其他任意数字的和都大于 target,因此删除这种可能,即让 right--。

  2. numbers[0] + numbers[3] = 2 + 6 = 8 < target,由于数组已按非递减顺序排列,所以numbers[0] 和数组中其他任意数字的和都小于 target,因此删除这种可能,即让 left++。

  3. numbers[1] + numbers[3] = 3 + 6 = 9 = target。

相关内容