/**
* 题目描述:给定⼀个数组和⼀个⽬标和,从数组中找两个数字相加等于⽬标和,输出这两个数字的下标。
* 其中两数之和等于目标数, 只有一解
* 难度:简单
*/
public class Test01 {
public static void main(String[] args) {
int[] nums = {11,15,2,7};
int target = 9;
int[] ints1 = twoSum01(nums, target);
int[] ints2 = twoSum02(nums, target);
int[] ints3 = twoSum03(nums, target);
System.out.println(Arrays.toString(ints1));
System.out.println(Arrays.toString(ints2));
System.out.println(Arrays.toString(ints3));
}
/**
* 解法一:循环, 两个指针, 从左到右移动依次相加判断是否相等
* 双层循环
* 时间复杂度:两层 for 循环,O(n²)
* 空间复杂度:O(1)
* @param nums
* @param target
*/
public static int[] twoSum01(int[] nums, int target){
int [] ans = null;
for(int i=0; i< nums.length -1; i++) {
for(int j = (i+1);j< nums.length; j++){
if(nums[i]+nums[j] == target) {
ans=new int[2];
ans[0] = i;
ans[1] = j;
return ans;
}
}
}
return ans;
}
/**
* 解法二: 双层循环 改成单层循环, map 记录值和下标的信息
* 时间复杂度:⽐解法⼀少了⼀个 for 循环,降为 O(n)
* 空间复杂度:所谓的空间换时间,这⾥就能体现出来, 开辟了⼀个 hash table ,空间复杂度变为 O(n)
*
* sub=target-nums[i]
* if(nums[j]==sub){}
* 有没有⼀种⽅法,不⽤遍历就可以找到元素⾥有没有等于 sub 的?
* hash table !!!
* 我们可以把数组的每个元素保存为 hash 的 key,下标保存为 hash 的 value
* 另外排除重复使用同一个元素, 也就是本身
* @param nums
* @param target
* @return
*/
public static int[] twoSum02(int[] nums, int target){
int [] ans = null;
Map<Integer,Integer> map=new HashMap<>();
for (int i = 0; i < nums.length; i++) {
map.put(nums[i], i);
}
for (int i = 0; i < nums.length; i++) {
int sub = target - nums[i];
if (map.containsKey(sub) && map.get(sub)!=i) {
ans=new int[2];
ans[0] = i;
ans[1] = map.get(sub);
return ans;
}
}
return ans;
}
/**
* 解法三: 优化解法二,变为一个for
* 变化
* 仅仅是不需要判断是不是当前元素了,因为当前元素还没有添加进 hash ⾥
* @param nums
* @param target
* @return
*/
public static int[] twoSum03(int[] nums, int target){
int [] ans = null;
Map<Integer,Integer> map=new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int sub = target - nums[i];
if (map.containsKey(sub)) {
ans=new int[2];
ans[0] = i;
ans[1] = map.get(sub);
return ans;
}
map.put(nums[i], i);
}
return ans;
}
}