我正在尝试对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)
因此,我想知道这是否是与语法相关的错误。我正在尝试检查两个数字加起来是否为另一个数字。
由于这是尝试递归解决方案的幼稚尝试,因此我很乐意接受其他批评。但是我最关心的是让我尝试解决这个问题并在所有测试用例中运行。
谢谢。
答案 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());
}
}
您需要了解几件事:
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};
}