1. 两数之和
方法一:暴力枚举
思路及算法:
枚举数组中的每一个数X,寻找数组中是否存在target - X。当使用遍历整个数组的方式寻找 target – X 时,需要注意到每一个位于 X 之前的元素都已经和 X 匹配过,因此不需要再进行匹配。而每一个元素不能被使用两次,所以我们只需要在X后面的元素中寻找target - X。
代码:
1 C: 2 /** 3 * Note: The returned array must be malloced, assume caller calls free(). 4 * 这句话的意思就是新建数组时需要使用malloc函数。 5 */ 6 int* twoSum(int* nums, int numsSize, int target, int* returnSize) { 7 for (int i = 0; i < numsSize; ++i) { 8 for (int j = i + 1; j < numsSize; ++j) { 9 if (nums[i] + nums[j] == target) { 10 int* ret = malloc(sizeof(int) * 2); 11 ret[0] = i, ret[1] = j; 12 *returnSize = 2; 13 return ret; 14 } 15 } 16 } 17 *returnSize = 0; 18 return NULL; 19 }
复杂度分析:
- 时间复杂度:,其中N是数组中的元素数量。最坏情况下数组中任意两个数都要被匹配一次。
- 空间复杂度:。
提交结果:
上述暴力枚举代码只能通过78/80的测试用例,提交结果是运行超时,原因在于时间复杂度较高。
方法二:哈希表
思路及算法:
在遍历的同时,记录一些信息,省去一层循环,以“空间换时间”。需要记录遍历过的数值和它对应的下标,可以通过查找表实现。一种是哈希表,一种是平衡二叉树(需要维护元素的顺序)。
从头开始遍历,目标值是8,第一个数是6,需要寻找2,不在哈希表中,将6放入哈希表中,遍历下一个数。第二个数是3,需要寻找5,不在哈希表中,将3放入哈希表中,遍历下一个数。第三个数是8,需要寻找0,不在哈希表中,将8放入哈希表中,遍历下一个数。第四个数是2,需要寻找6,在哈希表中,将6的下标与2的下标输出。
代码:
1 Java: 2 class Solution { 3 public int[] twoSum(int[] nums, int target) { 4 //设置hash表长度 5 int len = nums.length; 6 //定义hash表 7 Map<Integer, Integer> hashtable = new HashMap<Integer, Integer>(len-1); 8 //将第一个直接放入hash表中 9 hashtable.put(nums[0] , 0 ); 10 for (int i = 1; i < nums.length; i++) { 11 //判断hash表中是否已存在符合输入条件的数 12 if (hashtable.containsKey(target - nums[i])) { 13 return new int[]{hashtable.get(target - nums[i]) , i}; 14 } 15 //没有找到,就插入hash表中 16 hashtable.put(nums[i], i); 17 } 18 return new int[0]; 19 } 20 }
复杂度分析:
- 时间复杂度:,其中N是数组中的元素数量。
- 空间复杂度:。哈希表中最多需要存n-1个键值对。
提交结果: