LeetCode每日打卡---两数之和 II - 输入有序数组

154 阅读2分钟

答案唯一,第一想法必然有双重循环来遍历的想法

 public static int[] twoSum(int[] numbers, int target) {
        int[] index=new int[2];
        for (int i = 0; i < numbers.length; i++) {
            for (int j = i+1; j <numbers.length ; j++) {
                if(numbers[i]+numbers[j]==target){
                    index[0]=i+1;
                    index[1]=j+1;
                    break;
                }
            }
        }
        return index;
    }

非常简单的思路
执行

太菜了所以开始优化。
首先是对空间复杂度进行优化,现在的空间复杂度为O(1)是常数所以没法优化,
但是双循环必然是没有必要的,所以对时间复杂度O(i**2)下手
由题意得数组由小到大排序,故当numbers[i]+numbers[j]>targets时,j再增大就显然无意义,顾可以尝试增加判断,若和大于则终止遍历
代码如下

public static int[] twoSum1(int[] numbers, int target) {
        int[] index=new int[2];
        for (int i = 0; i < numbers.length; i++) {
            a :for (int j = i+1; j <numbers.length ; j++) {
               if (numbers[i]+numbers[j]>target){
                   break a;
               }
                if(numbers[i]+numbers[j]==target){
                    index[0]=i+1;
                    index[1]=j+1;
                    break;
                }
            }
        }
        return index;
    }

效果如下

执行时间大幅缩短了,所以对于起始像是不是也可以进行优化呢?
如果头加尾都不够大,就只能提前进入下一个循环了
可是设计完以后告诉我超出时间了= =,我也是哭了,明明就用时少啊 估计是判断语句太多了不如循环来的快
于是有了最后的双指针法
具体思路,当头+尾<target时,前端+1,若>target则后端-1

   public int[] twoSum(int[] numbers, int target) {
      int[] index=new int[2];
        int len =numbers.length;
        int high=len-1;
        int i=0;
        while (i<high){
           if (numbers[i]+ numbers[high]<target){
               i++;
           }if (numbers[i]+ numbers[high]>target){
               high--;
           }
           if (numbers[i]+ numbers[high]==target){
               return new int[]{i+1,high+1};
           }

        }
        return new int[]{-1,-1};
    
    }

这最后的内存我想肯定有其他办法搞