数字之和类型
1. 两数之和(简单)
思路一:先排序再使用双指针。时间复杂度为O(nlogn)。但是本题,排序后索引改变了,会有点麻烦。
leetcode中167题,可直接用双指针进行求解。
思路二:使用哈希表,需要注意的是,不能先把数组中所有数据都放入哈希表,因为重复的数会被覆盖,需要建立一个指针从第一个数往后移动,指针之前的数放入哈希表 ,指针的数和之前的哈希表进行计算。时间复杂度为O(n)。
public int[] twoSum(int[] nums, int target) {
int[] result = new int[2];
HashMap<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if(map.containsKey(complement)) {
result[0] = i;
result[1] = map.get(complement);
return result;
}
map.put(nums[i], i);
}
return null;
}
15. 三数之和(中等)
思路一:先排序再使用双指针。这题适合这种方法,虽然有3个数,只需将一个数当成target就行。比如 0 - nums[0] 当成target,把第一个数分离成target后,再从nums[1]到数组最后,进行双指针遍历。
思路二:能否像上题一样,不排序就只进行哈希表的操作呢?会返回很多相同的值,比较麻烦,如果题目像leetcode中167题一样,只需返回一组答案,则可以用这个方法。
public static List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> list = new ArrayList<List<Integer>>();
Arrays.sort(nums);
for(int i = 0; i < nums.length-2; i++) {
int target = 0 - nums[i];
if (i > 0 && nums[i] == nums[i - 1]) continue;
int left = i + 1;
int right = nums.length - 1;
while(left < right) {
if(nums[left] + nums[right] < target)
left++;
else if(nums[left] + nums[right] > target)
right--;
else {
List<Integer> list2= new ArrayList<Integer>();
list2.add(nums[i]);
list2.add(nums[left]);
list2.add(nums[right]);
list.add(list2);
left++; right--;
while (left < right && nums[left] == nums[left - 1]) left++;
while (left < right && nums[right] == nums[right + 1]) right--;
}
}
}
return list;
}
18. 四数之和(中等)
思路:和上题一样,选出两个数去当target即可,剩下的两个数,则进行前后双指针遍历。
public static List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> list = new ArrayList<List<Integer>>();
Arrays.sort(nums);
for(int i = 0; i < nums.length-3; i++) {
if (i > 0 && nums[i] == nums[i - 1])
continue;
for(int j = i + 1; j < nums.length-2; j++) {
int target2 = target - nums[i] - nums[j];
if (j > i + 1 && nums[j] == nums[j - 1])
continue;
int left = j + 1;
int right = nums.length - 1;
while(left < right) {
if(nums[left] + nums[right] < target2)
left++;
else if(nums[left] + nums[right] > target2)
right--;
else {
List<Integer> list2= new ArrayList<Integer>();
list2.add(nums[i]);
list2.add(nums[j]);
list2.add(nums[left]);
list2.add(nums[right]);
list.add(list2);
left++; right--;
while (left < right && nums[left] == nums[left - 1]) left++;
while (left < right && nums[right] == nums[right + 1]) right--;
}
}
}
}
return list;
}
16. 最接近的三数之和(中等)
思路相同,略。
public static int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
int interval = 999, closest = 0;
for(int i = 0; i < nums.length-2; i++) {
int target2 = target - nums[i];
int left = i + 1;
int right = nums.length - 1;
while(left < right) {
if(nums[left] + nums[right] < target2) {
int abNum = Math.abs(nums[left] + nums[right] - target2);
if(abNum < interval) {
interval = abNum;
closest = nums[left] + nums[right] + nums[i];
}
left++;
}
else {
int abNum = Math.abs(nums[left] + nums[right] - target2);
if(abNum < interval) {
interval = abNum;
closest = nums[left] + nums[right] + nums[i];
}
right--;
}
}
}
return closest;
}