算法:给定一个整型数组,找出两个整数为指定整数的和

mac2025-04-15  3

题目

给定一个整型数组,是否能找出其中的两个数使其和为某个指定的值?(假定是无序数组)

解法一:暴力破解(穷举法,不提倡)

/** * 给定一个整型数组,是否能找出其中的两个数使其和为某个指定的值?(假定是无序数组) * 暴力破解 (穷举,时间复杂度:O(n^2),正常不会用这个,假如只是为了快速解题,对时间没有限制,用这个最简单) * * @param nums 无序整形数组 * @param target 和值 */ public static void search1(int[] nums, int target) { int one, two; for (int i = 0; i < nums.length; i++) { one = nums[i]; two = target - one; for (int j = 0; j < nums.length; j++) { if (i != j) { if (two == nums[j]) { System.out.println("one:" + one + " two:" + two); return; } } } } System.out.println("找不到这两个数"); }

解法二:二分法(相当于用两个指针)

/** * 两个指针二分查找--重点是先使数组有序 * (排序时间复杂度为O(nlog(n)),while最多O(N),所以最终程序的时间复杂度为:O(nlo(n))) * * @param nums 无序整形数组 * @param target 和值 */ public static void search2(int[] nums, int target) { System.out.println("二分查找(两个指针二分查找,时间复杂度:O(nlog(n)))"); // 1.排列(用的是Dual-Pivot Quicksort(快速排序),时间复杂度为O(nlog(n))) // ****此处是重点**** Arrays.sort(nums); // 2.类二分查找 int left = 0; int right = nums.length - 1; // for(;left < right;) while (left < right) { int sum = nums[left] + nums[right]; if (sum == target) { System.out.println("one:" + nums[left] + " two:" + nums[right]); return; } if (sum < target) {// 太小 left增加 left++; } if (sum > target) {// 太大 right减少 right--; } } System.out.println("找不到这两个数"); }

解法三:使用哈希表和辅助空间

/** * 使用辅助空间(使用哈希表,时间复杂度是O(n),空间复杂度:O(n),n是数组大小) * 把数值作为 key,它的下标作为 value 遍历数组,判断 map 是否含有这个目标值-当前数值, 有直接返回,没有的话放到map里面 * * 所以以后写代码,如果有双层 for 循环,首先考虑一下能否用 map 替换一层 * * 空间换时间的方式,用hashmap来记录值和index,这样只要遍历一遍,并用Hashmap直接判定是否存在另一个下标。 * 这种方法有一个问题,就是当存在相同值时,并且恰好求和的两个数是同值不同位时,必然会出问题。修正方式是 * hashmap中的value用list或者set来存储,那么如果最终两个值对应的index set不同,或者index set相同但set * size>1,那么就是存在。 */ public static void search3(int[] nums, int target) { Map<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { if (map.containsKey(target - nums[i])) { System.out.println("one:" + nums[i] + " two:" + (target - nums[i])); return; } map.put(nums[i], i); } System.out.println("找不到这两个数"); }

拓展题目

设计一个类,包含如下两个成员函数(允许整数集合中存在相同值的元素): 

save(int input) 插入一个整数到一个整数集合里。 test(int target) 检查是否存在两个数和为输入值。如果存在着两个数,则返回true,否则返回false  import java.util.HashMap; import java.util.Iterator; /** * 设计一个类,包含如下两个成员函数(允许整数集合中存在相同值的元素): * save(int input) 插入一个整数到一个整数集合里。 * test(int target) 检查是否存在两个数和为输入值。如果存在着两个数,则返回true,否则返回false * * @author kongshubin * */ public class TwoNumberOfSum { // key:数值,value:数值对应的个数 HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(); /** * 插入一个整数到一个整数集合里 * * @param input */ public void save(int input) { int count = 0; if (map.containsKey(input)) { count = map.get(input); } map.put(input, count + 1); } /** * 检查是否存在两个数和为输入值 * * @param target * @return 如果存在着两个数,则返回true,否则返回false */ public boolean test(int target) { Iterator<Integer> iterator = map.keySet().iterator(); while (iterator.hasNext()) { int one = iterator.next(); int two = target - one; if (map.containsKey(two)) { System.out.println("one:" + one + " two:" + two); if (!(target == two << 1 && map.get(two) == 1)) { // 如果target为two的2倍,并且只有一个two不同时成立,返回true return true; } } } return false; } public static void main(String[] args) { TwoNumberOfSum t = new TwoNumberOfSum(); t.save(5); t.save(10); t.save(4); t.save(7); System.out.println(t.test(12)); } }

 

最新回复(0)