玩转算法(八)——查找表(数字之和)

数字之和类型

1. 两数之和(简单)

思路一:先排序再使用双指针。时间复杂度为O(nlogn)。但是本题,排序后索引改变了,会有点麻烦。

leetcode中167题,可直接用双指针进行求解。

思路二:使用哈希表,需要注意的是,不能先把数组中所有数据都放入哈希表,因为重复的数会被覆盖,需要建立一个指针从第一个数往后移动,指针之前的数放入哈希表 ,指针的数和之前的哈希表进行计算。时间复杂度为O(n)。

1. 两数之和

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. 三数之和(中等)

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. 四数之和(中等)

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. 最接近的三数之和(中等)

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值