ARTS
Algorithm:每周至少做一个leetcode的算法题;
Review:阅读并点评至少一篇英文技术文章;
Tip/Tech:学习至少一个技术技巧;
Share:分享一篇有观点和思考的技术文章;
Algorithm
387. 字符串中的第一个唯一字符
https://leetcode-cn.com/problems/first-unique-character-in-a-string/
给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。
案例:
s = “leetcode”
返回 0.
s = “loveleetcode”,
返回 2.
注意事项:您可以假定该字符串只包含小写字母。
这里的常规解法,就是遍历,然后把数据记录到哈希表里,每条数据按照顺序存储,其实代码看起来是很简单易懂的,show the code:
class Solution {
public int firstUniqChar(String s) {
int len = s.length();
LinkedHashMap<Character, Integer> map = new LinkedHashMap<>();
for (int i = 0; i < len; ++i) {
char temp = s.charAt(i);
if (map.containsKey(temp)) {
map.put(temp, map.get(temp) + 1);
} else {
map.put(temp, 1);
}
}
for (Character item : map.keySet()) {
if (map.get(item) == 1) {
return s.indexOf(item);
}
}
return -1;
}
}
但是提交之后才发现,原来这题有着更加高明的解法,解题的方法简直让我眼前一亮,直接遍历26个字母,如果说这个字母出现的位置就是最后出现的位置,那么就进行比较,比较这个字母和之前的记录的结果(res)哪个小,哪个小用哪个,当然,第一次发现这种字母的时候,就把它赋值给结果(res)
class Solution {
public int firstUniqChar(String s) {
int res = -1;
for(char c = 'a' ;c <= 'z' ; c ++ ){
int idx = s.indexOf(c);
if(idx != -1 && idx == s.lastIndexOf(c)){
res = (res == -1) ? idx : Math.min(res , idx);
}
}
return res;
}
}
217. 存在重复元素
https://leetcode-cn.com/problems/contains-duplicate/
给定一个整数数组,判断是否存在重复元素。
如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。
示例 1:
输入: [1,2,3,1]
输出: true
示例 2:
输入: [1,2,3,4]
输出: false
示例 3:
输入: [1,1,1,3,3,4,3,2,4,2]
输出: true
这道题这个礼拜给我带来的收获最多,这是关于代码如何优化到极致的一种收获。这道题目其实很简单,只要你能想到用Java里面的数据结构Set来进行进行判断就是最快的做法了,但是就是这个最快做法,却输给了大部分的提交,先来看看原来的代码是咋写的:
//通过 26 ms 41.4 MB java
public boolean containsDuplicate(int[] nums) {
int len = nums.length;
Set<Integer> set = new HashSet<>();
for (int i = 0; i < len; ++i) {
if (set.contains(nums[i])) {
return true;
} else {
set.add(nums[i]);
}
}
return false;
}
这种效率无疑是被吊起来打的,但是思想没有错啊。那么代码应该如何去优化?
// 通过 9 ms 34.4 MB
public boolean containsDuplicate(int[] nums) {
int len = nums.length;
Set<Integer> set = new HashSet<>();
for (int i = 0; i < len; ++i) {
boolean addResult = set.add(nums[i]);
if (!addResult) {
return true;
}
}
return false;
}
contains 这个方法比add这个方法的效率慢的真的太多了, 这题给我带来的收获真的是,平时我们在写代码的过程中是不注重函数的使用的,对于代码的效率而言也是得过且过的,但是这次给我带来的感觉就是,你最好要明白每个函数到底表达了什么,最好要知道每个函数的运行机制是什么。
我大胆的猜测一下:add是直接根据参数计算哈希值,然后根据哈希值来判断是否存在;而contains则是去遍历整个set来判断这个值是否存在。其实感觉这个有点说不通啊,contains也是可以计算哈希值的,没有道理去遍历啊。最好还是看一下字节码来进行做判断了。
Review
https://www.techiedelight.com/determine-linked-list-palindrome-or-not/
这篇文章提供的一个思路就是用栈来把数据存储起来,然后不断的出栈进行每个元素的比较。这个倒是个非常简单好懂的做法。
我们一般判断一个链表是否回文,一般都是先找出中间结点,然后根据中间结点,把后面的节点进行遍历反转,然后进行分别判断,这么做倒是省了不少的空间,但是代码写起来难度有点高,涉及到链表反转,肯定是要费一番功夫的。
Tip/Tech
学习并且使用了二叉树的前序、中序、后序遍历方式,做了很多道关于二叉树的题。
Share
http://nautil.us/issue/68/context/what-impossible-meant-to-feynman
『不可能』对费曼先生来说意味着什么?
这篇文章真的是说的,特别的琐碎,更像是带着对费曼先生的感谢之情的回忆。说了好多关于费曼先生的日常的言行举止等等。
费曼先生在面对自己以前没有见过的时候,常常会说『Impossible』,表示自己的震惊。
感觉费曼先生对作者影响深远啊。