← 返回首页
StriveZs的博客 Blog 2021-07-31T10:48:34.039Z www.strivezs.com/ StriveZs Hexo 链表插入排序 www.strivezs.com/2021/07/31/%E9%93%BE%E8%A1%A8%E6%8F%92%E5%85%A5%E6%8E%92%E5%BA%8F/ 2021-07-31T10:48:34.039Z 2021-07-31T10:48:34.039Z 链表插入排序

这里是链表的插入排序。时间效率和空间效率十分堪忧,但是思想比较简单。

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, val=0, next=None):
self.val = val
self.next = next

class Solution(object):
def insertionSortList(self, head):
"""
插入排序:除了第一个节点不动,第二个元素和前面已经排序好的元素进行比较,插入到合适的位置
重复上述过程即可。
比如:
1 3 5 2 4 |左边为排序好的节点
1 | 3 5 2 4
1 3 | 5 2 4
1 3 5 | 2 4
1 2 3 5 | 4
1 2 3 4 5 |
:type head: ListNode
:rtype: ListNode
"""
if head.next is None:
return head
ends = head.next
node = head.next
start = head
# 单独处理前两个节点
if node.val < start.val:
start.next = node.next
node.next = start
ends = start
start = node
head = node
# 递归处理后面所有情况
node = ends.next
while node is not None:
# 寻找合适的插入位置 (3种情况:头插入、中间插入、尾插入)
# 头插入
if node.val < start.val:
ends.next = node.next
node.next = start
start = node
head = node
node = ends.next
# 尾插入
elif node.val > ends.val:
ends = node
node = ends.next
# 中间插入
else:
cur = start
# 寻找插入位置
while True:
if node.val >= cur.val and node.val <=cur.next.val:
break
cur = cur.next
# 插入
ends.next = node.next
node.next = cur.next
cur.next = node
node = ends.next
return head
]]> <h1>链表插入排序</h1> <p>这里是链表的插入排序。时间效率和空间效率十分堪忧,但是思想比较简单。</p> <figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="lin 链表归并排序 www.strivezs.com/2021/07/31/%E9%93%BE%E8%A1%A8%E5%BD%92%E5%B9%B6%E6%8E%92%E5%BA%8F/ 2021-07-31T10:48:30.825Z 2021-07-31T10:48:30.825Z 链表归并排序

用一张图来说明归并排序:

代码

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution(object):
# fixme: 归并排序(自底向上合并链表)
def merge(self, node1, node2):
dummy = ListNode()
pre = dummy
while node1 is not None and node2 is not None:
if node1.val <= node2.val:
pre.next = node1
pre = pre.next
node1 = node1.next
else:
pre.next = node2
pre = pre.next
node2 = node2.next
if node1 is not None:
pre.next = node1
if node2 is not None:
pre.next = node2
return dummy.next

# fixme: 归并排序(自顶向下划分链表)
def merge_sort(self, head):
if head is None or head.next is None:
return head
# 快慢指针寻找中间节点
slow = head
fast = head
while fast.next is not None and fast.next.next is not None:
slow = slow.next
fast = fast.next.next
# 找到中间节点之后断开链表
new_head = slow.next
slow.next = None
# 递归断开所有的节点
slow = self.merge_sort(head)
fast =self.merge_sort(new_head)

# 合并
return self.merge(slow, fast)

def sortList(self, head):
"""
参考大佬的题解考虑使用归并排序
对于数组的归并排序来说,可以直接根据数组的长度来找到中间值,对于链表来说,我们可以通过快慢指针来找到中间节点
然后采用递归的方法将链表层层断开,排序后
最后再合并
:type head: ListNode
:rtype: ListNode
"""
return self.merge_sort(head)
]]> <h1>链表归并排序</h1> <p>用一张图来说明归并排序:</p> <p><img src="https://gitee.com/zyp521/upload_image/raw/master/wWJB4K.jpg" alt="figure.3"></p> <h2 id="代码 LeetCode No.154 www.strivezs.com/2021/07/31/LeetCode%E7%AC%AC154%E9%A2%98/ 2021-07-31T10:44:54.107Z 2021-07-31T10:44:54.107Z LeetCode第154题—寻找旋转排序数组中的最小值 II

自己代码的开源仓库:click here 欢迎Star和Fork :)

题目描述

已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,4,4,5,6,7] 在变化后可能得到:

给你一个可能存在 重复 元素值的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

示例 1

输入:nums = [1,3,5]
输出:1
示例 2

输入:nums = [2,2,2,0,1]
输出:0
 

提示:

n == nums.length
1 <= n <= 5000
-5000 <= nums[i] <= 5000
nums 原来是一个升序排序的数组,并进行了 1 至 n 次旋转

代码

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
class Solution(object):
def findMin(self, nums):
"""
除了return min(nums)之外的考虑,延续上一道题的想法
:type nums: List[int]
:rtype: int
"""
flag = True
if nums[0] < nums[-1]:
flag = True # 从左端开始找
else:
flag = False # 从右端开始找

for i in range(1, len(nums)):
if flag:
if nums[i] < nums[i - 1]:
return nums[i]
else:
if nums[len(nums) - i] < nums[len(nums) - 1 - i]:
return nums[len(nums) - i]
return nums[0]

