leetcode-167. 两数之和 II - 输入有序数组

78 阅读1分钟
import java.util.Arrays;

/**
 * ref:https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/
 * 给定一个已按照非递减顺序排列的整数数组numbers,请你从数组中找出两个数满足相加之和等于目标数target。
 * 函数应该以长度为2的整数数组的形式返回这两个数的下标值。numbers的下标从1开始计数,
 * 所以答案数组应当满足1<=answer[0]< answer[1]<= numbers.length 。
 * 你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
 * 示例 1:
 * 输入:numbers = [2,3,4], target = 6
 * 输出:[1,3]
 **/
public class SortedArrayTwoSumTarget {

    public static void main(String[] args){
        int[] array = new int[]{2,3,4};
        System.out.println(Arrays.toString(findByBinarySearch(array,6)));
        System.out.println(Arrays.toString(findByTwoPoint(array,6)));
    }

    /**
     * 将第一层循环的迭代下标作为左侧left=i,元素尾部下标作为右侧值right=array.length-1。
     * 第二层内循环采用二分查找:使用目标值与迭代值作差与迭代中中间值下标进行比较的方式。
     * 目标值target-迭代值array[i]和中间值下标mid=left+(right-left)的值array[mid]进行比较。
     * 如果array[mid]=target-array[i],则迭代结束,返回对应下标+1(题目要求下标从1开始)的值即可。
     * 如果array[mid]<target-array[i],则说明中值偏小,则left的值取中值+1=mid+1。继续下轮比较。
     * 如果array[mid]>target-array[i],则说明中值偏大,则right的取值中值-1=mid-1。继续下轮比较。
     * @param array
     * @param target
     * @return
     */
    public static int[] findByBinarySearch(int[] array,int target) {
        for(int i=0;i<array.length;i++){
            int left = i;
            int right = array.length - 1;
            while(left<=right){
                int mid = left+(right-left)/2;
                if(array[mid]==target-array[i]){
                    return new int[]{i+1,mid+1};
                }else if(array[mid]<target-array[i]){
                    left = mid+1;
                }else{
                    right = mid-1;
                }
            }
        }
        return new int[]{};
    }

    /**
     * 双指针方:
     * 使用两个值分别代表数组下标,左侧下标left值小,右侧下标right的值大。
     * left值从0开始递增,由小到大。right值从array.length-1开始递减,由大到小。
     * 当循环至left的值大于等于right时,迭代结束。
     * 在循环过程中,比较两个下标对应数组元素值之和与target大小。
     * 如果array[left]+array[right]=target,则迭代结束,返回对应下标+1(题目要求下标从1开始)的值即可。
     * 如果array[left]+array[right]>target,则说明之和偏大,需要迭代小点的值,即right值-1。继续下轮比较。
     * 如果array[left]+array[right]<target,则说明之和偏小,需要迭代大点的值,即left值+1。继续下轮比较。
     * @param array
     * @param target
     * @return
     */
    public static int[] findByTwoPoint(int[] array,int target) {
        int left = 0;
        int right = array.length-1;
        while(left<=right){
            if(array[left]+array[right]==target){
                return new int[]{left+1,right+1};
            }else if(array[left]+array[right]>target){
                right--;
            }else{
                left++;
            }
        }
        return new int[]{};
    }

}