LeetCode临时整理
LeetCode刷题记录
记录模板
解法xxx:xxx
- 思路
- 犯错
- 代码
0001 两数之和
O(n)思路:使用哈希表记录原数和原数的下标,扫描一遍,去哈希表中寻找另一半数,找不到就记录原数和原数的下标,找到据返回。
错误:忽略了map查找有两个返回值的特点,返回值可以更简洁,不一定要设计变量记录
1 |
|
0002 两数相加
思路:思路清晰,就是模拟整个相加的过程。对两个链表进行遍历,首先确定相加的数字,然后求和,最后将结果添加结点到目标链表中。结束遍历后要对进位位进行检查,如果有进位就要再创建一个结点。
错误:为了使链表信息可保存(添加结点的时候不会丢失当前结点),我们创建了一个空的头结点,在添加结点时是添加下一个结点。同时处理完记得后移。
1 |
|
0003 无重复字符的最长子串
思路:双指针+哈希表记录(也可以叫做滑动窗口,其实就是双指针,字符串常用双指针),head指针的含义是不重复子串的开头。我们使用一个数组标记访问过的字符,用来存放遇到重复字符时,从什么地方开始重新扫描确定无重复子串。这种使用数组来记录失败时回退的位置的做法,和KMP的getNext函数似乎很类似。
1
2
3
4
5
6
7
8
9
10func lengthOfLongestSubstring(s string) int {
var m [128]int //128个ASCII码,存下标位置+1,默认为0,用于更新无重复子串的开头
head, maxLen := 0, 0
for i := 0; i < len(s); i++ {
head = max(head, m[s[i]])//更新head到无重复子串的开头,也就是舍弃掉重复的字符串
m[s[i]] = i + 1//标记出现过的字母的下一位置
maxLen = max(maxLen, i-head+1)//更新最长无重复子串的长度
}
return maxLen
}
这其实算是优化过后的做法,使得head可以直接跳转到下一位,而不是单纯用哈希表标记字符是否出现,跳转的操作更少,代价就是我们每遇到一个字符就要更新一次最长长度,但是少了很多的判断,计算机执行应该更快。
我们来看看LeetCode官方的题解,还要涉及到删除哈希表的记录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 func lengthOfLongestSubstring(s string) int {
// 哈希集合,记录每个字符是否出现过
m := map[byte]int{}
n := len(s)
// 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
rk, ans := -1, 0
for i := 0; i < n; i++ {
if i != 0 {
// 左指针向右移动一格,移除一个字符->就是把左侧重复字符的哈希记录删了,
//原来重复的字符(即rk+1处的字符)在右侧就不算重复了
//算是一种更新手段吧,方便后续右指针更新
delete(m, s[i-1])
}
for rk + 1 < n && m[s[rk+1]] == 0 {
// 不断地移动右指针
m[s[rk+1]]++
rk++
}
// 第 i 到 rk 个字符是一个极长的无重复字符子串
ans = max(ans, rk - i + 1)
}
return ans
}
func max(x, y int) int {
if x < y {
return y
}
return x
}
0004 HHH寻找两个正序数组的中位数
•简单粗暴思想:正序合并数组。有空数组直接处理非空数组;没有空数组,合并数组。按照大小添加元素,发现任意一个数组元素全部添加完后,只添加另一数组元素。
错误点:思路不清晰,数组越界处理不当。
1 |
|
•稍微变换:找数字,一个一个排除,处理到找到中位数即可
a < m && (b == n || nums1[a] < nums2[b])利用了或运算逻辑短路实在是妙啊。b==n说明了已经越界了,此时就返回了1,后续访问也不再执行,而b不等于n时后续会访问数组比大小,写的很简洁。
核心就在for循环中的if语句逻辑处理上
1 |
|
•转换思路:查找第k小数(k=l/2)
•定义思路:切分数组
1 |
|
- No.0011盛水
题目:
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。返回容器可以储存的最大水量。说明:你不能倾斜容器。
双指针思路:关键在于缩减搜索空间。使用两个指针,一左一右,每次移动短板,只有移动短板才有可能使得水槽短板变长,高度才可能变长。移动长板的话,短板会不变或者变短。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18func maxArea(height []int) int {
i, j := 0, len(height)-1
high, max:=0, 0
for i != j {
//更新高度、最大值
high = min(height[i], height[j])
if high*(j-i) > max {
max = high * (j - i)
}
//每次移动短板寻找max
if height[i] > height[j] {
j--
} else {
i++
}
}
return max
}