if __name__ == '__main__':
s = Solution()
print(s.findMin([2,2,2,0,1]))
]]> <h1>LeetCode第154题—寻找旋转排序数组中的最小值 II</h1> <p>自己代码的开源仓库:<a href="https://github.com/zs670980918/LeetCode_Coding_Record">click here</a> 欢迎Star和 LeetCode No.153 www.strivezs.com/2021/07/28/LeetCode%E7%AC%AC153%E9%A2%98/ 2021-07-28T01:08:58.819Z 2021-07-28T01:08:58.819Z LeetCode第153题—寻找旋转排序数组中的最小值

自己代码的开源仓库:click here 欢迎Star和Fork :)

题目描述

已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]
注意,数组 [a[0], a[1], a[2], …, a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], …, a[n-2]] 。

给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
示例 1

输入:nums = [3,4,5,1,2]
输出:1
解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。
示例 2

输入:nums = [4,5,6,7,0,1,2]
输出:0
解释:原数组为 [0,1,2,4,5,6,7] ,旋转 4 次得到输入数组。
示例 3

输入:nums = [11,13,15,17]
输出:11
解释:原数组为 [11,13,15,17] ,旋转 4 次得到输入数组。


提示:

n == nums.length
1 <= n <= 5000
-5000 <= nums[i] <= 5000
nums 中的所有整数 互不相同
nums 原来是一个升序排序的数组,并进行了 1 至 n 次旋转

代码

非常不推荐

没意义.

1
2
3
4
5
6
7
class Solution(object):
def findMin(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
return min(nums)

正确思路

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
class Solution(object):
def findMin(self, nums):
"""
分析:
感觉题目的意思可以看出本题的实质是找到分断点(因为原数组是有序数组)
因此从两端开始判断的话,只需找到比较小的那一端,然后从小的那一端开始判断
1.如果是从左端开始的话,如果nums[i] <= nums[i+1],则继续右移,直到不满足结果
2. 如果是从右端开始的话,如果nums[i] <= nums[i+1], 则继续左移,直到不满足结果
:type nums: List[int]
:rtype: int
"""
flag = True
if nums[0] < nums[-1]:
flag = True # 从左端开始找
else:
flag = False # 从右端开始找

for i in range(1, len(nums)):
if flag:
if nums[i] < nums[i-1]:
return nums[i]
else:
if nums[len(nums) - i] < nums[len(nums) - 1 - i]:
return nums[len(nums) - i]
return nums[0]
if __name__ == '__main__':
s = Solution()
print(s.findMin(nums = [1,2,3,4,5]))
]]> <h1>LeetCode第153题—寻找旋转排序数组中的最小值</h1> <p>自己代码的开源仓库:<a href="https://github.com/zs670980918/LeetCode_Coding_Record">click here</a> 欢迎Star和For LeetCode No.152 www.strivezs.com/2021/07/27/LeetCode%E7%AC%AC152%E9%A2%98/ 2021-07-27T07:38:33.136Z 2021-07-27T07:38:33.136Z LeetCode第152题—乘积最大子数组

自己代码的开源仓库:click here 欢迎Star和Fork :)

题目描述

给你一个整数数组 nums ,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。

1
2
3
4
5
6
7
8
9
10
示例 1:

输入: [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6
示例 2:

输入: [-2,0,-1]
输出: 0
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution(object):
def maxProduct(self, nums):
"""
考虑使用动态规划. 因为数组中的值包含了正值和负值,可能会变为负负得正,或者你最大的正值乘个-1就会变为最小的负值
因此考虑使用两个数组来进行记录,分别记录当前的最大值和最小值, 然后进行后续应用
:type nums: List[int]
:rtype: int
"""
max_dp = [0] * len(nums)
min_dp = [0] * len(nums)
dp = [0] * len(nums)
max_dp[0] = nums[0]
min_dp[0] = nums[0]
dp[0] = nums[0]
for i in range(1, len(nums)):
max_dp[i] = max(max_dp[i-1] * nums[i], min_dp[i-1] * nums[i], nums[i])
min_dp[i] = min(max_dp[i-1] * nums[i], min_dp[i-1] * nums[i], nums[i])
dp[i] = max(max_dp[i], dp[i-1])
return dp[-1]

if __name__ == '__main__':
s = Solution()
print(s.maxProduct([-1, -2, -9, 6]))
]]> <h1>LeetCode第152题—乘积最大子数组</h1> <p>自己代码的开源仓库:<a href="https://github.com/zs670980918/LeetCode_Coding_Record">click here</a> 欢迎Star和Fork :)</ LeetCode No.151 www.strivezs.com/2021/07/24/LeetCode%E7%AC%AC151%E9%A2%98/ 2021-07-24T01:18:47.229Z 2021-07-24T01:18:47.229Z LeetCode第151题—翻转字符串里的单词

自己代码的开源仓库:click here 欢迎Star和Fork :)

题目描述

给你一个字符串 s ,逐个翻转字符串中的所有 单词 。

单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。

请你返回一个翻转 s 中单词顺序并用单个空格相连的字符串。

说明:

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
31
32
33
34
35

示例 1

输入:s = "the sky is blue"
输出:"blue is sky the"
示例 2

