Skip to content

Commit b47217c

Browse files
author
haolin3
committed
Merge branch 'master' of github.com:geekxh/hello-algorithm
2 parents b28d400 + 2281ea1 commit b47217c

File tree

241 files changed

+3479
-155
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

241 files changed

+3479
-155
lines changed

learning/0.0.学习须知/023.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
---
2+
title: 打鸡血
3+
date: 2020-07-12
4+
---
5+
6+
今天的文章,不浪,没图。给大家加加油!
7+
8+
<img src="./023/1.jpg" alt="PNG" style="zoom: 33%;" />
9+
10+
回顾过去一年,京东、知乎、美团、微博、去哪儿、滴滴等。爆出裁员的有多少,虽然最终都被官方辟谣。**但是,你们懂的。**
11+
12+
<br/>
13+
14+
互联网寒冬之下,所有公司都勒紧裤腰带过活。那么,对于个体的你,不努力,不学习,想去大厂?凭什么。
15+
16+
<br/>
17+
18+
请大家原谅我说话的直白。2020年就目前来看,对于企业是明显的买方市场(供过于求)。**而且,未来几年应该都是这样**。所以,大部分企业在招聘时,是要在很多优秀的人中去选出一个更优秀的人,而不是在一群普通人中选择一个优秀的人。
19+
20+
<br/>
21+
22+
毕竟,如果你不够格,可能简历都过不了。**而对于应届生,如果不能多维度的获取你的信息。那么出几道难题,在没有更好的替代方案之前,目前是唯一的选择。**
23+
24+
<br/>
25+
26+
所以我最终很直白的告诉这位同学,刷题,你还是得刷。该记的,你还是得记。尤其如果目标本身就是一个好的offer,那更应是如此。
27+
28+
<br/>
29+
30+
但是,**这样的回答其实是不负责任的**。虽然我考虑到给对方一点压力,很直白的回复了他。但如果放开这一切,我们为什么学算法?为什么学数据结构?
31+
32+
<br/>
33+
34+
“面试造火箭,工作拧螺丝” ,工作四五年,别说红黑树,就连普通二叉树基本都没手写过,**我知道很多人都是这个状态**。这种状态正常吗?**正常**。但不写不等于不用。就算真的不用,也不等于不需要知道怎么用。
35+
36+
<br/>
37+
38+
**其实,很多学生学习数据结构是有问题的**。就这位同学而言,至少出现背代码,就是绝对错误的。数据结构的本质,在我看来是去契合一些应用场景,自然而然的产生,而不是死记硬背。
39+
40+
<br/>
41+
42+
比如说红黑树,我们需要知道这是一种常用的平衡二叉树(或者说特殊的平衡二叉树)知道其对于查找, 插入,删除的复杂度都是log(n) --- n 这里是说树中元素的个数。如果你是java栈,你可能还需要知道 hashmap 为什么选用红黑树来实现。要知道红黑树可以在一些非实时任务调度中,可以高效公平的调度任务。要知道其所有的应用,都是围绕着“平衡”二字。这才是数据结构的核心。
43+
44+
<br/>
45+
46+
至于实现的细枝末节,**知道固然好,但没必要去逼着自己记忆**。因为,我们的职业生涯里,绝对不可能出现让你手写红黑树的节点删除的场景。
47+
48+
<br/>
49+
50+
但你需要知道为什么创造/引入它,它有什么特殊的,它满足哪些场景,又不满足哪些场景,不满足的场景又如何替代。这才是对数据结构的良好理解。
51+
52+
<br/>
53+
54+
其实,除了算法,在我看来很多别的知识也是这样。**只是说算法,更容易在面试的时候去展示而已。本身而言,并没有什么特殊的。**
55+
56+
<br/>
57+
58+
比如学习操作系统。那我们为什么学习操作系统?难道是让我们造出来一个操作系统吗?显而易见并不是。学习操作系统是让我们了解为什么会提出OS,如果没有OS又会是什么样子。它怎么样做任务调度,怎么样做进程管理,怎么样对可用的硬件做成抽象,死锁是如何产生的,内存是怎么管理的,文件系统是如何实现的,通信是指谁与谁的通信。不是说应付了考试就算学了,而是带着脑子掌握这个东西的脉络,这才是核心。
59+
60+
<br/>
61+
62+
比如学习数据库原理,不是说让你去造一个数据库。当然你有这本事,那也ok。更多的是去了解数据库是如何来抽象数据管理的,大数据在什么场景下应运而生。学了之后,你会知道关系型数据库只是数据库中的冰山一角。你知道缓存,索引,批处理,中间件之中都是有着数据库的影子。你用 git 你会知道 .git 文件下,其实就用几个很简单的数据结构,就构建了一个数据库的雏形。你知道事务控制,其实最初只是想把事情做正确,你知道 ACID 是在保证什么。你知道数据库的整个设计中,很多时候我们是在性能和正确性中做选择。你知道除了程序员之外,还有 DBA 更加会关注高可用。你不会再觉得读写分离,主从备份多么高大上,因为你知道除了读写分离之外,还有快慢分离,异地多活,**Replication 和 Failover 很多东东**,都是上个世纪就有了完美的理论支撑。
63+
64+
<br/>
65+
66+
比如学习计算机网络,不是说让你去死记硬背几层网络模型,都各自是什么。而是让你知道全球互联网是如何运作的,知道TCP为了保证数据可靠做了多少额外的工作,握手为什么是3次,不是456次。知道滑动窗口并不等于leetcode上的几道题。知道层与层之间是如何划分的。知道在计算机网络的基础下,还有计算机网络安全一大块基石。
67+
68+
<br/>
69+
70+
比如学习编译原理,没人让你死记硬背那些分词算法。而是去知道为什么要划分词法,语法,语义分析。知道为什么很多语言要提出中间代码这个东东。知道编译原理很多东西,其实就是 NLP 的基础,其实就是智能机器人的基础。知道在 ES 的设计中,其实也参考很多编译器的设计。
71+
72+
<br/>
73+
74+
当然,我们很可能不会完美的掌握上面所说的所有。**但我们会在这个过程中,去发现自己的知识盲点,进而刻意提高**。而不是一直陷入“学不会-理解不了-记不住”的死循环。
75+
76+
<br/>
77+
78+
当然,对于要找工作的人,我们可以直接去击打一些面试痛点,更好的兼容社会。**但我们面试过后,总归是要知识落地,这才能体现你的最终价值。**
79+
80+
<br/>
81+
82+
不要说什么“面试造火箭,工作拧螺丝”,拧螺丝的人,只能一直留在位置上拧螺丝。而努力拧螺丝的人,说不定就有机会去造火箭。而那些有造火箭能力的人,他们终究会造上火箭。

