Skip to content

Commit 8d906de

Browse files
committed
‘’
1 parent 00d6cff commit 8d906de

Some content is hidden

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

66 files changed

+1160
-154
lines changed

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

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

4.17 KB
Loading

learning/1.1.链表系列/104.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
---
2+
title: 两数相加(2)
3+
date: 2020-07-09
4+
---
5+
6+
> 前几天写了一篇“小白为了面试如何刷题”的文章大受好评。随之而来的是好多小伙伴私下跑来问我“**浩哥,你说前200道题很好,但是前两百道题的难度很大,我不会怎么办**”这问题我想了一两天。。。好吧,既然你们说难不会。那我干脆就把前两百道题都给你们配上图解,全部安排,这样总可以了吧?牛气冲天有木有,哪个公号主敢这么干的!奥利给,搞起。今儿为大家分享经典面试题目 - 两数相加。做过的朋友,也不要急着叉掉,不妨借机复习一番。
7+
8+
## 01、题目示例
9+
10+
> 各数据结构中的“加减乘除”都是很爱考察的内容。
11+
12+
| 第2题:两数相加 |
13+
| ------------------------------------------------------------ |
14+
| 给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。 |
15+
16+
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
17+
18+
<br/>
19+
20+
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
21+
22+
<br/>
23+
24+
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
25+
26+
<br/>
27+
28+
**示例:**
29+
30+
```
31+
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
32+
输出:7 -> 0 -> 8
33+
原因:342 + 465 = 807
34+
```
35+
36+
## 02、算法图解
37+
38+
> 烧饼(哨兵)节点:烧饼节点就是说有一个节点长的像烧饼,站在最前面。往往第一个节点小子都会来啃一口,因为是牛肉拔丝烧饼,扯不掉就连起来了。。。好了,我实在编不下去了~囧....
39+
40+
<br/>
41+
42+
不了解哨兵节点的可以看下:
43+
44+
<br/>
45+
46+
[删除链表倒数第N个节点(19)](1.0.数组系列/101.md)
47+
48+
<br/>
49+
50+
好了,了解了哨兵节点,其实这道题和哨兵节点**并没有什么毛线关系,**我只是让你复习一下(会不会想打我)。现在开始正式分析题目。
51+
52+
<br/>
53+
54+
老样子,我们还是先画图,假若我们的链表是 (2 -> 4 -> 3) + (5 -> 6 -> 4) ,大概就是这样(注意,这里我们其实是要完成 342 + 465):
55+
56+
<img src="./104/1.jpg" alt="PNG" style="zoom: 80%;" />
57+
58+
加法肯定是从最低位到最高位进行相加,也就是这里的**链表头到链表尾进行相加,所以需要遍历链表**。我们令 l1 和 l2 指向两个链表的头,用一个 tmp 值来存储同一位相加的结果,以及一个新的链表来存储 tmp 的值。(为什么不直接用新链表存储结果,而是用 tmp 先存储结果,再用新链表存储 tmp 的值呢?请继续往下看)
59+
60+
<img src="./104/2.jpg" alt="PNG" style="zoom: 80%;" />
61+
62+
记住:**所有模拟运算的题目,都需要考虑进位**。这里因为个位不涉及进位,开始计算十位。我们同时遍历 l1,l2,以及新链表到下一位。
63+
64+
<img src="./104/3.jpg" alt="PNG" style="zoom: 80%;" />
65+
66+
重复上面的操作,可以看到十位与个位不同,发生了进位。这时,刚才的 tmp 就有了用武之地。**我们使用 tmp 携带进位的值到下一位的运算**。自然,这里的链表也不能直接存储 tmp 的值了,而是要存储 tmp%10 的值。重复这个步骤,**直到两个链表都遍历完成,并且 tmp 没有进位值**
67+
68+
<img src="./104/4.jpg" alt="PNG" style="zoom: 80%;" />
69+
70+
现在只需要返回我们的新链表就可以了。问题来了,**因为我们没有构造哨兵节点,所以此时不太容易直接返回新链表**。所以在整个流程的第一步,我们还需要用一个哨兵节点指向我们的新链表。
71+
72+
<img src="./104/5.jpg" alt="PNG" style="zoom: 80%;" />
73+
74+
分析完毕,直接上代码(好久没翻Go的牌子了):
75+
76+
```go
77+
//go
78+
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
79+
list := &ListNode{0, nil}
80+
//这里用一个result,只是为了后面返回节点方便,并无他用
81+
result := list
82+
tmp := 0
83+
for l1 != nil || l2 != nil || tmp != 0 {
84+
if l1 != nil {
85+
tmp += l1.Val
86+
l1 = l1.Next
87+
}
88+
if l2 != nil {
89+
tmp += l2.Val
90+
l2 = l2.Next
91+
}
92+
list.Next = &ListNode{tmp % 10, nil}
93+
tmp = tmp / 10
94+
list = list.Next
95+
}
96+
return result.Next
97+
}
98+
```
99+
100+
执行结果:
101+
102+
<img src="./104/6.jpg" alt="PNG" style="zoom: 80%;" />
103+
104+
## 03、总结
105+
106+
> 1950年6月19日,毛泽东写信给当时的教育部部长马叙伦:“要各校注意健康第一,学习第二。营养不足,宜酌增经费。”1951年9月底,毛泽东接见安徽参加国庆的代表团,代表团成员中有渡江小英雄马三姐。毛泽东关切地问她念书情况,还送她一本精美的笔记本,并且在扉页上题词:**好好学习,天天向上**。这8个字的题词迅速在全国传播开来。
107+
108+
<br/>
109+
110+
今天的题目到这里就结束了。你学会了吗?快来评论区留下你的想法吧!
111+

0 commit comments

Comments
 (0)