输入:s = " hello world "
输出:"world hello"
解释:输入字符串可以在前面或者后面包含多余的空格,但是翻转后的字符不能包括。
示例 3

输入:s = "a good example"
输出:"example good a"
解释:如果两个单词间有多余的空格,将翻转后单词间的空格减少到只含一个。
示例 4

输入:s = " Bob Loves Alice "
输出:"Alice Loves Bob"
示例 5

输入:s = "Alice does not even like bob"
输出:"bob like even not does Alice"


提示:

1 <= s.length <= 104
s 包含英文大小写字母、数字和空格 ' '
s 中 至少存在一个 单词


进阶:

请尝试使用 O(1) 额外空间复杂度的原地解法。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution(object):
def reverseWords(self, s):
"""
使用split分割之后进行翻转即可
:type s: str
:rtype: str
"""
s = s.split(' ')
res = ''
for i in range(len(s)):
if s[len(s) - i - 1] == '':
continue
if res == '':
res = s[len(s) - i - 1]
else:
res = res + ' ' + s[len(s) - i - 1]
return res

if __name__ == '__main__':
s = Solution()
print(s.reverseWords("a good example"))
]]> <h1>LeetCode第151题—翻转字符串里的单词</h1> <p>自己代码的开源仓库:<a href="https://github.com/zs670980918/LeetCode_Coding_Record">click here</a> 欢迎Star和Fork :) LeetCode 波兰式和逆波兰式 www.strivezs.com/2021/07/23/%E6%B3%A2%E5%85%B0%E5%BC%8F%E5%92%8C%E9%80%86%E6%B3%A2%E5%85%B0%E5%BC%8F/ 2021-07-23T09:20:02.152Z 2021-07-23T09:20:02.152Z 波兰式和逆波兰式

首先介绍一下中缀表达式,中缀表达式是人类最熟悉的表达式,比如1+2, (1+2)*3等。
如下图:

中缀表达式就是对上述二叉树进行中序遍历得到的结果。

波兰式又称为前缀表达式,它是对上述语法二叉树进行前序遍历得到的结果。上图的前缀表达式为:
-+A*B-CD*EF

逆波兰式又称为后缀表达式,是上述语法二叉树的后序遍历得到的结果。

]]> <h1>波兰式和逆波兰式</h1> <p>首先介绍一下中缀表达式,中缀表达式是人类最熟悉的表达式,比如1+2, (1+2)*3等。<br> 如下图:</p> <p><img src="https://gitee.com/zyp521/upload_image/raw/master LeetCode No.150 www.strivezs.com/2021/07/23/LeetCode%E7%AC%AC150%E9%A2%98/ 2021-07-23T09:19:13.883Z 2021-07-23T09:19:13.883Z LeetCode第150题—逆波兰表达式求值

自己代码的开源仓库:click here 欢迎Star和Fork :)

题目描述

根据 逆波兰表示法,求表达式的值。

有效的算符包括 +、-、*、/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。

说明:

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
示例 1

输入:tokens = ["2","1","+","3","*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
示例 2

输入:tokens = ["4","13","5","/","+"]
输出:6
解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6
示例 3

输入:tokens = ["10","6","9","3","+","-11","*","/","*","17","+","5","+"]
输出:22
解释:
该算式转化为常见的中缀算术表达式为:
((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22


提示:

1 <= tokens.length <= 104
tokens[i] 要么是一个算符("+""-""*""/"),要么是一个在范围 [-200, 200] 内的整数

代码

可以说只要想到用栈和理解逆波兰式的含义就十分简单了。唯一一点就是要注意只取整数部分,不考虑小数部分。

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
31
32
33
34
35
import math
class Solution(object):
def evalRPN(self, tokens):
"""
逆波兰式是后缀表达式
后缀表达式的求法:只需要处理符号的前两个值就可以了
那么就可以考虑使用栈来模拟计算过程
需要注意的是,这里只取整数部分,不考虑小数 因此考虑使用math.modf()
:type tokens: List[str]
:rtype: int
"""
stack = [] # 数字栈
characters = ['-', '+', '*', '/'] # 符号
for i in range(len(tokens)):
if tokens[i] in characters:
b = stack[-1]
stack.pop()
a = stack[-1]
stack.pop()
if tokens[i] == '-':
c = a - b
elif tokens[i] == '+':
c = a + b
elif tokens[i] == '*':
c = a * b
elif tokens[i] == '/':
c = a / b
stack.append(math.modf(c)[1])
else:
stack.append(int(tokens[i]))
return int(stack[-1])

if __name__ == '__main__':
s = Solution()
print(s.evalRPN(["10","6","9","3","+","-11","*","/","*","17","+","5","+"]))
]]> <h1>LeetCode第150题—逆波兰表达式求值</h1> <p>自己代码的开源仓库:<a href="https://github.com/zs670980918/LeetCode_Coding_Record">click here</a> 欢迎Star和Fork :)< LeetCode No.149 www.strivezs.com/2021/07/22/LeetCode%E7%AC%AC149%E9%A2%98/ 2021-07-22T03:26:58.728Z 2021-07-22T03:26:58.728Z LeetCode第149题—直线上最多的点数

自己代码的开源仓库:click here 欢迎Star和Fork :)

题目描述

