问题:给定一个数组A和一个目标T,检查A中是否存在一个对的总和为T。
如果您是面试准备之旅的开始,这通常是您遇到的第一个。
让我们分解一下。
问我们要做什么?
- 我们得到了一个数组,该数组可以排序或不排序。 令A [] = [2,5,1,6,8,3,4,7]
- 给定目标T = 15
- We've to return check if there exists a pair which sum to t, ie let x & y be two elements in A such that x+y = T. We have to find those two elements.
天真/蛮力方法:
Brute force approach would be to search for each x & y pairs which would sum to target T:
public class Solution {
//brute force O(n^2) time O(1) space
public int[] twoSum(int[] nums,int target){
for(int i=0;i<nums.length-1;i++){
for(int j=i;j<nums.length;j++){
if(nums[i]+nums[j] == target) return new int[]{i,j};
}
}
return new int[]{-1,-1};
}
这将生成所有可能的对,并将返回与条件匹配的第一对,现在让我们考虑一个情况,其中Give数组为
A = [1,2,3,4,5,6,7,8] Target = 15
在这种情况下,将生成[1,2],[1,3],[1,4],[1,5] .. [7,8]的所有可能组合。
改善:
让我们考虑一下我们可以使用的东西,如何在以前的最坏情况下处理数组,以减少现在的时间,最坏的情况发生在我们必须搜索整个数组并且结果位于 最后ie [7,8]?
- Sorting and Two pointers: if we sort the array A, then A becomes [1,2,3,4,5,6,7,8]. How can we use this to our advantage? let's assign two pointers, start and end. start = 0 & end = nums.length-1; here we observe that if
- nums [start] + nums [end] ==目标,我们已经解决了。
- nums[start] + nums[end] > target, we've too much of the bigger number, so decrement end.
- nums[start] + nums[end] < target, we've too less of the smaller number, so increment start. But here we face a caveat since we're expected to return the indices of the elements in the array. For that we do:
- 在数组中搜索开始和结束元素。
int[] nums2 = Arrays.copyOf(nums, nums.length);
Arrays.sort(nums2);
int a = 0, b = 0;
int start = 0, end = nums2.length-1;
//find two nums
while(start<end){
int sum = nums2[start] + nums2[end];
if(sum < target)
start++;
else if(sum > target)
end--;
else{
a = nums2[start]; b = nums2[end];
break;
}
}
//find the index of two numbers
int[] res = new int[2];
for(int i = 0; i < nums.length; i++){
if(nums[i] == a){
res[0] = i;
break;
}
}
if(a != b){
for(int i = 0; i < nums.length; i++){
if(nums[i] == b){
res[1] = i;
break;
}
}
} else{
for(int i = 0; i < nums.length; i++){
if(nums[i] == b && i != res[0]){
res[1] = i;
break;
}
}
}
return res;
}
此时,面试官应该对您正在接近感到满意,但他会问
“我们可以做得更好吗?”
是的,我们可以。
- HashMap:HashMap存储对,我们使用此属性存储索引和总和。 我们将target-num [i]存储为键,将索引i存储为值。 让我们经历一下: 对于数组[2,5,1,6,8,3,4,7]和target = 15,存储的键值对为:
2 > 15-2 = 13 <13,0>
5 > 15-5 = 10 <10,1>
1 > 15-1 = 14 <14,2>
6 > 15-6 = 9 < 6,3>
8 > 15-8 = 7 < 7,4>
3 > 15-3 = 12 <12,5>
4 > 15-4 = 11 <11,6>
7 > now here is where the magic happens, since at index 4, element 8, we stored <7,4> in hashMap, it means that we need that and we've seen 15-7 = 8 at position 4. which means we've found the solution. return the current index of 7 ie 7 and index of 8 ie 4.
Map<Integer,Integer> map = new HashMap<>();
int[] res = new int[]{-1,-1};
for(int i=0;i<nums.length;i++){
if(map.containsKey(nums[i])){
res[1] = i;
res[0] = map.get(nums[i]);
}else{
map.put(target-nums[i],i);
}
}
return res;
}
希望你喜欢这个旅程.
Github链接 : https://github.com/AKHILP96/Data-Structures-and-Algorithms/blob/master/problems/TwoSum.java