Leetcode题库-两数之和 II - 输入有序数组(java语言版)

题目描述:

给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。

函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2

说明:

  • 返回的下标值(index1 和 index2)不是从零开始的。
  • 你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。

示例:

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

     这道题和题库中的第一道题特别相似,唯一的不同就是这道题输入的是一个排序数组。方法也特别类似。详细请看第一篇博客:

https://blog.csdn.net/weixin_37850160/article/details/86500847

     本题主要有三种方法:

     第一种方法:暴力for循环:就是两重for循环挨个找,找到就返回对应的下标+1的值(因为返回的下标值(index1 和 index2)不是从零开始的。)。时间复杂度O(n^2).不推荐,简单但是时间复杂度太高。

     第二种方法:map:将数组中的元素当作键,下标当作值,存储到map中。然后循环遍历原数组,判断目标数-数组中的元素是否在map中存在,并且,i还要小于,存在时的这个键对应的值的下标。满足这两个条件,然后输出数组对应的下标i,和map中满足条件的值。

      第三种方法:对撞指针法:们首先判断首尾两项的和是不是 target,如果比 target 小,那么我们左边 (i)+1 位置的数(比左边位置的数大)再和右相相加,继续判断。如果比 target 大,那么我们右边 (j)-1 位置的数(比右边位置的数小)再和左相相加,继续判断。我们通过这样不断放缩的过程,就可以在 O(n) 的时间复杂度内找到对应的坐标位置。

     具体看代码:

第一种方法:

  Scanner sc  = new Scanner ( System.in );
        int target = sc.nextInt ();
        int []a = new int[]{2,5,6,7,11,15};
//        第一种方法,for暴力求解,时间复杂度高
//        index1 和 index2,其中 index1 必须小于 index2
        for (int i = 0;i<a.length;i++){
            for (int j = i+1;j<a.length;j++){
                  if (a[i]+a[j]==target&&i<j){
                      System.out.println("["+(i+1)+","+(j+1)+"]");
                  }
            }
        }

执行结果:

运行时间:

第二种方法:

//        第二种方法,map存储,时间复杂度低O(n)
        Map<Integer,Integer> map = new HashMap <> (  );
        for (int i = 0;i<a.length;i++){
              map.put ( a[i],i );
        }
        for (int i = 0;i<a.length;i++){
              if (map.containsKey (target-a[i])&&i<map.get ( target-a[i])){
                  System.out.println("["+(i+1)+","+(map.get ( target-a[i])+1)+"]");
              }

        }

执行时间:

第三种方法:

//        第三种对撞指针法(首位各一个指针):
//        首先判断首尾两项的和是不是 target,如果比 target 小,那么我们左边 (i)+1 位置的数(比左边位置的数大)再和右相相加,继续判断。如果比 target 大,那么我们右边 (j)-1 位置的数(比右边位置的数小)再和左相相加,继续判断。我们通过这样不断放缩的过程,就可以在 O(n) 的时间复杂度内找到对应的坐标位置。
        int j= a.length-1;
        for (int i = 0;i<a.length;){
             if (a[i]+a[j]<target&&i<j){
                 i++;
             }else if (a[i]+a[j]>target&&i<j){
                 j--;
             }else{
                 System.out.println("["+(i+1)+","+(j+1)+"]");
                 break;
             }
        }
    }

执行时间:

 总结:这道题思路方法很多,但推荐使用第三种或者第二种方法,时间复杂度小,代码简单容易理解。 

 2019-3-6

发布了43 篇原创文章 · 获赞 6 · 访问量 6674

猜你喜欢

转载自blog.csdn.net/weixin_37850160/article/details/88262094