给你一个数组 points ,其中 points[i] = [xi, yi] 表示 X-Y 平面上的一个点。求最多有多少个点在同一条直线上。

1
2
3
4
示例 1

输入:points = [[1,1],[2,2],[3,3]]
输出:3

1
2
3
4
5
6
7
8
9
10
示例 2
输入:points = [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
输出:4

提示:

1 <= points.length <= 300
points[i].length == 2
-104 <= xi, yi <= 104
points 中的所有点 互不相同

代码

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
from fractions import Fraction
class Solution(object):
# 统计在直线上点的个数
def num_points_on_line(self, k, b, points):
num = 0
for i in range(len(points)):
if points[i][0] * k + b == points[i][1]:
num += 1
return num

def time_out(self, points):
"""
暴力搜索的方法,目前自己能想到的方法
找到两个点求出斜率,然后确定还有多少个点在上面,找到最大的, 暴力搜索不出意外的Time out了,下面尝试对代码进行优化
:type points: List[List[int]]
:rtype: int
"""
if len(points) == 1:
return 1
if len(points) == 2:
return 2
max_num = 0
for i in range(len(points)):
for j in range(len(points)):
if i == j:
continue
if points[i][0] - points[j][0] == 0: # 为纵轴的情况
cur_num = 0
for m in range(len(points)):
if points[m][0] == points[i][0]:
cur_num += 1
else:
k = Fraction((points[i][1] - points[j][1]) , (points[i][0] - points[j][0]))
b = points[i][1] - k * points[i][0]
cur_num = self.num_points_on_line(k, b, points)
if cur_num > max_num:
max_num = cur_num
return max_num

def maxPoints(self, points):
"""
不出意料的暴力搜索的代码直接裂开了,我最开始的那个暴力算法冗余度太高了,后面需要进行优化,这里使用哈希表进行记忆
可以使用如下方法:
固定一个点来统计和其他的点的斜率
最后再将斜率和b相同的点个数统计,返回最大的值
考虑用字典来记录,字典:{斜率: [位于当前斜率上的点]}
:type points: List[List[int]]
:rtype: int
"""
if len(points) == 1:
return 1
if len(points) == 2:
return 2
max_num = 0
k_num = dict()
for i in range(len(points)):
for j in range(len(points)):
if i == j:
continue
if points[i][0] - points[j][0] == 0: # 为纵轴的情况 斜率不存在用对应的x值的字符串表示
if str(points[i][0]) not in k_num.keys():
k_num[str(points[i][0])] = []
if points[i] not in k_num[str(points[i][0])]:
k_num[str(points[i][0])].append(points[i])
if points[j] not in k_num[str(points[i][0])]:
k_num[str(points[i][0])].append(points[j])
if len(k_num[str(points[i][0])]) > max_num:
max_num = len(k_num[str(points[i][0])])
else:
k = Fraction((points[i][1] - points[j][1]) , (points[i][0] - points[j][0]))
b = points[i][1] - k * points[i][0]
key = str(k)+','+str(b)
if key not in k_num.keys():
k_num[key] = []
if points[i] not in k_num[key]:
k_num[key].append(points[i])
if points[j] not in k_num[key]:
k_num[key].append(points[j])
if len(k_num[key]) > max_num:
max_num = len(k_num[key])
return max_num
if __name__ == '__main__':
s = Solution()
print(s.maxPoints([[0,0],[4,5],[7,8],[8,9],[5,6],[3,4],[1,1]]))
]]> <h1>LeetCode第149题—直线上最多的点数</h1> <p>自己代码的开源仓库:<a href="https://github.com/zs670980918/LeetCode_Coding_Record">click here</a> 欢迎Star和Fork :)< LeetCode No.148 www.strivezs.com/2021/07/21/LeetCode%E7%AC%AC148%E9%A2%98/ 2021-07-21T04:59:18.746Z 2021-07-21T04:59:18.746Z LeetCode第148题—链表排序

自己代码的开源仓库:click here 欢迎Star和Fork :)

题目描述

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

进阶:

你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?

1
2
3
4
5
示例 1

输入:head = [4,2,1,3]
输出:[1,2,3,4]
示例 2

1
2
3
4
5
6
7
8
9
10
11
12
输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]
示例 3

输入:head = []
输出:[]


提示:

链表中节点的数目在范围 [0, 5 * 104] 内
-105 <= Node.val <= 105

归并排序思想

用一张图来说明归并排序:

代码

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution(object):
# fixme: 归并排序(自底向上合并链表)
def merge(self, node1, node2):
dummy = ListNode()
pre = dummy
while node1 is not None and node2 is not None:
if node1.val <= node2.val:
pre.next = node1
pre = pre.next
node1 = node1.next
else:
pre.next = node2
pre = pre.next
node2 = node2.next
if node1 is not None:
pre.next = node1
if node2 is not None:
pre.next = node2
return dummy.next

# fixme: 归并排序(自顶向下划分链表)
def merge_sort(self, head):
if head is None or head.next is None:
return head
# 快慢指针寻找中间节点
slow = head
fast = head
while fast.next is not None and fast.next.next is not None:
slow = slow.next
fast = fast.next.next
# 找到中间节点之后断开链表
new_head = slow.next
slow.next = None
# 递归断开所有的节点
slow = self.merge_sort(head)
fast =self.merge_sort(new_head)

