两种twoSum算法-java代码

题目描述:

给定一个已按照升序排列的整数数组nums,请从数组中找出满足两个数相加之和等于目标值target。
函数应该以长度为
2
*的整数数组的形式返回两个数的下标值。
每个输入只对应唯一的答案,而且不可以重复使用相同的元素。

示例 1:

输入: nums = [2, 9, 11, 13], target = 13
输出: [1, 2]
解释: 2 和 11之和等于目标数 13。 因此index1 = 1,index2 = 2。

示例 2:

输入: nums = [6, 9, 12], target = 18
输出: [1, 3]
解释: 6 和 12之和等于目标数 18。 因此index1 = 1,index2 = 3。

示例 3:

输入: nums = [-2, 0], target = -2
输出: [1, 2]
解释: -2 和 0之和等于目标数 -2。 因此index1 = 1,index2 = 2。

方法一:binarySearch

在数组中找到两个数,使得两元素之和sum等于目标值target,可以首先固定第一个元素,然后通过二分查找第二个元素:利用数组的升序排列的性质,第二个元素等于目标值减去第一个元素的值。为了避免重复查找,只在第一个元素的右侧查找第二个元素。 时间复杂度:O(nlogn),空间复杂度:O(1)。

	\\二分查找算法
public int[] twoSum(int[] nums, int target) {
    
    
	//判断数组是否为空
    if (nums == null || nums.length == 0) return new int[0];
    for (int i = 0; i < nums.length; i++) {
    
    
        int x = nums[i];
        // 线性查找 - O(n)
        // 1. 二分查找 - O(logn)
        // [i + 1, nums.length - 1] 区间二分查找 target - x
        int index = binarySearch(nums, target - x);
        if (index != -1) {
    
    
            return new int[]{
    
    i + 1, index + 1};
        }
    }
    return new int[0];
}

二分查找算法

public int binarySearch(int[] nums, int target) {
    
    
	int low = 0, high = nums.length - 1;//low、high分别表示为数组左侧低阶和数组右侧高阶的下标
    while (low <= high) {
    
    
        int mid = low + (high - 1)/2;//将数组从中间二分
        if (nums[mid] == target) {
    
    
            return mid;
            } else if (nums[mid] < target) {
    
    //如果中间元素<目标值,则继续[mid+1, high]二分循环查找
            low = mid + 1;
            }
        else {
    
    //如果中间元素>目标值,则继续[low, mid-1]二分循环查找
            high = mid - 1;
            }
    }
    return -1;//在这个函数中,如果有异常就返回-1,即 return -1; 
		//这是一种编程技巧,如果出现异常就通过返回-1就知道该函数出现异常
}

方法二:doublePointer

利用数组的升序排列的性质,所以只需要使用双指针,一个指针指向值较小的元素,一个指针指向值较大的元素。即. 指向较小的元素是从数组最开始从头向尾遍历,指向较大的元素是从数组最后面从尾往前遍历。

  1. 如果两个指针指向元素的之和 sum == target,那么得到要求的结果;
  2. 如果sum > target,移动较大的元素,使 sum 值变小;
  3. 如果sum < target,移动较小的元素,使 sum 值变大。

数组中的元素最多遍历一次,于是. 时间复杂度为O(N)。只使用两个额外的变量,空间复杂度为O(1)。

	\\双指针算法
public int[] doublePointer(int[] nums, int target) {
    
    
		//判断数组是否为空
		if (nums == null || nums.length == 0) return new int[0];	
		int left = 0;		//初始化数组开始位置的下标(左指针)
		int right = nums.length - 1;//初始化数组结束位置的下标(右指针)
		while (left < right) {
    
     //如果左指针出现在右指针右侧,结束循环
			int sum = nums[left] + nums[right];//求出左右指针位置值得和
			//比较目标值target与两指针之和的大小
			if (sum == target) {
    
    
				return new int[] {
    
    left + 1, right + 1};
			} else if (sum < target) {
    
    //两数之和小了,说面左指针处的值过小,左指针右移一位
				left++;	
			} else {
    
    //两数之和大了,说面右指针处的值过大,右指针左移一位
				right--;
			}
		}
		return new int[0];
	}

猜你喜欢

转载自blog.csdn.net/weixin_46439885/article/details/114282400