面试题57:和为s的数字
题目一:和为 s 的两个数字
输入一个递增排序的数组和一个数字,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。
思路1:利用hash表
用hash表记录每个数字出现的次数,然后再次遍历数组,当遍历到某个值为 val 时,就判断 target - val 在不在数组中。
代码实现:
package Question57;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class T01 {
public static void main(String[] args) {
int[] arr = {1, 3, 4, 5 ,5};
System.out.println(Arrays.toString(solve2(arr, 10)));
}
public static int[] solve(int[] arr, int target) {
Map<Integer, Integer> map = new HashMap<>();
for(int data : arr) {
if(!map.containsKey(data)) map.put(data, 1);
else map.put(data, map.get(data) + 1);
}
for(int data : arr) {
if(target - data == data && map.get(data) > 1) return new int[]{data, data};
else if(map.containsKey(target - data)) return new int[]{data, target-data};
}
return new int[0];
}
}
思路2:使用双指针(看代码就懂了)
代码实现:
package Question57;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class T01 {
public static void main(String[] args) {
int[] arr = {1, 3, 4, 5 ,5};
System.out.println(Arrays.toString(solve2(arr, 10)));
}
public static int[] solve2(int[] arr, int target) {
int left = 0, right = arr.length - 1;
while(left < right) {
if(arr[left] + arr[right] > target) right--;
else if(arr[left] + arr[right] < target) left++;
else return new int[]{arr[left], arr[right]};
}
return new int[0];
}
}
题目二:和为 s 的连续正数序列
输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个数)。
思路:滑动窗口
- 初始化一个滑动窗口 {1,2},并用两个指针(samll,big)分别记录第一个元素和最后一个元素。用temp表示窗口内所有元素之和。
- 如果temp<target,说明窗口内的值需要增大,则big++,temp+=big
- 如果temp>target,说明窗口内的值需要减小,则temp-=small;small++
- 如果temp==target,记录本次的窗口元素,然后temp-=small;small++
- 终止条件 big <= (target + 1) / 2
代码实现:
package Question57;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
public class T02 {
public static void main(String[] args) {
int[][] ans = solve(5);
for(int[] data : ans) {
System.out.println(Arrays.toString(data));
}
}
public static int[][] solve(int target) {
List<int[]> result = new ArrayList<int[]>();
int small = 1, big = 2;
int temp = small + big;
while(big <= (target+1) / 2) {
if(temp > target) {
temp -= small;
small++;
} else if(temp < target) {
big++;
temp += big;
} else {
int[] ans = new int[big-small+1];
for(int i = 0; i < ans.length; i++) ans[i] = i + small;
result.add(ans);
temp -= small;
small++;
}
}
int[][] ret = new int[result.size()][];
for(int i = 0; i < ret.length; i++) ret[i] = result.get(i);
return ret;
}
}