题目一:两数之和Ⅰ
示例:
解题思路:当看到这道题的时候,我最开始的思路是先确定一个元素 nums[i] ,nums[j],(j = i + 1),然后通过循环去遍历整个数组,查找是否存在 nums[i] + nums[j] == target;这样通过枚举的方法,它的时间复杂度是 O(N^2),空间复杂度是 O(1)。刚好最近学习了哈希表,我又想到快速寻找数组中是否存在目标元素的方法,这样就可以大大简化算法的时间复杂度了。
方法一:暴力枚举
public Solution {
public int[] twoSum(int[] nums,int target){
for(int i = 0;i < nums.length;i++){
for(int j = i + 1;j < nums.length;j++){
if(nums[i] + nums[j] == target){
return new int[] {i,j};
}
}
}
return new int[0];
}
}
方法二:哈希表
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> hashtable = new HashMap<Integer, Integer>();
for (int i = 0; i < nums.length; ++i) {
if (hashtable.containsKey(target - nums[i])) {
return new int[]{hashtable.get(target - nums[i]), i};
}
hashtable.put(nums[i], i);
}
return new int[0];
}
}
题目二:两数之和Ⅱ - 输入有序数组
示例:
解题思路:这道题也可以使用题目一中的两个方法,但是这两种解法都是针对无序数组的,没有利用到输入数组有序的性质。利用输入数组有序的性质,可以得到时间复杂度和空间复杂度更优的解法。
方法一:二分查找
class Solution {
public int[] twoSum(int[] numbers, int target) {
for (int i = 0; i < numbers.length; ++i) {
int low = i + 1, high = numbers.length - 1;
while (low <= high) {
int mid = (high - low) / 2 + low;
if (numbers[mid] == target - numbers[i]) {
return new int[]{i + 1, mid + 1};
} else if (numbers[mid] > target - numbers[i]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
}
return new int[]{0,0};
}
}
方法二:双指针
class Solution {
public int[] twoSum(int[] numbers, int target) {
int low = 0, high = numbers.length - 1;
while (low < high) {
int sum = numbers[low] + numbers[high];
if (sum == target) {
return new int[]{low + 1, high + 1};
} else if (sum < target) {
++low;
} else {
--high;
}
}
return new int[]{-1, -1};
}
}
题目三:两数之和Ⅲ - 数据结构设计
示例:
解题思路:twoSum题的拓展,设计一个数据结构,实现添加数字和找目标数字的功能。用 HashMap 来存数字和查找。
代码示例
public class TwoSum {
private HashMap<Integer, Integer> elements = new HashMap<Integer, Integer>();
public void add(int number) {
if (elements.containsKey(number)) {
elements.put(number, elements.get(number) + 1);
} else {
elements.put(number, 1);
}
}
public boolean find(int value) {
for (Integer i : elements.keySet()) {
int target = value - i;
if (elements.containsKey(target)) {
if (i == target && elements.get(target) < 2) {
continue;
}
return true;
}
}
return false;
}
}
题目四:两数之和Ⅳ - 输入BST
示例:
解题思路:我们可以使用深度优先搜索的方式遍历整棵树,用哈希表记录遍历过的节点的值。对于一个值为 xx 的节点,我们检查哈希表中是否存在 k - xk−x 即可。如果存在对应的元素,那么我们就可以在该树上找到两个节点的和为 kk;否则,我们将 xx 放入到哈希表中。如果遍历完整棵树都不存在对应的元素,那么该树上不存在两个和为 kk 的节点。
代码示例
class Solution {
Set<Integer> set = new HashSet<Integer>();
public boolean findTarget(TreeNode root, int k) {
if (root == null) {
return false;
}
if (set.contains(k - root.val)) {
return true;
}
set.add(root.val);
return findTarget(root.left, k) || findTarget(root.right, k);
}
}