【问题标题】:Two Sum LeetCode Java Questions两个求和 LeetCode Java 问题
【发布时间】:2018-07-28 20:40:25
【问题描述】:

我正在尝试在 LeetCode 上进行 Java 模拟面试。我有以下问题:

给定一个整数数组,返回两个数字的索引,使它们相加到一个特定的目标。

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

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)

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

if ((sumnums[i]+sumnums[j])==t){

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

由于这是对递归解决方案的幼稚尝试,因此我很乐意接受任何其他批评。但我最关心的是让我在这个问题上的尝试能够与所有测试用例一起工作和运行。

谢谢。

【问题讨论】:

  • sumnums.length 将是 2,而现有的唯一索引是 0 和 1。您可能打算这样做 int j = sumnums.length - 1
  • 谢谢。我的疏忽。至少这解决了我遇到的问题。

标签: java arrays recursion


【解决方案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 中,则检查其补集(目标 - 元素)是否也存在于 Map 中。如果存在补码,则返回当前元素的索引和补码。 否则,将元素放入 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.使用Sorting和双指针滑动窗口的方法 当您需要返回数字而不是它们的索引时,还有另一种方法可以使用。以下是它的工作原理:

对数组进行排序。 初始化两个变量,一个指向数组的开头(左),另一个指向数组的结尾(右)。 循环直到左

如果 arr[left] + arr[right] == target,则返回索引。 如果 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[] {};
}

【讨论】:

    【解决方案2】:

    正如你所说 首先是 2。这里我们将检查 (9 - 2),即 7 在 hashmap 中不存在

    其实7确实存在于HashMap右边 nums = [2, 7, 11, 15], 目标 = 9

    【讨论】:

      【解决方案3】:
      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;
      
          }
      

      【讨论】:

        【解决方案4】:

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

        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]]
        

        【讨论】:

          【解决方案5】:

          我使用更简单的方法

          类解决方案{ 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;
          }
          

          }

          【讨论】:

            【解决方案6】:

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

            它的工作原理如下: 考虑nums = [2, 7, 11, 15], target = 9

            我们将开始迭代数组

            首先是 2。这里我们将检查 (9 - 2),即 7 在 hashmap 中不存在,所以我们将存储 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};
                }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-04-16
              • 2022-06-12
              • 2020-05-01
              • 2020-03-02
              • 1970-01-01
              相关资源
              最近更新 更多