作为大名鼎鼎的面试刷题网站,最近也出了中文版,如果之前没有了解过的童鞋,建议去网站看看,里面有各大互联网公司的算法面试题,包括谷歌,Fackbook,微软,亚马逊等等,近年来国内的互联网公司也越来越重视算法和数据结构了,特别是后端,经常看到高级工程师 职位以上的jd都写明,算法水平需要到LeetCode Hard程度,前端稍微好一点,但是也需要LeetCode Easy 水平,因此无论是为了巩固基础,还是找工作跳槽,我们都需要不断练习算法,那么比较好的方式自然就是找一个靠谱的平台刷题了。
英文网站:https://leetcode.com/
中文网站:https://leetcode-cn.com/
值得一提的是,现在中文LeetCode【力扣】 还支持同步英文网站的账号数据,但是就个人而言,英语过得去的还是建议上英文,因为里面的功能比中文网多一点,而且最重要的是,Discuss里面的人数也会多一些,经常能看到NB的解法,还是很有帮助的。
那么为什么刷题还要写文章记录下来呢?
其实这篇文章的题目我在两年前就已经做过了,但是今天重新看,发现还是需要花很多时间去想解法,一方面当然是因为没有坚持做算法题,思维跟不上,另外一方面就是当时做完就算了,没有进一步思考,除了自己的这个解法,是否还有更好的方法。
因此我选择了把思考和改进的过程记录下来,当然大家用笔记类的工具记录,或者放到Github上都可以,目的都是为了锻炼自己的思维,提高算法水平罢了。
我当时的提交记录:
我打败了58%的人,那么前面的算法是怎么样的呢?
之前使用的是Java,那么如果换成C,C++,Python等语言,结果又是怎么样呢?
除了算法之外,是不是也有一些编程语言的技巧呢?
通过进一步的思考,我们会发现越来越多可以深入学习的地方。
因此,我决定把一部分题目写成博客,初衷就是为了方便自己,如果正好也能给予他人一点帮助的话,那就更好了。
Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the absolute difference between i and j is at most k.
Example 1:
Input: nums = [1,2,3,1], k = 3
Output: true
Example 2:
Input: nums = [1,0,1,1], k = 1
Output: true
Example 3:
Input: nums = [1,2,3,1,2,3], k = 2
Output: false
翻译:
给定一个数组和一个整数k,找出是否存在两个不同下标i和j,满足nums[i] = nums[j],并且这两个数字的绝对值不大于k。
思路:
public class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
boolean isTrue = false;
return isTrue;
}
}
public class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
boolean isTrue = false;
// Setp 2
HashMap<Integer,Integer> hashMap = new HashMap<>();
// 通过遍历数组,把数组的值存到HashMap中,再找后面是否存在值一样,而且下标差值<=k的数,有的话返回 true
for(int i=0;i<nums.length;i++){
if(hashMap.containsKey(nums[i]) && i - hashMap.get(nums[i]) <= k){
isTrue = true;
}else {
hashMap.put(nums[i], i);
}
}
return isTrue;
}
}
public class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
boolean isTrue = false;
// Step 3
if(nums.length<=1){
return isTrue;
}
HashMap<Integer,Integer> hashMap = new HashMap<>();
for(int i=0;i<nums.length;i++){
if(hashMap.containsKey(nums[i]) && i - hashMap.get(nums[i]) <= k){
isTrue = true;
}else {
hashMap.put(nums[i], i);
}
}
return isTrue;
}
}
这个解答的时间是:11ms,打败了58%的人,那么有没有更简单更好的解答呢?
这个是LeetCode Discuss上的解答,经过我在LeetCode上Run Code,Runtime为 0 ms:
public boolean containsNearbyDuplicate(int[] nums, int k) {
Set<Integer> set = new HashSet<Integer>();
for(int i = 0; i < nums.length; i++){
if(i > k) set.remove(nums[i-k-1]);
if(!set.add(nums[i])) return true;
}
return false;
}
思路:
同样是通过遍历数组,
我们来看看HashSet的源码:
/**
* Adds the specified element to this set if it is not already present.
* More formally, adds the specified element e to this set if
* this set contains no element e2 such that
* (e==null ? e2==null : e.equals(e2)).
* If this set already contains the element, the call leaves the set
* unchanged and returns false.
*
* @param e element to be added to this set
* @return true if this set did not already contain the specified
* element
*/
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
通过这个方法就可以判断当前元素是否已经在集合里面了。
其实这个解法的思路和我的解法是大同小异的,但是代码写得很巧妙,值得学习的地方有好几个:
通过set.add()的方法来判断,不需要 i - hashMap.get(nums[i]) <= k
通过set.remove(nums[i-k-1]) 来移除不满足条件的数字,而不是像我的方法,通过add,再一个个判断,减少了工作量
除了学习算法思路以外,也可以学习到集合的一些源码和实现,也就是数据结构的知识
class Solution {
public:
bool containsNearbyDuplicate(vector& nums, int k) {
unordered_set st;
for (int i = 0; i < nums.size(); i++) {
if (i > k) {
st.erase(nums[i - k - 1]);
}
if (!st.insert(nums[i]).second) {
return true;
}
}
return false;
}
};
def containsNearbyDuplicate(self, nums, k):
dic = {}
for i, v in enumerate(nums):
if v in dic and i - dic[v] <= k:
return True
dic[v] = i
return False
今年立下的目标就是巩固基础,包括设计模式,算法与数据结构,学习第三方框架源码等,每天都要进步一点点,量变引起质变!与大家共勉!