# 合并
return self.merge(slow, fast)

def sortList(self, head):
"""
参考大佬的题解考虑使用归并排序
对于数组的归并排序来说,可以直接根据数组的长度来找到中间值,对于链表来说,我们可以通过快慢指针来找到中间节点
然后采用递归的方法将链表层层断开,排序后
最后再合并
:type head: ListNode
:rtype: ListNode
"""
return self.merge_sort(head)
]]> <h1>LeetCode第148题—链表排序</h1> <p>自己代码的开源仓库:<a href="https://github.com/zs670980918/LeetCode_Coding_Record">click here</a> 欢迎Star和Fork :)</p> LeetCode No.147 www.strivezs.com/2021/07/20/LeetCode%E7%AC%AC147%E9%A2%98/ 2021-07-20T02:17:16.938Z 2021-07-20T02:17:16.938Z LeetCode第147题—对链表进行插入排序

自己代码的开源仓库:click here 欢迎Star和Fork :)

题目描述

对链表进行插入排序。

插入排序的动画演示如上。从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示)。
每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中。

插入排序算法:

插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
重复直到所有输入数据插入完为止。

1
2
3
4
5
6
7
8
示例 1

输入: 4->2->1->3
输出: 1->2->3->4
示例 2

输入: -1->5->3->4->0
输出: -1->0->3->4->5

插入排序原理

用一张原理图来说明。

代码

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, val=0, next=None):
self.val = val
self.next = next

class Solution(object):
def insertionSortList(self, head):
"""
插入排序:除了第一个节点不动,第二个元素和前面已经排序好的元素进行比较,插入到合适的位置
重复上述过程即可。
比如:
1 3 5 2 4 |左边为排序好的节点
1 | 3 5 2 4
1 3 | 5 2 4
1 3 5 | 2 4
1 2 3 5 | 4
1 2 3 4 5 |
:type head: ListNode
:rtype: ListNode
"""
if head.next is None:
return head
ends = head.next
node = head.next
start = head
# 单独处理前两个节点
if node.val < start.val:
start.next = node.next
node.next = start
ends = start
start = node
head = node
# 递归处理后面所有情况
node = ends.next
while node is not None:
# 寻找合适的插入位置 (3种情况:头插入、中间插入、尾插入)
# 头插入
if node.val < start.val:
ends.next = node.next
node.next = start
start = node
head = node
node = ends.next
# 尾插入
elif node.val > ends.val:
ends = node
node = ends.next
# 中间插入
else:
cur = start
# 寻找插入位置
while True:
if node.val >= cur.val and node.val <=cur.next.val:
break
cur = cur.next
# 插入
ends.next = node.next
node.next = cur.next
cur.next = node
node = ends.next
return head
]]> <h1>LeetCode第147题—对链表进行插入排序</h1> <p>自己代码的开源仓库:<a href="https://github.com/zs670980918/LeetCode_Coding_Record">click here</a> 欢迎Star和Fork :) LeetCode No.146 www.strivezs.com/2021/07/19/LeetCode%E7%AC%AC146%E9%A2%98/ 2021-07-19T03:10:07.227Z 2021-07-19T03:10:07.227Z LeetCode第146题—LRU缓存机制

回家休息几天,搬宿舍心累。再回实验室就开始好好科研了!!!

自己代码的开源仓库:click here 欢迎Star和Fork :)

题目描述

运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制 。
实现 LRUCache 类:

LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存
int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。

进阶:你是否可以在 O(1) 时间复杂度内完成这两种操作?

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
示例:

输入
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
输出
[null, null, null, 1, null, -1, null, -1, 3, 4]

解释
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1); // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache.get(2); // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache.get(1); // 返回 -1 (未找到)
lRUCache.get(3); // 返回 3
lRUCache.get(4); // 返回 4


提示:

1 <= capacity <= 3000
0 <= key <= 10000
0 <= value <= 105
最多调用 2 * 105get 和 put

LRU缓存机制介绍

LRU:最近最少使用缓存机制

其设计的原则依据:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。
假定系统为某进程分配了3个物理块,进程运行时的页面走向为 7 0 1 2 0 3 0 4,开始时3个物理块均为空,那么LRU算法是如下工作的:

代码

自己写的

效率和内存差了点,但是自己纯手工写的。QAQ
核心思想就是通过使用双向链表和字典来存储内容。

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
class LRUCache(object):
"""
LRU 最近最少使用缓存机制:
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
对上面例子分析:
1. LRUCache 2 表示:创建一个容量为2的LRU缓存
2. put表示执行put操作,把1放到LRU中,并设置它的使用次数为1 其他所有数值的使用次数-1
3. put 2,2表示:把2放到LRU中,并设置它的使用次数为1 其他所有数值的使用次数-1
4. get 1表示使用一次LRU中的1,并将它的使用次数+1 其他所有数值的使用次数-1
5. put 3,3表示:把3放入到LRU中,因为LRU已经满了,因此需要将使用次数最小的那个值(2)置换出来,把3放进入 其他所有数值的使用次数-1

使用字典来存储key-value
使用list作为双端链表来存储使用次数
"""
def __init__(self, capacity):
"""
:type capacity: int
"""
self.length = capacity
self.lru_cache = [] # 双端链表,头部表示最新使用的节点,尾部是最久没使用的节点
self.key_value = dict()

