LeetCode No.1 Two Sum
2017-05-09 23:26
281 查看
这是LeetCode题海中的第一题,就让我们从读题开始吧~
题目:给定一个整数的数组,返回两个元素的索引,这两个元素之和要等于一个给定的值target;假定每一组输入仅有唯一的解,并且同一个元素不能被使用两次。
看一个样例:
nums = [2, 7, 11, 15], target = 9;
因为nums[0] + nums[1] = 9;
所以应该返回[0, 1]
在这里我讲介绍三种解法:
第一种是最直接的蛮力算法,第二种和第三种是利用散列表提高查找速度的算法,其中第三种算法最为简洁高效~
思路一:蛮力解法
蛮力解法是很直接的!
从数组的第一个元素开始,依次遍历其后的元素;
判断这两个元素之和是否等于target,若等于则返回这两个元素的索引,否则继续遍历知道达到数组尾部;
从数组的第二个元素开始,依次遍历其后元素;
重复第二步;
从第三个,依此类推;
代码:
蛮力算法之所以叫蛮力算法,就是因为它很蛮,这个算法的时间复杂度高达O(n2)。
![](https://img-blog.csdn.net/20170511214012359?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc29sb21vbnBva2Vtb24=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
果然很慢,只击败了8%的人。。。。。
这个算法之所以很慢,就是因为它在查找我们的目标元素的时候需要依次遍历,但是我们根据target是可以知道要查找的目标元素的值的,如果我们能够很快地找到它,那算法的速度自然也就会提升!根据这个思路,我们自然想到了使用平衡搜索数或者散列表这种查找元素很快的数据结构;
思路二:利用散列表
我们利用散列表快速查找目标元素,即可在O(n)的时间内完成算法,但是这里要注意重复元素的处理,比如:
给定一个数组:[3, 2, 4], target = 6, 那么我们要的返回结果应该是[1, 2]而不是[0, 0];
当数组为:[3, 3, 7, 5], target = 6时,返回结果就是[0, 1];
代码:
![](https://img-blog.csdn.net/20170511231103389?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc29sb21vbnBva2Vtb24=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
可以看到,这个算法只用了9ms,复杂度下降到了O(n),散列表是不是很神奇呢!
思路三:我们可以更加简单快速的使用散列;
我们先创建一个空的散列,然后从原数组的第一个元素开始,在散列中查找它的目标元素;
如果找到,直接返回结果,否则,将这个元素插入到散列中;
依次迭代直到到达数组尾部,当然,这个题目假设一定有解;
代码:
题目:给定一个整数的数组,返回两个元素的索引,这两个元素之和要等于一个给定的值target;假定每一组输入仅有唯一的解,并且同一个元素不能被使用两次。
看一个样例:
nums = [2, 7, 11, 15], target = 9;
因为nums[0] + nums[1] = 9;
所以应该返回[0, 1]
在这里我讲介绍三种解法:
第一种是最直接的蛮力算法,第二种和第三种是利用散列表提高查找速度的算法,其中第三种算法最为简洁高效~
思路一:蛮力解法
蛮力解法是很直接的!
从数组的第一个元素开始,依次遍历其后的元素;
判断这两个元素之和是否等于target,若等于则返回这两个元素的索引,否则继续遍历知道达到数组尾部;
从数组的第二个元素开始,依次遍历其后元素;
重复第二步;
从第三个,依此类推;
代码:
vector twoSum(vector& nums, int target) { for(unsigned int i = 0; i < nums.size(); ++i) { for(unsigned int j = i + 1; j < nums.size(); ++j) { if(nums[i] + nums[j] == target) { return vector{i, j}; } } } }
蛮力算法之所以叫蛮力算法,就是因为它很蛮,这个算法的时间复杂度高达O(n2)。
果然很慢,只击败了8%的人。。。。。
这个算法之所以很慢,就是因为它在查找我们的目标元素的时候需要依次遍历,但是我们根据target是可以知道要查找的目标元素的值的,如果我们能够很快地找到它,那算法的速度自然也就会提升!根据这个思路,我们自然想到了使用平衡搜索数或者散列表这种查找元素很快的数据结构;
思路二:利用散列表
我们利用散列表快速查找目标元素,即可在O(n)的时间内完成算法,但是这里要注意重复元素的处理,比如:
给定一个数组:[3, 2, 4], target = 6, 那么我们要的返回结果应该是[1, 2]而不是[0, 0];
当数组为:[3, 3, 7, 5], target = 6时,返回结果就是[0, 1];
代码:
vector twoSum(std::vector& nums, int target) { unordered_multimap numbers; vector result; for (unsigned i = 0; i < nums.size(); ++i) numbers.insert({ nums[i], i }); for (unsigned int i = 0; i < nums.size(); ++i) { auto candi_iter = numbers.find(target - nums[i]); if (candi_iter != numbers.end()) { if (candi_iter->first == nums[i]) { if (numbers.bucket_size(numbers.bucket(nums[i])) > 1) { for (auto iter = numbers.begin(numbers.bucket(nums[i])); iter != numbers.end(numbers.bucket(nums[i])); ++iter) result.push_back(iter->second); return result; } else continue; } result.push_back(i); result.push_back(candi_iter->second); return result; } } }
可以看到,这个算法只用了9ms,复杂度下降到了O(n),散列表是不是很神奇呢!
思路三:我们可以更加简单快速的使用散列;
我们先创建一个空的散列,然后从原数组的第一个元素开始,在散列中查找它的目标元素;
如果找到,直接返回结果,否则,将这个元素插入到散列中;
依次迭代直到到达数组尾部,当然,这个题目假设一定有解;
代码:
vector twoSum3(vector& nums, int target) { unordered_multimap numbers; for (unsigned int i = 0; i < nums.size(); ++i) { auto candi_iter = numbers.find(target - nums[i]); if (candi_iter != numbers.end()) { return vector{candi_iter->second, i}; } numbers.insert({ nums[i], i }); } }
相关文章推荐
- 【LeetCode】No.1 Two Sum
- Leetcode NO.1 Two Sum
- leetcode No.1 Two Sum
- [leetcode NO.1] Two Sum (JAVA)
- LeetCode No.1 Two Sum
- LeetCode--No.1--Two Sum
- LeetCode No.1 Two Sum
- leetcode-Two Sum[题解]
- [leetcode, python] Two Sum 两数之和等于某数
- LeetCode之Two Sum
- leetcode 【 Two Sum 】python 实现
- LeetCode第一题Two Sum
- LeetCode[Hash Table]: Two Sum
- leetcode-1.two sum
- LeetCode之Two Sum
- LeetCode---Two Sum
- leetcode001 Two Sum
- [LeetCode] Two sum
- LeetCode | 1) Two sum
- 1.[LeetCode]Two Sum