Skip to content

Commit 0b6b67c

Browse files
update
1 parent d0a6cb1 commit 0b6b67c

14 files changed

+499
-48
lines changed

BinarySearch/LC528 Random Pick with Weight.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
2121
问题转化为: 随机出一个[1,max_prefix_sum]之间的整数target 然后二分前缀和数组
2222
找到第一个大于等于target的值 等价于找到了这个随机数落在了哪个长度的区间内
23-
二分找到的值 代表了所在区间长度的右端点 它的下标 也就是w原数组的下标
23+
二分找到的值 代表了所在区间长度的右端点 它的下标 也就是w原数组的下标
24+
25+
测试方法: 1) fix target 比较output 2)call this multiple times
2426
'''
2527

2628
import random
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
'''
2+
Given two nodes of a binary tree p and q, return their lowest common ancestor (LCA).
3+
Each node will have a reference to its parent node. The definition for Node is below:
4+
'''
5+
6+
class Node:
7+
def __init__(self, val):
8+
self.val = val
9+
self.left = None
10+
self.right = None
11+
self.parent = None
12+
13+
# method 1. 计算两个节点的深度. 深的节点往上跳 直到两个节点深度一致. 然后两个节点同时往上跳 汇合时即为LCA
14+
# T: O(n) S: O(1)
15+
def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':
16+
p_depth = self.getDepth(p)
17+
q_depth = self.getDepth(q)
18+
19+
# 更深的节点向上移动 直到same level
20+
for _ in range(p_depth - q_depth):
21+
p = p.parent
22+
for _ in range(q_depth - p_depth):
23+
q = q.parent
24+
25+
# at the same level, return until they meet.
26+
while p != q:
27+
p = p.parent
28+
q = q.parent
29+
return p
30+
31+
def getDepth(self, node):
32+
dep = 0
33+
while node:
34+
dep += 1
35+
node = node.parent
36+
return dep
37+
38+
# method 2: 用set存储p的所有parents. q向上找, 如果parent in set, 则是LCA
39+
# T: O(n) S: O(n)
40+
def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':
41+
if not p or not q: return None
42+
parentSet = set()
43+
while p:
44+
parentSet.add(p)
45+
p = p.parent
46+
47+
while q:
48+
if q in parentSet:
49+
return q
50+
else:
51+
q = q.parent
52+
return None
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
'''
2+
ocean在右边.要求返回有o view元素的下标 下标从小到大返回.
3+
'''
4+
5+
'''
6+
solution: monotolic stack. stack存下标 下标对应元素的高度单调增 stack top的高度最小
7+
T: O(n) S: O(n)
8+
'''
9+
def findBuildings(heights: List[int]) -> List[int]:
10+
if not heights:
11+
return []
12+
stack = []
13+
for i in range(len(heights)):
14+
while stack and heights[stack[-1]] <= heights[i]:
15+
stack.pop() # 栈顶对应的高度<=当前高度 则栈顶一定没有o view
16+
stack.append(i)
17+
return stack

Meta/LC227 Basic Calculator II.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# 包括加减乘除 没有括号
2+
3+
'''
4+
linear scan: time O(n) space O(1)
5+
let ch be current char in s
6+
1. 如果ch.isdigit() 记录number
7+
2. 如果当前ch in "+-/*", 看previous sign(op): cur此时累进计算前面的+-*/
8+
2.1 如果当前ch in "+-", 把cur累加到ret, cur归零
9+
2.2 pre_op = ch(把当前ch给pre_op, 用pre_op记录previous operator), num归零
10+
'''
11+
def calculate0(s) -> int:
12+
if not s:
13+
return 0
14+
15+
ret, cur = 0, 0
16+
pre_op = '+'
17+
18+
s += '+' # 最后一个数可能会被漏掉 在s后面append一个'+' 方便计算
19+
num = 0 # 截取s中的数字 可能有多位数
20+
21+
for ch in s:
22+
if ch.isdigit():
23+
num = num * 10 + int(ch) # 注意这里是= 不是+=
24+
25+
if ch in ('+', '-', '*', '/'):
26+
if pre_op == '+':
27+
cur += num
28+
elif pre_op == '-':
29+
cur -= num
30+
elif pre_op == '*':
31+
cur *= num
32+
else: # pre_op is '/'
33+
cur = int(cur / num) # 有可能有负数除法 要用int() 不能用//
34+
# 这里的if 和下面堆pre_op/num赋值 都在ch是运算符的if条件下
35+
if ch in ('+', '-'):
36+
ret += cur
37+
cur = 0
38+
39+
pre_op = ch
40+
num = 0
41+
42+
return ret
43+
44+
# method 2: stack T O(n) S O(n)
45+
def calculate1(self, s: str) -> int:
46+
stack = []
47+
num = 0
48+
sign = "+"
49+
for i, c in enumerate(s):
50+
if c.isdigit():
51+
num = num * 10 + int(c)
52+
if c in "+-*/" or i == len(s) - 1: #最后一个数 既要参与上面if计算 也要在这里计算. 所以不能用elif
53+
if sign == "+":
54+
stack.append(num)
55+
if sign == "-":
56+
stack.append(-num)
57+
if sign == "*":
58+
stack.append(stack.pop() * num)
59+
if sign == "/":
60+
stack.append(int(stack.pop() / num)) # "//"不能做负数运算 需要用int(a/b)
61+
62+
sign = c
63+
num = 0
64+
return sum(stack)

Meta/LC339 Nested List Weight Sum.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
'''
2+
given a nested list of integers nestedList. Each element is either an integer or a list whose elements may also be integers or other lists.
3+
The depth of an integer is the number of lists that it is inside of. For example, the nested list [1,[2,2],[[3],2],1] has each integer's value set to its depth.
4+
Return the sum of each integer in nestedList multiplied by its depth.
5+
Example 1:
6+
Input: nestedList = [[1,1],2,[1,1]]
7+
Output: 10
8+
Explanation: Four 1's at depth 2, one 2 at depth 1. 1*2 + 1*2 + 2*1 + 1*2 + 1*2 = 10.
9+
'''
10+
11+
'''
12+
解法1:bfs. say N is the total number of nested elements in input: nested list + integers.
13+
T: O(N) S: O(N)
14+
'''
15+
16+
def depthSum0(nestedList: List[NestedInteger]) -> int:
17+
if not nestedList:
18+
return 0
19+
level = 1
20+
queue = collections.deque(nestedList) #这里不要加"[]":把nestedList对象入队,不能变成list结构!
21+
ret = 0
22+
while queue:
23+
for _ in range(len(queue)): # 遍历当前层
24+
cur = queue.popleft()
25+
if cur.isInteger():
26+
ret += cur.getInteger() * level
27+
else:
28+
queue.extend(cur.getList()) # 取出当前item的内置items入队
29+
level += 1 # 当前层遍历完
30+
return ret
31+
32+
'''
33+
解法1:dfs. say N is the total number of nested elements in input: nested list + integers.
34+
T: O(N) S: O(N) for recursive call stack. e,g, [[[[1]]]]
35+
'''
36+
def depthSum1(nestedList: List[NestedInteger]) -> int:
37+
if not nestedList:
38+
return 0
39+
return self.dfs(nestedList, 1)
40+
41+
def dfs(nestedList: List[NestedInteger], level: int) -> int:
42+
ret = 0
43+
for item in nestedList: # 遍历的是List of NestedInteger
44+
if item.isInteger():
45+
ret += item.getInteger() * level
46+
else: # 不可以直接算的 用getList()取出来 递归往下传 level+1
47+
ret += self.dfs(item.getList(), level + 1)
48+
return ret

Meta/LC50 Pow(x, n).py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# method 1: iterative. time o(logn) space o(1)
2+
def myPow(self, x: float, n: int) -> float:
3+
if n == 0:
4+
return 1
5+
6+
# Handle case where, n < 0.
7+
if n < 0:
8+
n = -1 * n
9+
x = 1.0 / x
10+
11+
# Perform Binary Exponentiation.
12+
result = 1
13+
while n != 0:
14+
# If 'n' is odd
15+
if n % 2 == 1:
16+
result *= x
17+
n -= 1
18+
# We square 'x' and reduce 'n' by half, x^n => (x^2)^(n/2).
19+
x *= x
20+
n //= 2
21+
return result
22+
23+
# method2: recursive time O(logn) space O(h) at most o(logn)
24+
def myPow(self, x: float, n: int) -> float:
25+
if x == 0: return 0
26+
if x == 1: return 1
27+
if n == 0: return 1
28+
if n < 0:
29+
return 1/self.myPow(x, -n)
30+
if n % 2 == 0:
31+
return self.myPow(x*x, n // 2)
32+
else: # n%2==1
33+
return x * self.myPow(x, n - 1) # x在外面乘

Meta/LC71 Simplify Path.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
'''
2+
Meta version
3+
Given current directory and change directory path, return final path.
4+
5+
For Example:
6+
Curent Change Output
7+
8+
/ /facebook /facebook
9+
/facebook/anin ../abc/def /facebook/abc/def
10+
/facebook/instagram ../../../../. /
11+
'''
12+
13+
def change_path(cwd: str, cd: str) -> str:
14+
path = cwd + "/" + cd # 先把两个path用'/'连起来
15+
stack = []
16+
for dir in path.split('/'):
17+
if dir == ".":
18+
continue
19+
elif dir == "..":
20+
if stack:
21+
stack.pop()
22+
elif not dir: # 注意 如果当前dir为空 题意需要回到根目录
23+
stack.clear()
24+
else:
25+
stack.append(dir)
26+
27+
return "/" + "/".join(stack)
28+
29+
# unit test
30+
cwd1 = '/facebook/anin'
31+
cd1 = '../abc/def'
32+
print(change_path(cwd1, cd1))
33+
cwd2 = '/'
34+
cd2 = '/facebook'
35+
print(change_path(cwd2, cd2))
36+
cwd3 = '/facebook/anin'
37+
cd3 = '..//def'
38+
print(change_path(cwd3, cd3))
39+
40+
'''
41+
用stack存最终返回path里面的子path
42+
用'/'把input split成list
43+
如果遇到“..”:
44+
如果有stack就pop. 如果“.” or "", continue. else stack.append
45+
'''
46+
def simplifyPath(self, path: str) -> str:
47+
if not path:
48+
return ""
49+
stack = []
50+
path_list = path.split("/")
51+
for item in path_list:
52+
if item == "." or item == "":
53+
continue
54+
elif item == "..": # 退到上一层
55+
if stack:
56+
stack.pop()
57+
else:
58+
stack.append(item)
59+
return "/" + "/".join(stack) # 前面加一个'/'

Meta/LC88 Merge Sorted Array.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from typing import List
2+
# meta version: output no duplicates
3+
def merge_no_duplicates(nums1: List[int], nums2: List[int]) -> None:
4+
res = []
5+
i, j = 0, 0
6+
while i < len(nums1) and j < len(nums2):
7+
if nums1[i] <= nums2[j]:
8+
if not res or res[-1] != nums1[i]:
9+
res.append(nums1[i])
10+
i += 1
11+
else:
12+
if not res or res[-1] != nums2[j]:
13+
res.append(nums2[j])
14+
j += 1
15+
16+
while i < len(nums1):
17+
if not res or res[-1] != nums1[i]:
18+
res.append(nums1[i])
19+
i += 1
20+
while j < len(nums2):
21+
if not res or res[-1]!= nums2[j]:
22+
res.append(nums2[j])
23+
j += 1
24+
return res
25+
26+
nums1 = [1,1,2,2,5,5]
27+
nums2 = [3,3,4,4]
28+
nums3 = []
29+
print(merge_no_duplicates(nums3, nums3))
30+
31+
# in-place modify. need to go backward.
32+
def merge(nums1: List[int], m: int, nums2: List[int], n: int) -> None:
33+
"""
34+
Do not return anything, modify nums1 in-place instead.
35+
"""
36+
i, j, k = m - 1, n - 1, m + n - 1
37+
while i >= 0 and j >= 0:
38+
if nums1[i] >= nums2[j]:
39+
nums1[k] = nums1[i]
40+
i -= 1
41+
k -= 1
42+
else:
43+
nums1[k] = nums2[j]
44+
j -= 1
45+
k -= 1
46+
47+
while i >= 0:
48+
nums1[k] = nums1[i]
49+
i -= 1
50+
k -= 1
51+
while j >=0:
52+
nums1[k] = nums2[j]
53+
j -= 1
54+
k -= 1
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
'''
2+
Given an array of integers arr, randomly return an index of the maximum value seen by far.
3+
Example:
4+
Input: [11, 30, 2, 30, 30, 30, 6, 2, 62, 62]
5+
Having iterated up to the at element index 5 (where the last 30 is), randomly give an index among [1, 3, 4, 5] which are indices of 30 - the max value by far. Each index should have a ¼ chance to get picked.
6+
Having iterated through the entire array, randomly give an index between 8 and 9 which are indices of the max value 62.
7+
'''
8+
import random
9+
10+
# 思路: reservoir sampling T(n) S(1)
11+
def max_random_index(nums):
12+
max_val = float('-inf')
13+
idx_max = -1
14+
count = 0
15+
16+
for i, n in enumerate(nums):
17+
if n > max_val:
18+
max_val = n
19+
count = 1
20+
idx_max = i
21+
elif n == max_val:
22+
count += 1
23+
r = random.randint(1, count)
24+
if r == 1:
25+
idx_max = i
26+
27+
print(i, idx_max)
28+
29+
nums = [11, 30, 2, 30, 30, 30, 6, 2, 62, 62]
30+
print(max_random_index(nums))

0 commit comments

Comments
 (0)