def get(self, key):
"""
:type key: int
:rtype: int
"""
if key not in self.key_value.keys():
return -1
else:
# 如果能够获取,将访问的node放置于链表最前头
self.lru_cache.remove(key)
self.lru_cache.insert(0,key) # 置于链表头部
return self.key_value[key]

def put(self, key, value):
"""
:type key: int
:type value: int
:rtype: None
"""
if key in self.key_value.keys():
self.key_value[key] = value # 更新
# 如果能够获取,将访问的node放置于链表最前头
self.lru_cache.remove(key)
self.lru_cache.insert(0, key) # 置于链表头部
else:
if len(self.key_value) < self.length:
self.lru_cache.insert(0, key) # 置于链表头部
self.key_value[key] = value
else:
# 链表末尾元素出链表
rm_key = self.lru_cache[-1]
self.lru_cache.pop()
self.key_value.pop(rm_key)

# 添加新的元素
self.lru_cache.insert(0, key) # 置于链表头部
self.key_value[key] = value

if __name__ == '__main__':
t1 = ["LRUCache","get","put","get","put","put","get","get"]

t2 = [[2],[2],[2,6],[1],[1,5],[1,2],[1],[2]]
t = None
for i in range(len(t1)):
if t1[i] == 'LRUCache':
t = LRUCache(t2[i][0])
print('None')
elif t1[i] == 'put':
print(t.put(t2[i][0], t2[i][1]))
elif t1[i] == 'get':
print(t.get(t2[i][0]))
]]> <h1>LeetCode第146题—LRU缓存机制</h1> <p>回家休息几天,搬宿舍心累。再回实验室就开始好好科研了!!!</p> <p>自己代码的开源仓库:<a href="https://github.com/zs670980918/LeetCode_Coding_Rec LRU缓存机制 www.strivezs.com/2021/07/19/LRU(%E6%9C%80%E8%BF%91%E6%9C%80%E5%B0%91%E4%BD%BF%E7%94%A8)%E7%BC%93%E5%AD%98%E6%9C%BA%E5%88%B6/ 2021-07-19T03:09:05.136Z 2021-07-19T03:09:05.136Z LRU(最近最少使用)缓存机制

LRU:最近最少使用缓存机制

其设计的原则依据:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。
假定系统为某进程分配了3个物理块,进程运行时的页面走向为 7 0 1 2 0 3 0 4,开始时3个物理块均为空,那么LRU算法是如下工作的:

上述操纵通过一个双向链表就可以轻松实现了。
只需要每次将不论是否出现在链表中的值都置于链表的头就可以了,如果链表满了,就将链表的元素移除链表。

]]> <h1>LRU(最近最少使用)缓存机制</h1> <p>LRU:最近最少使用缓存机制</p> <p>其设计的原则依据:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。<br> 假定系统 LeetCode No.145 www.strivezs.com/2021/07/18/LeetCode%E7%AC%AC145%E9%A2%98/ 2021-07-18T11:05:43.496Z 2021-07-18T11:05:43.496Z LeetCode第145题—二叉树的后序遍历

回家休息几天,搬宿舍心累。再回实验室就开始好好科研了!!!

自己代码的开源仓库:click here 欢迎Star和Fork :)

题目描述

v给定一个二叉树,返回它的 后序 遍历。

1
2
3
4
5
6
7
8
9
10
11
示例:

输入: [1,null,2,3]
1
\
2
/
3

输出: [3,2,1]
进阶: 递归算法很简单,你可以通过迭代算法完成吗?

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Definition for a binary tree node.
class TreeNode(object):
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution(object):
res = []
# fixme: 后序遍历
def backward(self, node):
if node is not None:
self.backward(node.left)
self.backward(node.right)
self.res.append(node.val)

def postorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
self.res = []
self.backward(root)
return self.res
]]> <h1>LeetCode第145题—二叉树的后序遍历</h1> <p>回家休息几天,搬宿舍心累。再回实验室就开始好好科研了!!!</p> <p>自己代码的开源仓库:<a href="https://github.com/zs670980918/LeetCode_Coding_Re LeetCode No.143 www.strivezs.com/2021/07/16/LeetCode%E7%AC%AC144%E9%A2%98/ 2021-07-16T12:24:51.831Z 2021-07-16T12:24:51.831Z LeetCode第144题—二叉树的前序遍历

最近刚从雁栖湖搬到中关村。各方面和自己的预期很有差异。可能是还是没有适应。

自己代码的开源仓库:click here 欢迎Star和Fork :)

题目描述

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

1
2
3
4
5
6
7
8
9
10
11
12
13
示例 1

输入:root = [1,null,2,3]
输出:[1,2,3]
示例 2

输入:root = []
输出:[]

示例 3

输入:root = [1]
输出:[1]

1
2
3
示例 4
输入:root = [1,2]
输出:[1,2]

1
2
3
4
5
6
7
8
示例 5
输入:root = [1,null,2]
输出:[1,2]

提示:

树中节点数目在范围 [0, 100] 内
-100 <= Node.val <= 100
]]> <h1>LeetCode第144题—二叉树的前序遍历</h1> <p>最近刚从雁栖湖搬到中关村。各方面和自己的预期很有差异。可能是还是没有适应。</p> <p>自己代码的开源仓库:<a href="https://github.com/zs670980918/LeetCode_C LeetCode No.143 www.strivezs.com/2021/07/12/LeetCode%E7%AC%AC143%E9%A2%98/ 2021-07-12T03:48:59.497Z 2021-07-12T03:48:59.497Z LeetCode第143题—重排链表

即将回家!

自己代码的开源仓库:click here 欢迎Star和Fork :)

题目描述

给定一个单链表 L:L0→L1→…→Ln-1→Ln ,
将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→…

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

1
2
3
4
5
6
示例 1:

给定链表 1->2->3->4, 重新排列为 1->4->2->3.
示例 2:

给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3.

代码

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import copy
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, val=0, next=None):
self.val = val
self.next = next

class Solution(object):
def reorderList(self, head):
"""
分析题目可以得到这个链表就是通过中间节点划分之后,前端链表和后端链表合并的结果
因此可以先用快慢指针来找到中间节点,然后用栈存储后端链表节点
最后实现前端链表和栈节点合并即可
:type head: ListNode
:rtype: None Do not return anything, modify head in-place instead.
"""
if head is None or head.next is None:
return head
fast = head # 快指针
slow = head # 慢指针
mid = None # 中间节点
forward = [] # 用于存储前向链表的队列
stack = [] # 用于存储后端链表的栈
# 快慢指针寻找中间节点
while fast is not None and fast.next is not None:
fast = fast.next.next
forward.append(slow)
slow = slow.next
mid = slow
# 遍历后端链表节点,将所有节点都放到栈里面
node = mid
while node is not None:
stack.append(node)
node = node.next
# 合并前端链表和反向后端链表
node = head
temp = stack[-1]
stack.pop()
node.next = temp
node = node.next
for i in range(1,len(forward)):
node.next = forward[i]
node = node.next
temp = stack[-1]
stack.pop()
node.next = temp
node = node.next
if len(stack) != 0:
node.next = stack[-1]
node = node.next
node.next = None

return head

if __name__ == '__main__':
root = ListNode(1)
node1 = ListNode(2)
node2 = ListNode(3)
node3 = ListNode(4)

root.next = node1
node1.next = node2
node2.next = node3

s = Solution()
t = s.reorderList(root)
while t is not None:
print(t.val)
t = t.next
]]> <h1>LeetCode第143题—重排链表</h1> <p>即将回家!</p> <p>自己代码的开源仓库:<a href="https://github.com/zs670980918/LeetCode_Coding_Record">click here</a> 欢迎Star MAC+VSCode+Latex 配置Latex编写环境 www.strivezs.com/2021/07/09/MAC+VSCode+Latex%20%E9%85%8D%E7%BD%AELatex%E7%BC%96%E5%86%99%E7%8E%AF%E5%A2%83/ 2021-07-09T07:52:44.396Z 2021-07-09T07:52:44.396Z MAC+VSCode+Latex 配置Latex编写环境

安装VsCode

自行去官网下载安装VsCode就可以,下载地址

安装Mac Tex

这里我建议还是安装Latex吧,如果你的电脑空间不够了可以尝试安装Basic Tex,关于Basic Tex的相关内容我在之前的博文中讲过了(ps:其实他还是存在一些问题的,因此建议安装的是MacTex)。下面是安装MacTex的话可以通过如下命令进行安装:

1
2
3
4
5
6
7
8
9
10
brew cask install basictex

export PATH=/usr/local/texlive/2019basic/bin/x86_64-darwin:$PATH
// 打开usr.local隐藏路径,可以打开finder然后shift+command+G


// 安装相关包,安装包使用 tlmgr install命令进行安装
sudo tlmgr update --self --repository http://mirrors.tuna.tsinghua.edu.cn/CTAN/systems/texlive/tlnet

sudo tlmgr install latexmk --repository http://mirrors.tuna.tsinghua.edu.cn/CTAN/systems/texlive/tlnet

配置VsCode

安装Latex WorkShop插件

在VsCode中安装latex workshop插件,如下图:

配置设置

进入用户设置:

打开扩展->Json中的用户设置:

将下述内容添加到{}中即可:

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

"latex-workshop.latex.recipes": [{
"name": "xelatex",
"tools": [
"xelatex"
]
}, {
"name": "latexmk",
"tools": [
"latexmk"
]
},

{
"name": "pdflatex -> bibtex -> pdflatex*2",
"tools": [
"pdflatex",
"bibtex",
"pdflatex",
"pdflatex"
]
}
],
"latex-workshop.latex.tools": [{
"name": "latexmk",
"command": "latexmk",
"args": [
"-synctex=1",
"-interaction=nonstopmode",
"-file-line-error",
"-pdf",
"%DOC%"
]
}, {
"name": "xelatex",
"command": "xelatex",
"args": [
"-synctex=1",
"-interaction=nonstopmode",
"-file-line-error",
"%DOC%"
]
}, {
"name": "pdflatex",
"command": "pdflatex",
"args": [
"-synctex=1",
"-interaction=nonstopmode",
"-file-line-error",
"%DOC%"
]
}, {
"name": "bibtex",
"command": "bibtex",
"args": [
"%DOCFILE%"
]
}],
"latex-workshop.view.pdf.viewer": "tab",
"latex-workshop.latex.clean.fileTypes": [
"*.aux",
"*.bbl",
"*.blg",
"*.idx",
"*.ind",
"*.lof",
"*.lot",
"*.out",
"*.toc",
"*.acn",
"*.acr",
"*.alg",
"*.glg",
"*.glo",
"*.gls",
"*.ist",
"*.fls",
"*.log",
"*.fdb_latexmk"
],

完成上述步骤之后重启VsCode即可。

至于中文的设置可以通过引用

1
\documentclass[UTF8]{ctexart}

来实现.

]]> <h1>MAC+VSCode+Latex 配置Latex编写环境</h1> <h2 id="安装VsCode"><a class="header-anchor" href="#安装VsCode">¶</a>安装VsCode</h2> <p>自行去官网下载安装VsCode就可以,< LeetCode No.142 www.strivezs.com/2021/07/09/LeetCode%E7%AC%AC142%E9%A2%98/ 2021-07-09T00:55:19.752Z 2021-07-09T00:55:19.752Z LeetCode第142题—环形链表II

即将回家!

自己代码的开源仓库:click here 欢迎Star和Fork :)

题目描述

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。

说明:不允许修改给定的链表。

进阶:

你是否可以使用 O(1) 空间解决此题?

1
2
3
4
5
示例 1

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

1
2
3
4
5
示例 2

输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

1
2
3
4
5
6
7
8
9
10
11
示例 3

输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。

提示:

链表中节点的数目范围在范围 [0, 104] 内
-105 <= Node.val <= 105
pos 的值为 -1 或者链表中的一个有效索引

代码

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
31
32
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None

class Solution(object):
return_node = None
flag = True
def detectCycle(self, head):
"""
dfs遍历,返回环的第一个节点就好了
:type head: ListNode
:rtype: ListNode
"""
if head is None or head.next is None:
return None
self.return_node = None
self.flag = True # 结束标志
meomory = [] # 记忆列表

def dfs(node):
if self.flag:
if node is not None:
if node in meomory:
self.return_node = node
self.flag = False
meomory.append(node)
dfs(node.next)

dfs(head)
return self.return_node
]]> <h1>LeetCode第142题—环形链表II</h1> <p>即将回家!</p> <p>自己代码的开源仓库:<a href="https://github.com/zs670980918/LeetCode_Coding_Record">click here</a> 欢迎St Anaconda配置.yml来生成一个虚拟环境 www.strivezs.com/2021/07/08/Anaconda%E9%85%8D%E7%BD%AE.yml%E6%9D%A5%E7%94%9F%E6%88%90%E4%B8%80%E4%B8%AA%E8%99%9A%E6%8B%9F%E7%8E%AF%E5%A2%83/ 2021-07-08T11:31:44.999Z 2021-07-08T11:31:44.999Z Anaconda配置.yml来生成一个虚拟环境

创建新的环境的命令如下:

1
conda env create -f environment.yml

其中.yml是需要自己的配置的。

配置格式如下:

1
2
3
4
5
6
7
8
9
name: 虚拟环境名
channels:
- pytorch
- defaults
- 还是使用国内地清华源、科大源等
dependencies:
- 包名=版本号
- pip:(使用pip 进行安装的一些包)
- 包名=版本号

例子:

1
2
3
4
5
6
7
8
9
10
name: Total3D
channels:
- pytorch
- defaults
dependencies:
- _libgcc_mutex=0.1
- blas=1.0
- pip:
- cycler==0.10.0
- jellyfish==0.8.2
]]> <h1>Anaconda配置.yml来生成一个虚拟环境</h1> <p>创建新的环境的命令如下:</p> <figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</ LeetCode No.141 www.strivezs.com/2021/07/08/LeetCode%E7%AC%AC141%E9%A2%98/ 2021-07-08T11:27:58.407Z 2021-07-08T11:27:58.407Z LeetCode第141题—环形链表

这几天课比较多,有点忙,可能来不及更新喔

自己代码的开源仓库:click here 欢迎Star和Fork :)

题目描述

给定一个链表,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

如果链表中存在环,则返回 true 。 否则,返回 false 。

进阶:

你能用 O(1)(即,常量)内存解决此问题吗?

1
2
3
4
5
示例 1

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

1
2
3
4
5
示例 2

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

1
2
3
4
5
6
7
8
9
10
11
示例 3

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

提示:

链表中节点的数目范围是 [0, 104]
-105 <= Node.val <= 105
pos 为 -1 或者链表中的一个 有效索引

代码

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
31
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None

class Solution(object):
flag = True
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
if head is None:
return False
if head.next is None:
return False
self.flag = True
node_list = [] # 记忆node,如果出现过则表示存在环了
def dfs(node):
if node.next != None:
if node in node_list:
self.flag = False
return
node_list.append(node)
dfs(node.next)
dfs(head)
if self.flag:
return False
else:
return True
]]> <h1>LeetCode第141题—环形链表</h1> <p>这几天课比较多,有点忙,可能来不及更新喔</p> <p>自己代码的开源仓库:<a href="https://github.com/zs670980918/LeetCode_Coding_Record">click h