算法 - 两数之和
题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
有两种解法:
- 解法一:
传统的二次循环,空间复杂度为O(1),空间复杂度为O(n^2)
class Solution {
/**
* @param Integer[] $nums
* @param Integer $target
* @return Integer[]
*/
function twoSum($nums, $target) {
$subscriptArr = [];
$len = count($nums);
for ($i = 0; $i < $len - 1; $i ++) {
for ($j = $i + 1; $j < $len ; $j++) {
if ($nums[$i] + $nums[$j] == $target) {
$subscriptArr = [$i, $j];
}
}
}
return $subscriptArr;
}
}
- 解法二:
先将数组变为有序,再进行左右分别相加,类二分法的解法
class Solution {
/**
* @param Integer[] $nums
* @param Integer $target
* @return Integer[]
*/
function twoSum($nums, $target) {
if (!is_array($nums) || count($nums) < 2) {
return [];
}
$sortArr = $nums;
asort($sortArr);
$sortArr = array_values($sortArr);
$len = count($nums);
$left = 0;
$right = $len - 1;
$firNum = $secNum = null;
while ($left < $right) {
if ($sortArr[$left] + $sortArr[$right] == $target) {
$firNum = $sortArr[$left];
$secNum = $sortArr[$right];
break;
}
$sortArr[$left] + $sortArr[$right] > $target ? $right-- : $left++;
}
if (is_null($firNum) || is_null($secNum)) {
return [];
}
$fir = array_search($firNum, $nums);
// 删除是为了满足相同vaule时,只取到第一个值的情况,如:[3, 3]
unset($nums[$fir]);
$sec = array_search($secNum, $nums);
return [$fir, $sec];
}
}
- 方法三:
解题的要点思路在于$num = $target - $nums[$i];
寻找目标值和当前值的差值是否存在于数组中。
要注意的是:差值不能为当前值本身
class Solution {
/**
* @param Integer[] $nums
* @param Integer $target
* @return Integer[]
*/
function twoSum($nums, $target) {
if (!is_array($nums) || count($nums) < 2) {
return [];
}
$len = count($nums);
$firNum = $secNum = null;
for ($i = 0; $i < $len; $i++) {
$num = $target - $nums[$i];
if (in_array($num, array_slice($nums, $i + 1))) {
$firNum = $i;
unset($nums[$i]);
$secNum = array_search($num, $nums);
break;
}
}
if (is_null($firNum) || is_null($secNum)) {
return [];
}
return [$firNum, $secNum];
}
}