每周完成一个 ARTS:
Algorithm: 每周至少做一个 LeetCode 的算法题
Review: 阅读并点评至少一篇英文技术文章
Tips: 学习至少一个技术技巧
Share: 分享一篇有观点和思考的技术文章


Contents:


Algorithm

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)。


Review

Why IoT Needs Machine Learning to Thrive

本周阅读了 IoT for All 上的一篇文章,Why IoT Needs Machine Learning to Thrive,比较短小,但值得一读,尤其是物联网面临的几个关键挑战和机器学习能够应用的几个因素,非常有针对性。

文章从以下几个方面讲述了机器学习如何为 IoT 行业赋能:


Tips

vim 中的快速移动

大家知道,vim 的 normal 模式使用了 hjkl 这四个键来进行上下左右的移动,除了这四个键,Vim 其实还有很多其他的移动方式:

在单词之间进行移动:

行间搜索移动:

水平移动:

垂直移动:

页面移动:

以上这些命令,看不懂记不住的话,多用用多练习几次,这里附上一份 vim 命令速查表


Share

机器学习中的朴素贝叶斯分类

这篇内容是我学习的学习笔记,稍作整理,分享给大家。

贝叶斯定理

朴素贝叶斯算法起源于上世纪四五十年代,它基于的贝叶斯定理如下公式所示:

\[P(A|B) = \frac{P(B|A)*P(A)}{P(B)}\]

我们先来看一个例子:

一家生产某种产品的工厂有两台机床,也会生产出正品和次品,一共生产了 1000 个产品

解答:本题使用贝叶斯公式就能很好地解决问题

另一个角度(方法二):

其实就只是在贝叶斯公式的上下各乘了 1000,但胜在思路清晰:

\[P(Def|M2)=\frac{P(M2|Def)*P(Def)*1000}{P(M2)*1000}=1.25%\]

问题:为什么有方法二还要使用贝叶斯公式呢?

朴素贝叶斯分类器 - 原理

首先我们看一下贝叶斯公式:

\[P(A|B) = \frac{P(B|A)*P(A)}{P(B)}\]

P(A|B) 称为条件概率,或者后验概率,而 P(B|A) 和 P(B) 并不完全是概率,因为它们表示的是特征,所以这两个概率又被称为“似然 Likelihood”。

我们再来看一个例子:

这个例子的问题是:根据年龄和薪水,判断一个新的员工是走路上班还是开车上班

我们使用这种思路来进行试验:

朴素贝叶斯的几个问题

  1. 为什么称为“朴素 Naïve”? 在应用朴素贝叶斯之前,我们做了一个假设,即数据的所有特征都是相互独立的,但是在例子中,其实薪水和年龄之间并不是独立的(年龄越大经验越多薪水也就越来越高),但是在这个例子中这两个变量的相关性不是特别高,如果相关性很高的话,那么在计算圈中点的个数的时候,会有一点问题
  2. 似然函数 P(X) 的消去\[P(X) = \frac{Number\ of\ Similar\ Observations}{Total\ Observations}\]

  3. 大于两类的情况,如何应用朴素贝叶斯?