每周完成一个 ARTS:
Algorithm: 每周至少做一个 LeetCode 的算法题
Review: 阅读并点评至少一篇英文技术文章
Tips: 学习至少一个技术技巧
Share: 分享一篇有观点和思考的技术文章
3. Longest Substring Without Repeating Characters
题目:无重复字符的最长子串
难度:Medium
题意:给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
Input: "abcabcbb"
Output: 3
Explanation: The answer is "abc", with the length of 3.
示例 2:
Input: "bbbbb"
Output: 1
Explanation: The answer is "b", with the length of 1.
示例 3:
Input: "pwwkew"
Output: 3
Explanation: The answer is "wke", with the length of 3.
Note that the answer must be a substring, "pwke" is a subsequence and not a substring.
解法:
构造一个起始计数点 start,需要返回的结果 max
构造一个字典 dict,对字符串中的每一个字符进行读取:
如果这个字符在字典中,且它上一次出现在字符串中的位置比 start 要大[注1],那么:
将这个字符出现的位置置为 start(重新开始计数),并且将字典中这个字符的值修改为当前位置
如果这个字符不在字典中,那么:
将这个字符作为键,字符的位置作为值,加入到字典中去
如果当前位置减去起始位置比 max 要大,即说明我们目前读取过的字符数是最大的,那么修改 max 的值为当点位置减去 start
注意,如果字符串为空,那么返回值需要是 1,所以应该设置起始点为 -1
代码:
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
start = -1
max = 0
d = {}
for i in range(len(s)):
if s[i] in d and d[s[i]] > start:
start = d[s[i]]
d[s[i]] = i
else:
d[s[i]] = i
if i - start > max:
max = i - start
return max
注1:为什么这里一定要说明「读取到的字符上一次出现的位置比 start
要大」呢?
如果条件中没有
d[s[i]] > start
,那么就不能保证计算的子字符串是从上一个子字符串之后重新开始计算的。
第一次做 Medium 难度的题目,感觉还是很有挑战的,这里参考了 B站up主 Michelle 小梦想家 的这个视频。
时间复杂度为 O(n),空间复杂度也是 O(n)。
Why IoT Needs Machine Learning to Thrive
本周阅读了 IoT for All 上的一篇文章,Why IoT Needs Machine Learning to Thrive,比较短小,但值得一读,尤其是物联网面临的几个关键挑战和机器学习能够应用的几个因素,非常有针对性。
文章从以下几个方面讲述了机器学习如何为 IoT 行业赋能:
vim 中的快速移动
大家知道,vim 的 normal 模式使用了 hjkl 这四个键来进行上下左右的移动,除了这四个键,Vim 其实还有很多其他的移动方式:
在单词之间进行移动:
行间搜索移动:
f{char}
移动到该行第一个 char
字符上(f 可以理解为 find),使用 t{char}
移动到 char
的前一个字符上(t 可以理解为 till)char
,那么可以使用 分号 ;
跳转到下一个 char
,逗号 ,
跳转到上一个 char
水平移动:
垂直移动:
()
在句子间移动,使用 花括号 {}
在段落间移动页面移动:
以上这些命令,看不懂记不住的话,多用用多练习几次,这里附上一份 vim 命令速查表。
机器学习中的朴素贝叶斯分类
这篇内容是我学习的学习笔记,稍作整理,分享给大家。
朴素贝叶斯算法起源于上世纪四五十年代,它基于的贝叶斯定理如下公式所示:
\[P(A|B) = \frac{P(B|A)*P(A)}{P(B)}\]我们先来看一个例子:
一家生产某种产品的工厂有两台机床,也会生产出正品和次品,一共生产了 1000 个产品
解答:本题使用贝叶斯公式就能很好地解决问题
P(Defect | Mach 2) = ?
\[P(Def | M2) = \frac{P(M2 | Def)*P(Def)}{P(M2)} = \frac{0.5 * 0.01}{0.4} = 0.0125\]另一个角度(方法二):
其实就只是在贝叶斯公式的上下各乘了 1000,但胜在思路清晰:
\[P(Def|M2)=\frac{P(M2|Def)*P(Def)*1000}{P(M2)*1000}=1.25%\]问题:为什么有方法二还要使用贝叶斯公式呢?
计算 P(Defect | Mach 1)
\[P(Def|M1) = \frac{P(M1|Def)*P(Def)}{P(M1)} = \frac{0.5*0.01}{0.6} = 0.0083\]首先我们看一下贝叶斯公式:
\[P(A|B) = \frac{P(B|A)*P(A)}{P(B)}\]P(A|B) 称为条件概率,或者后验概率,而 P(B|A) 和 P(B) 并不完全是概率,因为它们表示的是特征,所以这两个概率又被称为“似然 Likelihood”。
我们再来看一个例子:
这个例子的问题是:根据年龄和薪水,判断一个新的员工是走路上班还是开车上班
步骤一
\[P(Walks|X) = \frac{P(X|Walks)*P(Walks)}{P(X)}\]步骤二
\[P(Drives|X) = \frac{P(X|Drives)*P(Drives)}{P(X)}\]步骤三
\[P(Walks|X)\ v.s.\ P(Drives|X)\]已知一个新用户的特征,分别求出他步行和开车上班的概率,这两个概率哪个比较大,新用户就会被分到哪一组
我们使用这种思路来进行试验:
P(Walks)
这个人走路上班的概率:
\[P(Walks) = \frac{Number\ of\ Walkers}{Total\ Observations} = \frac{10}{30} = \frac{1}{3}\]P(X)
在新数据点附近画一个小圈(圈的半径是一个参数,在算法中可调),看看圈中的点(不包含新数据点)在整个数据空间中所占的比例:
\[P(X) = \frac{Number\ of\ Similar\ Observations}{Total\ Observations} = \frac{4}{30} = \frac{2}{15}\]P(X|Walks)
已知这个人步行上班,求他的特征值落在图中圈里的概率:
\[P(X|Walks) = \frac{Number\ of\ Similar\ Observations\ Among\ those\ who\ walk}{Total\ number\ of\ Walkers}\\ = \frac{3}{10}\]P(Walks|X)
\[P(Walks|X) = \frac{\frac{3}{10}*\frac{10}{30}}{\frac{4}{30}} = 0.75\]P(Drives)
\[P(Drives) = \frac{20}{30}\]P(X|Drives)
\[P(X|Drives) = \frac{1}{20}\]P(Drives|X)
\[P(X|Drives) = \frac{\frac{1}{20}*\frac{20}{30}}{\frac{4}{30}} = 0.25\]步骤三,P(Walks|X) v.s. P(Drives|X)
\[P(Walks|X)\ v.s.\ P(Drives|X)\] \[0.75\gt 0.25\rightleftharpoons P(Walks|X)\gt P(Drives|X)\]因为 P(Walks|X) > P(Drives|X),所以这个新数据点被分到了走路上班这个类