Skip to content

Commit d403a5c

Browse files
committed
submissions until 2020/01/05
1 parent 3b4a972 commit d403a5c

File tree

1 file changed

+122
-0
lines changed

1 file changed

+122
-0
lines changed

ok_2_keys_keyboard.py

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
"""
2+
650. 2 Keys Keyboard
3+
Medium
4+
5+
Initially on a notepad only one character 'A' is present.
6+
You can perform two operations on this notepad for each step:
7+
Copy All: You can copy all the characters present on the notepad (partial copy is not allowed).
8+
Paste: You can paste the characters which are copied last time.
9+
10+
Given a number n. You have to get exactly n 'A' on the notepad by performing the minimum number of steps permitted.
11+
Output the minimum number of steps to get n 'A'.
12+
13+
Example 1:
14+
Input: 3
15+
Output: 3
16+
17+
Explanation:
18+
Intitally, we have one character 'A'.
19+
In step 1, we use Copy All operation.
20+
In step 2, we use Paste operation to get 'AA'.
21+
In step 3, we use Paste operation to get 'AAA'.
22+
23+
Note:
24+
The n will be in the range [1, 1000].
25+
26+
Details
27+
Runtime: 24 ms, faster than 93.91% of Python3 online submissions for 2 Keys Keyboard.
28+
Memory Usage: 12.7 MB, less than 100.00% of Python3 online submissions for 2 Keys Keyboard.
29+
"""
30+
from collections import defaultdict
31+
32+
33+
class Solution:
34+
def minSteps(self, n: int) -> int:
35+
"""
36+
Min steps to iterate from 1 to n while have only 2 ops: copy all and paste
37+
38+
n=2: 'A' -> copy -> paste -> 'AA'
39+
n=3: 'A' -> copy -> paste -> paste -> 'AAA'
40+
n=4: 'A' -> copy -> paste -> copy -> paste -> 'AAAA'
41+
n=5: 'A' -> copy -> paste -> paste -> paste -> paste -> 'AAAAA'
42+
In that case we can just paste and copy last combination, since. if we paste
43+
n+1 % 2 == 1 -> 1,3,5,7,.. we can paste only 1,3,5,7,.. els
44+
45+
So, when we should decide is COPY possible?
46+
n=6: 'A' -> copy -> paste -> copy -> paste -> paste -> 'AAAAAA' 6=1*2*3
47+
or -> copy -> paste -> paste -> copy -> paste -> 'AAAAAA'
48+
n=7: 'A' -> copy -> paste -> paste -> paste -> paste -> .. ans=7
49+
Note: prime numbers we can't copy multiple times! Only once when n=1
50+
n=8: copy->paste->copy->paste->copy->paste 8=2*4
51+
'AA' 'AAAA' 'AAAAAAAA'
52+
n=30: 30=1,2,3,5,10,15,30
53+
54+
1. build weighted graph, in forward notation: (vertex,weight or N_PASTE to achieve vertex)
55+
1: (2,1), (3,2), (5,4), (10,9), (15,14), (30,29)
56+
2: (6,2), (10,4), (30,14)
57+
3: (15,4), (30,9)
58+
5: (10,1), (15,2), (30,5)
59+
6: (30,4)
60+
10: (30,2)
61+
15: (30,1)
62+
30: (30,0)
63+
Note! and plus 1 for COPY operation
64+
2. use dfs to track best path:
65+
so: 1->2->10->30 = 1+4+2 + 3 = 10
66+
->30 = 1+4+14 + 2 = 29
67+
1->3->15->30 = 2+4+1 + 3 = 10
68+
->30 = 2+9 + 2 = 13
69+
and so on
70+
71+
n=27 (graph): 27=3,9,27
72+
1: (3,3), (9,9), (27,27)
73+
3: (9,3), (27,9)
74+
9: (27,3)
75+
27: None
76+
Q1: How to build the structure above?
77+
1. Find all factors
78+
Q2: How to improve performance?
79+
1. Can we remove weight and replace it by value//key? A: Yes => 32ms -> 24ms
80+
81+
M = log(N)
82+
T ~ O(N + log(N)*log(N) + log(N)+K) in theory
83+
"""
84+
graph = defaultdict(list)
85+
for num in range(2, n + 1): # T ~ O(N) to find all factors
86+
if n % num == 0:
87+
graph[1].append(num)
88+
89+
for i, vertex in enumerate(graph[1]): # T ~ O(M*M*1), where M - number of factors; to build graph
90+
for v in graph[1][i + 1:]: # O(M*1)
91+
if v % vertex == 0:
92+
graph[vertex].append(v)
93+
94+
value = v * vertex
95+
if value in graph[vertex]: # O(1)
96+
graph[vertex].append(value)
97+
98+
params = {'min_n_steps': n}
99+
100+
def backtracking(key, n_steps):
101+
if key == n:
102+
if params['min_n_steps'] > n_steps:
103+
params['min_n_steps'] = n_steps
104+
return
105+
106+
for k in graph[key]:
107+
backtracking(k, n_steps + k // key)
108+
109+
backtracking(1, 0) # T ~ O(M+K), where K is number of edges; for dfs
110+
return params['min_n_steps']
111+
112+
113+
def _main():
114+
from utils import check_result
115+
116+
inputs = [27, 30, 2, 3, 4, 5, 6, 7, 8]
117+
targets = [9, 10, 2, 3, 4, 5, 5, 7, 6]
118+
check_result(Solution().minSteps)(inputs, targets)
119+
120+
121+
if __name__ == '__main__':
122+
_main()

0 commit comments

Comments
 (0)