Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitda1e870

Browse files
committed
add new solutions
1 parent5629fe8 commitda1e870

File tree

7 files changed

+93
-168
lines changed

7 files changed

+93
-168
lines changed

‎栈/316. 去除重复字母.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,5 @@ class Solution:
4141

4242
Tips
4343

44-
和402一脉相承,单调栈+贪心。原理来源于高位的字符越小整体的字典序越小,所以对于存在重复的字符,只要该字符在栈尾,且新的元素比它更小,就自动pop
44+
1. 和402一脉相承,单调栈+贪心。原理来源于高位的字符越小整体的字典序越小,所以对于存在重复的字符,只要该字符在栈尾,且新的元素比它更小,就自动pop
45+
2. 这里有个两个计数存储,seen用来判断是否入栈,已经在栈内的元素不入栈,hash的计数用来判断是否出栈,如果没有剩余元素则不能出栈

‎栈/32. 最长有效括号.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,6 @@ class Solution:
4949

5050
Tips
5151

52-
有效括号的升级版。计算最长的连续有效括号,计算括号是否有效通过左括号入栈,右括号弹出的操作可以实现,但是最长连续这里又一点tricky。其实是通过右括号也入栈来对有效的括号进行隔断。如果只有右括号,则右括号自动隔断前面的所有有效括号,这里stack=[-1]的初始位置是精髓
52+
有效括号的升级版。计算最长的连续有效括号,计算括号是否有效通过左括号入栈,右括号弹出的操作可以实现,但是最长连续这里又一点tricky。
53+
1. 左括号多:左括号本身不会被消掉,所以左index+1
54+
2. 右括号多:没有左括号与之匹配,所以右括号入栈形成隔断

‎链表/0.链表总结.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@
2929
- 234 回文链表:中间节点+翻转链表+遍历
3030
- 设计类
3131
- 146 LRU:双向链表,插入head(先建立node左右link,再插入),超过长度移除tail.prev, 移除是把元素左右node链接
32-
- 460 LFU:
3332
- 707 设计链表
3433
- 技巧题
35-
- 160 相交链表:
36-
- 382 链表随机节点:蓄水池算法,第K个节点有1/K的概率overwrite之前sample的元素
34+
- 160 相交链表:不用技巧,常规解法是把两个链表拼接到相同长度,然后开始遍历寻找相同节点
35+
- 382 链表随机节点:蓄水池算法,第K个节点有1/K的概率被采样

‎链表/143. 重排链表v.md

