LeetCode Java Sum两个问题

时间:2018-07-28 20:40:26

标签: java arrays recursion

我正在尝试对LeetCode进行Java模拟采访。我有以下问题:

给出一个整数数组,返回两个数字的索引,以便它们加起来成为一个特定的目标。

您可以假设每个输入都只有一个解决方案,并且您可能不会两次使用相同的元素。

@property
def stay_time(self):
    return (self.departure_date-self.allotment_date)

我正在尝试实施递归解决方案。但是,尝试运行代码时收到错误消息。

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

错误:

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] sumnums = nums.clone();
        //int[2] sol = {0,1};
        int[] sol = new int[]{0,1};

        sol = new int[2];
        int j=sumnums.length;
        int t=target;

        for(int i=0;i<sumnums.length;i++){
            if ((sumnums[i]+sumnums[j])==t){
                sol[0]=i;
                sol[1]=j;
                //return sol;
            }
        }
        j=j-1;
        twoSum(sumnums,t);
        return sol;

    }
}

在我看来,该错误可能与以下代码行有关:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
    at Solution.twoSum(Solution.java:12)
    at __DriverSolution__.__helper__(__Driver__.java:8)
    at __Driver__.main(__Driver__.java:54)

因此,我想知道这是否是与语法相关的错误。我正在尝试检查两个数字加起来是否为另一个数字。

由于这是尝试递归解决方案的幼稚尝试,因此我很乐意接受其他批评。但是我最关心的是让我尝试解决这个问题并在所有测试用例中运行。

谢谢。

6 个答案:

答案 0 :(得分:1)

方法1.天真的方法:使用两个for循环 天真的方法是只使用两个嵌套的for循环,并检查数组中任何两个元素的总和是否等于给定的目标。

时间复杂度:O(n ^ 2)

 // Time complexity: O(n^2)
private static int[] findTwoSum_BruteForce(int[] nums, int target) {
    for (int i = 0; i < nums.length; i++) {
        for (int j = i + 1; j < nums.length; j++) {
            if (nums[i] + nums[j] == target) {
                return new int[] { i, j };
            }
        }
    }
    return new int[] {};
}

方法2.使用HashMap(最有效) 您可以使用HashMap解决O(n)时间复杂度的问题。步骤如下:

初始化一个空的HashMap。 遍历数组的元素。 对于数组中的每个元素- 如果地图中存在该元素,请检查地图中是否还存在补码(目标-元素)。如果补码存在,则返回当前元素和补码的索引。 否则,将元素放在Map中,然后移至下一个迭代。 时间复杂度:O(n)

 // Time complexity: O(n)
private static int[] findTwoSum(int[] nums, int target) {
    Map<Integer, Integer> numMap = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        int complement = target - nums[i];
        if (numMap.containsKey(complement)) {
            return new int[] { numMap.get(complement), i };
        } else {
            numMap.put(nums[i], i);
        }
    }
    return new int[] {};
}

方法3.将排序与两点滑动窗口方法一起使用 当您需要返回数字而不是其索引时,还有另一种方法有效。运作方式如下:

排序数组。 初始化两个变量,一个变量指向数组的开头(左),另一个指向数组的结尾(右)。 循环直到左<右,并且每次迭代

如果arr [left] + arr [right] ==目标,则返回索引。 如果arr [left] + arr [right] <目标,则增加左索引。

否则,递减正确的索引。 这种方法称为两指针滑动窗口方法。这是解决数组相关问题的非常常见的模式。

时间复杂度:O(n * log(n))

 // Time complexity: O(n*log(n))
private static int[] findTwoSum_Sorting(int[] nums, int target) {
    Arrays.sort(nums);
    int left = 0;
    int right = nums.length - 1;
    while(left < right) {
        if(nums[left] + nums[right] == target) {
            return new int[] {nums[left], nums[right]};
        } else if (nums[left] + nums[right] < target) {
            left++;
        } else {
            right--;
        }
    }
    return new int[] {};
}

答案 1 :(得分:1)

您提到过 首先是2。在这里,我们将检查(9-2)即哈希映射中不存在7

HashMap权利中确实存在

7 nums = [2,7,11,15],目标= 9

答案 2 :(得分:0)

public static int[] twoSum(int[] nums, int target) {
        int[] sumnums = nums.clone();
        //int[2] sol = {0,1};
        int[] sol = new int[]{0,1};

        sol = new int[2];
        int j=sumnums.length; // Every recursion j will be initialized as sumnums.length instead of J-1
        int t=target;

        for(int i=0;i<sumnums.length;i++){
           // if ((sumnums[i]+sumnums[j])==t){  
           // Remember that Java arrays start at index 0, so this value(sumnums[j]) is not exist in the array.
              if ((sumnums[i]+sumnums[j-1])==t){
                sol[0]=i;
                sol[1]=j;
                return sol;
            }
        }
        j=j-1;
        twoSum(sumnums,t);
        return sol;

    }

答案 3 :(得分:0)

许多可能的解决方案之一:

public class TwoSumIndex {
    public static void main(String... args) {
    int[] arr = {2, 7, 11, 15, 9, 0, 2, 7};
        System.out.println(findTwoSums(arr, 9));
    }

    private static List<List<Integer>> findTwoSums(int[] arr, int target) {
        Set<Integer> theSet = Arrays.stream(arr).mapToObj(Integer::valueOf).collect(Collectors.toSet());
        List<Integer> arrList = Arrays.stream(arr).mapToObj(Integer::valueOf).collect(Collectors.toList());
        List<Pair<Integer, Integer>> theList = new ArrayList<>();
        List<Integer> added = new ArrayList<>();
        for (int i = 0; i < arr.length; i++) {
            int a = target - arr[i];
            if (theSet.contains(a) && added.indexOf(i) < 0) { // avoid duplicates;
                Integer theOther = arrList.indexOf(a);
                theList.add(new Pair(i, theOther));
                added.add(i);
                added.add(theOther);
            }
        }
        return theList.stream().map(pair -> new ArrayList<>(Arrays.asList(pair.getKey(), pair.getValue())))
                .collect(Collectors.toList());
    }
}

您需要了解几件事:

    允许在输入数组中
  1. 重复
  2. 允许输入中无序数组;
  3. 输出中没有重复的索引对;
  4. 时间复杂度在理论上为O(N^2),但实际上会更低,因为theSet.contains(a) O(logN)会过滤掉所有失败索引,然后进行索引重复 O(N)检查,因此实际时间复杂度应为O(NlogN);

演示的输出:

[[0, 1], [4, 5], [6, 1], [7, 0]]

答案 4 :(得分:0)

我使用更简单的方法

class解决方案{     public int [] twoSum(int [] nums,int target){

     int[] indices= new int[2];
    int len=nums.length;
    for(int i=0; i<len; i++){

            for(int j=i+1; j<len;j++){         

                if((nums[i]+nums[j])==target){
                    indices[0] = i;
                    indices[1] = j;
                    return indices;

                }
            }


    }
     return null;
}

}

答案 5 :(得分:0)

为什么不使用HashMap?这是它将如何工作的。我们将遍历数组,并检查映射中是否存在target - nums[i]。如果没有,我们将分别存储Key, Value作为数字及其索引,即K = nums[i], V = i

这是它如何工作的: 考虑nums = [2, 7, 11, 15], target = 9

我们将开始迭代数组

首先出现2。在这里,我们将检查(9-2)即7在哈希图中不存在,因此我们将2作为键存储,将其索引0存储为值

然后是7。在这里,我们将检查(9-7)即地图中存在的2,因此我们将返回索引2和索引7,即返回[0,1]

public int[] twoSum(int[] nums, int target) {

        HashMap<Integer,Integer> map = new HashMap<>();
         for(int i = 0; i < nums.length; i++) 
         {
             if(map.containsKey(target - nums[i])) 
             {
                 return new int[] {map.get(target-nums[i]),i};

             }
             else
                 map.put(nums[i],i);
         }
         return new int[] {-1,-1};
    }