learning/0.0.学习须知/023/1.jpg

538 KB
Loading

learning/1.0.数组系列/009.md

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
---
2+
title: Z字形变换(6)
3+
date: 2020-07-08
4+
---
5+
6+
> 今天为大家分享一道让很多人头疼过的题目 - Z字形变化。
7+
8+
## 01、题目示例
9+
10+
> 额。。。不知道是不是我瞎,明明是N么(杠精勿扰,只是说说)
11+
12+
<br/>
13+
14+
| 第6题:Z 字形变换 |
15+
| ------------------------------------------------------------ |
16+
| 将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。比如输入字符串为 **"LEETCODEISHIRING" **行数为 3 时,排列如下: |
17+
18+
```
19+
L C I R
20+
E T O E S I I G
21+
E D H N
22+
```
23+
24+
<br/>
25+
26+
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:**"LCIRETOESIIGEDHN"**
27+
28+
<br/>
29+
30+
请你实现这个将字符串进行指定行数变换的函数:
31+
32+
```
33+
string convert(string s, int numRows);
34+
```
35+
36+
**示例 1:**
37+
38+
```
39+
输入: s = "LEETCODEISHIRING", numRows = 3
40+
输出: "LCIRETOESIIGEDHN"
41+
```
42+
43+
**示例 2:**
44+
45+
```
46+
输入: s = "LEETCODEISHIRING", numRows = 4
47+
输出: "LDREOEIIECIHNTSG"
48+
49+
解释:
50+
L D R
51+
E O E I I
52+
E C I H N
53+
T S G
54+
```
55+
56+
<img src="./009/1.gif" alt="PNG" style="zoom: 67%;" />
57+
58+
## 02、题目分析
59+
60+
> 这是我比较推崇的一道“小学题目”,因为其没有任何复杂的思维逻辑,只需要按部就班,就可以顺利解答。难的是,按部就班的过程里,却极其容易出错。
61+
62+
<br/>
63+
64+
因为最终目的是变换字符串的顺序,并且题中也没有限制说不可用额外空间,所以我们秉承不重复造轮子的原则,想办法利用某种结构对原字符串做文章。
65+
66+
<br/>
67+
68+
假若我们采用示例2的数据来进行分析,输入字符串 s 为 "LEETCODEISHIRING", numRows 为 4 ,画成图大概长这样:
69+
70+
<img src="./009/2.jpg" alt="PNG" style="zoom: 50%;" />
71+
72+
重点来了,**我们的目标是按行打印,那总得有个东西来存储每行的数据吧**?因为只需要存储**每行**的数据,那是不是用个数组就可以了。(当然,你硬说搞个map来存也没啥毛病,就是有点闲得蛋疼)
73+
74+
<br/>
75+
76+
问题来了,那数组设置多大呢?自然是有多少行我们就设置多大呗,换句话说,numRows多大,我们的数组就设置多大。画成图大概就是下面这个样子:
77+
78+
<img src="./009/3.jpg" alt="PNG" style="zoom: 50%;" />
79+
80+
存储的容器有了,原字符串也列出来是啥样了,现在嘎哈?自然就是把原字符串放到容器里咯。怎么放?**根据 numRows 的大小来回进行放置即可**(即从0到n-1,再从n-1到0)。具体的请看下图:
81+
82+
<img src="./009/4.jpg" alt="PNG" style="zoom: 67%;" />
83+
84+
上面的图长得不得了,但是观察我们能看出来,**每 2n-2 即为一个周期**。到了这里,应该没有人会质疑这是一道小学题目了吧。。。把所有的字符串放完之后,大概就是下面这个样子:
85+
86+
<img src="./009/5.jpg" alt="PNG" style="zoom: 67%;" />
87+
88+
最后一步,咱们让这个数组排排坐,就可以开始吃果果:
89+
90+
<img src="./009/6.jpg" alt="PNG" style="zoom: 67%;" />
91+
92+
如果看不清楚,不如这样:
93+
94+
<img src="./009/7.jpg" alt="PNG" style="zoom: 67%;" />
95+
96+
根据分析,得出代码(好久没翻go的牌子了):
97+
98+
```go
99+
//go
100+
func convert(s string, numRows int) string {
101+
if numRows == 1{
102+
return s
103+
}
104+
var b = []rune(s)
105+
var res = make([]string, numRows)
106+
var length = len(b)
107+
var period = numRows * 2 - 2
108+
for i := 0 ;i < length; i ++ {
109+
var mod = i % period
110+
if mod < numRows {
111+
res[mod] += string(b[i])
112+
} else {
113+
res[period - mod] += string(b[i])
114+
}
115+
}
116+
return strings.Join(res, "")
117+
}
118+
```
119+
120+
执行结果:
121+
122+
<img src="./009/8.jpg" alt="PNG" style="zoom:;" />
123+
124+
上面的代码要强调两点:
125+
126+
<br/>
127+
128+
第一:用了一个rune,这个其实是go里的用法,用来处理unicode或utf-8字符而已,并没有什么特别的。
129+
130+
第二:12-15行的意思是,在周期内,正着走 numRows-1 下,剩余的反着走。(也就是上面那个长长的图)
131+
132+
<br/>
133+
134+
为了照顾Java的小伙伴,再给出一个Java版本的:
135+
136+
```java
137+
//java
138+
class Solution {
139+
public static String convert(String s, int numRows) {
140+
if (numRows == 1) return s;
141+
String[] arr = new String[numRows];
142+
Arrays.fill(arr, "");
143+
char[] chars = s.toCharArray();
144+
int len = chars.length;
145+
int period = numRows * 2 - 2;
146+
for (int i = 0; i < len; i++) {
147+
int mod = i % period;
148+
if (mod < numRows) {
149+
arr[mod] += chars[i];
150+
} else {
151+
arr[period - mod] += String.valueOf(chars[i]);
152+
}
153+
}
154+
StringBuilder res = new StringBuilder();
155+
for (String ch : arr) {
156+
res.append(ch);
157+
}
158+
return res.toString();
159+
}
160+
}
161+
```
162+
163+
和Go语言的示例一样,代码的关键仍然是计算轨迹的过程(10-17),这里再提供另外一种计算轨迹的方式:
164+
165+
```java
166+
//java
167+
class Solution {
168+
public String convert(String s, int numRows) {
169+
if (numRows == 1) return s;
170+
String[] arr = new String[numRows];
171+
Arrays.fill(arr, "");
172+
int i = 0, flag = -1;
173+
for (char c : s.toCharArray()) {
174+
arr[i] += c;
175+
if (i == 0 || i == numRows - 1) flag = -flag;
176+
i += flag;
177+
}
178+
StringBuilder res = new StringBuilder();
179+
for (String ch : arr) {
180+
res.append(ch);
181+
}
182+
return res.toString();
183+
}
184+
}
185+
```
186+
187+
通过使用一个标志位,来使轨迹回移。(本质其实是一样的)
188+
189+
<br/>
190+
191+
## 03、总结
192+
193+
> 这道题目的意义在于考察coding的能力,本身的思维过程并不复杂。有的同学一看这种题目,**就想通过二维数组来进行计算,殊不知已经落入了题目的陷阱(不信你试试,二维数组出错率一定远胜一维数组)**。当然,本题也是可以不借助额外空间来进行实现的,核心的逻辑完全相同,建议大家下去自己动手练习一下。
194+
195+
<br/>
196+
197+
所以,今天的问题你学会了吗,评论区留下你的想法!
198+

learning/1.0.数组系列/009/1.gif

53.4 KB
Loading

learning/1.0.数组系列/009/2.jpg

10.1 KB
Loading

learning/1.0.数组系列/009/3.jpg

27.2 KB
Loading

learning/1.0.数组系列/009/4.jpg

12.9 KB
Loading

learning/1.0.数组系列/009/5.jpg

17.5 KB
Loading

learning/1.0.数组系列/009/6.jpg

8.53 KB
Loading

learning/1.0.数组系列/009/7.jpg

5.33 KB
Loading

0 commit comments

Comments
 (0)