Lines changed: 40 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -52,49 +52,50 @@ class Solution:
5252
"""
5353
Do not return anything, modify head in-place instead.
5454
"""
55+
5556
ifnot head:
56-
return
57-
middle=self.find_middle(head)
58-
l2= middle.next
59-
l1= head
60-
middle.next=None
61-
l2=self.reverse(l2)
62-
result=self.merge_linklist(l1, l2)
63-
64-
@staticmethod
65-
deffind_middle(head):
66-
slow=head
67-
fast= head
68-
while fast.nextand fast.next.next:
69-
fast= fast.next.next
70-
slow= slow.next
71-
return slow
72-
73-
@staticmethod
74-
defreverse(head):
75-
cur= head
76-
newnode=None
77-
while cur:
78-
tmp= cur.next
79-
cur.next= newnode
80-
newnode= cur
81-
cur= tmp
82-
return newnode
83-
84-
@staticmethod
85-
defmerge_linklist(head1,head2):
86-
while head1and head2:
87-
tmp1= head1.next
88-
tmp2= head2.next
89-
90-
head1.next= head2
91-
92-
head1= tmp1
93-
head2= tmp2
57+
returnNone
58+
59+
defreverse(head):
60+
newnode=None
61+
cur= head
62+
while cur:
63+
nextnode= cur.next
64+
cur.next=newnode
65+
newnode= cur
66+
cur= nextnode
67+
return newnode
68+
69+
defgetmid(head):
70+
slow, fast= head, head
71+
while fast.nextand fast.next.next:
72+
slow= slow.next
73+
fast= fast.next.next
74+
return slow
75+
76+
defmerge(l1,l2):
77+
while l1and l2:
78+
l1_tmp= l1.next
79+
l2_tmp= l2.next
80+
81+
l1.next= l2
82+
l1= l1_tmp
83+
84+
l2.next= l1
85+
l2= l2_tmp
86+
ptr1= head
87+
left_mid= getmid(head)
88+
mid= left_mid.next
89+
left_mid.next=None# 注意这一步
90+
91+
ptr2= reverse(mid)
92+
merge(ptr1, ptr2)
9493
```
9594

9695

9796

9897
Tips
9998

100-
1. 这道题融合了三道题,快慢指针找中点,反转链表,合并两个链表
99+
1. 这道题融合了三道题,快慢指针找中点,反转链表,合并两个链表
100+
2. 比148多了融合这一步,融合是在原地进行的只改变link不改变value
101+
3. 需要注意的是这里find_mid找的是中点的左边界,因为需要设置mid.next=None, 把前半部分隔出来

‎链表/2. 两数相加.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,6 @@ class Solution:
6868
Tips:
6969

7070
1. 注意链表的赋值一般都是对next,这样可以有效避免创建空节点。如果每次val都是赋值给当前节点,则需要额外判断l1和l2是否为空决定是否创建链表的next节点
71+
2. 注意审题,是顺序向后加,remainder也是加在后面
72+
7173

‎链表/382. 链表随机节点.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,7 @@ Tips
4141

4242
蓄水池抽样
4343

44-
N个候选,第K个候选被采用的概率是1/K,
45-
4644
- K=1, p=1
4745
- K=2, p=1/2,覆盖K=1的概率是1/2
48-
- K=3, p=1/3,覆盖之前的概率是2/3,所以K=2的元素被选择的概率变成1/2 * 2/3 = 1/3
46+
- K=3, p=1/3,第3个节点本身被采样的概率论是1/3,保留之前随机数的概率是2/3,所以K=2的元素被选择的概率变成1/2 * 2/3 = 1/3
4947
-

‎链表总结.md

Lines changed: 43 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@
3030
- 234 回文链表:中间节点+翻转链表+遍历
3131
- 设计类
3232
- 146 LRU:双向链表,插入head(先建立node左右link,再插入),超过长度移除tail.prev, 移除是把元素左右node链接
33-
- 460 LFU:
3433
- 707 设计链表
3534
- 技巧题
36-
- 160 相交链表:可以用常规接发, 找到长度,拼接成相同长度,然后遍历判断是否有相交节点
37-
- 382 链表随机节点:蓄水池算法,第K个节点有1/K的概率overwrite之前sample的元素
35+
- 160 相交链表:不用技巧,常规解法是把两个链表拼接到相同长度,然后开始遍历寻找相同节点
36+
- 382 链表随机节点:蓄水池算法,第K个节点有1/K的概率被采样
37+
3838

3939
###138. 复制带随机指针的链表.md
4040

@@ -291,6 +291,7 @@ $$
291291
也就是当slow和fast在C点相遇后,只要有一个ptr从head开始,和slow一起向前跑,当slow再次走到C,并绕着环跑了n-1圈后,两者会在B相遇
292292

293293
###143. 重排链表v.md
294+
294295
给定一个单链表 L 的头节点 head ,单链表 L 表示为:
295296

296297
L0 → L1 → … → Ln - 1 → Ln
@@ -320,77 +321,60 @@ L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
320321
链表的长度范围为 [1, 5 * 104]
321322
1 <= node.val <= 1000
322323

323-
324-
325-
326-
327-
328324
```python
329-
# Definition for singly-linked list.
330-
classListNode:
331-
def__init__(self,val=0,next=None):
332-
self.val= val
333-
self.next=next
334-
335-
def__str__(self):
336-
res= []
337-
cur=self
338-
while cur:
339-
res.append(str(cur.val))
340-
cur= cur.next
341-
return'->'.join(res)
342-
343325
classSolution:
344326
defreorderList(self,head: ListNode) ->None:
345327
"""
346328
Do not return anything, modify head in-place instead.
347329
"""
330+
348331
ifnot head:
349-
return
350-
middle=self.find_middle(head)
351-
l2= middle.next
352-
l1= head
353-
middle.next=None
354-
l2=self.reverse(l2)
355-
result=self.merge_linklist(l1, l2)
356-
357-
@staticmethod
358-
deffind_middle(head):
359-
slow=head
360-
fast= head
361-
while fast.nextand fast.next.next:
362-
fast= fast.next.next
363-
slow= slow.next
364-
return slow
332+
returnNone
365333

366-
@staticmethod
367-
defreverse(head):
368-
cur= head
369-
newnode=None
370-
while cur:
371-
tmp= cur.next
372-
cur.next= newnode
373-
newnode= cur
374-
cur= tmp
375-
return newnode
334+
defreverse(head):
335+
newnode=None
336+
cur= head
337+
while cur:
338+
nextnode= cur.next
339+
cur.next=newnode
340+
newnode= cur
341+
cur= nextnode
342+
return newnode
343+
344+
defgetmid(head):
345+
slow, fast= head, head
346+
while fast.nextand fast.next.next:
347+
slow= slow.next
348+
fast= fast.next.next
349+
return slow
350+
351+
defmerge(l1,l2):
352+
while l1and l2:
353+
l1_tmp= l1.next
354+
l2_tmp= l2.next
376355

377-
@staticmethod
378-
defmerge_linklist(head1,head2):
379-
while head1and head2:
380-
tmp1= head1.next
381-
tmp2= head2.next
382-
383-
head1.next= head2
356+
l1.next= l2
357+
l1= l1_tmp
358+
359+
l2.next= l1
360+
l2= l2_tmp
361+
ptr1= head
362+
left_mid= getmid(head)
363+
mid= left_mid.next
364+
left_mid.next=None# 注意这一步
384365

385-
head1= tmp1
386-
head2= tmp2
366+
ptr2= reverse(mid)
367+
merge(ptr1, ptr2)
387368
```
388369

389370

390371

391372
Tips
392373

393374
1. 这道题融合了三道题,快慢指针找中点,反转链表,合并两个链表
375+
2. 比148多了融合这一步,融合是在原地进行的只改变link不改变value
376+
3. 需要注意的是这里find_mid找的是中点的左边界,因为需要设置mid.next=None, 把前半部分隔出来
377+
394378
###146. LRU 缓存机制.md
395379
运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制 。
396380

@@ -564,6 +548,7 @@ Tips
564548
- 插入搜索:如果比当前位置大直接插入,如果小就会到链表的起点进行重新搜索
565549

566550
- 注意比较时只能比较next节点,如果比较当前节点无法插入
551+
567552
###148. 排序链表.md
568553
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
569554

@@ -1500,73 +1485,10 @@ Tips
15001485

15011486
蓄水池抽样
15021487

1503-
N个候选,第K个候选被采用的概率是1/K,
1504-
15051488
- K=1, p=1
15061489
- K=2, p=1/2,覆盖K=1的概率是1/2
1507-
- K=3, p=1/3,覆盖之前的概率是2/3,所以K=2的元素被选择的概率变成1/2 * 2/3 = 1/3
1490+
- K=3, p=1/3,第3个节点本身被采样的概率论是1/3,保留之前随机数的概率是2/3,所以K=2的元素被选择的概率变成1/2 * 2/3 = 1/3
15081491
-
1509-
###460. LFU 缓存.md
1510-
请你为 最不经常使用(LFU)缓存算法设计并实现数据结构。
1511-
1512-
实现 LFUCache 类:
1513-
1514-
LFUCache(int capacity) - 用数据结构的容量 capacity 初始化对象
1515-
int get(int key) - 如果键存在于缓存中,则获取键的值,否则返回 -1。
1516-
void put(int key, int value) - 如果键已存在,则变更其值;如果键不存在,请插入键值对。当缓存达到其容量时,则应该在插入新项之前,使最不经常使用的项无效。在此问题中,当存在平局(即两个或更多个键具有相同使用频率)时,应该去除 最近最久未使用 的键。
1517-
1518-
注意「项的使用次数」就是自插入该项以来对其调用 get 和 put 函数的次数之和。使用次数会在对应项被移除后置为 0 。
1519-
1520-
为了确定最不常使用的键,可以为缓存中的每个键维护一个 使用计数器 。使用计数最小的键是最久未使用的键。
1521-
1522-
当一个键首次插入到缓存中时,它的使用计数器被设置为 1 (由于 put 操作)。对缓存中的键执行 get 或 put 操作,使用计数器的值将会递增。
1523-
1524-
1525-
1526-
示例:
1527-
1528-
输入:
1529-
["LFUCache", "put", "put", "get", "put", "get", "get", "put", "get", "get", "get"]
1530-
[[2],[1, 1],[2, 2],[1],[3, 3],[2],[3],[4, 4],[1],[3],[4]]
1531-
输出:
1532-
[null, null, null, 1, null, -1, 3, null, -1, 3, 4]
1533-
1534-
解释:
1535-
// cnt(x) = 键 x 的使用计数
1536-
// cache=[] 将显示最后一次使用的顺序(最左边的元素是最近的)
1537-
LFUCache lFUCache = new LFUCache(2);
1538-
lFUCache.put(1, 1); // cache=[1,_], cnt(1)=1
1539-
lFUCache.put(2, 2); // cache=[2,1], cnt(2)=1, cnt(1)=1
1540-
lFUCache.get(1); // 返回 1
1541-
// cache=[1,2], cnt(2)=1, cnt(1)=2
1542-
lFUCache.put(3, 3); // 去除键 2 ,因为 cnt(2)=1 ,使用计数最小
1543-
// cache=[3,1], cnt(3)=1, cnt(1)=2
1544-
lFUCache.get(2); // 返回 -1(未找到)
1545-
lFUCache.get(3); // 返回 3
1546-
// cache=[3,1], cnt(3)=2, cnt(1)=2
1547-
lFUCache.put(4, 4); // 去除键 1 ,1 和 3 的 cnt 相同,但 1 最久未使用
1548-
// cache=[4,3], cnt(4)=1, cnt(3)=2
1549-
lFUCache.get(1); // 返回 -1(未找到)
1550-
lFUCache.get(3); // 返回 3
1551-
// cache=[3,4], cnt(4)=1, cnt(3)=3
1552-
lFUCache.get(4); // 返回 4
1553-
// cache=[3,4], cnt(4)=2, cnt(3)=3
1554-
1555-
1556-
1557-
提示:
1558-
1559-
0 <= capacity, key, value <= 104
1560-
最多调用 105 次 get 和 put 方法
1561-
1562-
1563-
1564-
1565-
进阶:你可以为这两种操作设计时间复杂度为 O(1) 的实现吗?
1566-
1567-
```
1568-
```
1569-
15701492

15711493
###61. 旋转链表.md
15721494
####

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp