Hearted Youtube comments on NeetCode (@NeetCode) channel.
-
3200
-
2700
-
2200
-
2200
-
1700
-
1600
-
1600
-
1500
-
1400
-
1400
-
1300
-
1300
-
1200
-
1100
-
1000
-
1000
-
1000
-
1000
-
964
-
904
-
788
-
766
-
744
-
705
-
675
-
655
-
646
-
643
-
630
-
623
-
611
-
608
-
562
-
550
-
521
-
486
-
474
-
470
-
467
-
441
-
420
-
419
-
398
-
391
-
391
-
390
-
377
-
368
-
366
-
360
-
357
-
353
-
343
-
318
-
318
-
313
-
310
-
308
-
304
-
294
-
288
-
281
-
281
-
280
-
279
-
278
-
277
-
264
-
261
-
250
-
If you want to do the same thing in Python, you can use this code (and I'll explain it!):
class Solution:
def getSum(self, a: int, b: int) -> int:
mask = 0xffffffff
while b != 0:
tmp = (a & b) << 1
a = (a ^ b) & mask
b = tmp & mask
if a > mask // 2:
return ~(a ^ mask)
else:
return a
To explain, the hexadecimal number 0xffffffff is the same as the binary number 0b1111111111111111111111111111111, containing 32 1's. (It's just easier to type lol.)
In order to make the code work like Java, we want to treat our numbers like they only have 32 bits. ANDing a number with the mask 0xffffffff, or 32 1's, basically turns all of a number's bits into 0's except for the rightmost 32. As a result, the number can be represented as if it only has 32 bits.
We do what Neetcode describes in his video, using XOR for the sum and AND for the carry. We AND with the mask each time we set a and b in order to keep our numbers within 32 bits.
After we exit the while loop, we have our answer a. If a is positive, then we can return it directly. However, in Python, negative numbers are represented in binary as having an unlimited number of leading 1's. The current answer would only have values in the rightmost 32 bits. Therefore, if the answer is negative, we need to convert it into Python's representation of negative numbers.
First, we need to check if the answer is negative. We cannot just check to see if the answer is less than zero because our representation of the answer is not the same as Python's (since Python's have unlimited leading 1's). We are still treating our answer as if it only fits into 32 bits.
A 32-bit signed integer is positive if the 32nd bit is a 0 and is negative if the 32nd bit is a 1. If we divide our mask (0xffffffff) by 2, we will get the binary number 0b0111111111111111111111111111111, which has 31 1's. This number is the greatest value we can have before the 32nd bit becomes a 1. Therefore, if our answer a > mask // 2, it is negative. Otherwise, it is positive and we can just return a itself.
If the number is negative, we then need to convert it into Python's representation of negative numbers. To do so, we can XOR with the mask of 32 1's in order to flip the rightmost 32 bits, since XORing a bit with 1 flips the bit. We can then NOT the number in order to turn all of the leading 0's into 1's. For example, say that the answer is -3, and (....0000000) or (....1111111) denote leading 0's or 1's until the 32nd bit:
Our representation of -3 in 32 bits: (...0000000)11111111111111111111111111111101
XOR with mask, aka flip rightmost 32 bits: (...0000000)00000000000000000000000000000010
NOT, aka flipping all bits: (...1111111)1111111111111111111111111111101
The result is Python's representation of -3, including an unlimited number of leading 1's.
Overall, the code uses the same process as Neetcode's Java code, but with masking to get numbers into 32 bits and some manipulation to get those 32-bit numbers back into Python's representation before returning.
244
-
241
-
240
-
240
-
239
-
236
-
233
-
232
-
230
-
228
-
224
-
223
-
221
-
218
-
217
-
214
-
213
-
212
-
205
-
Actually, the reason why it works is simple, and it happens because of two factors.
First, if you moved to some value, and your total sum is greater than zero, then it means, that previous values did bring some value to the outcome. For example, we have gas = [2,3,0] and cost = [0,0,5]. If we take just solely value 3 without 2, it wouldn't be enough to pass the last station, but previous values definitely bring some value to the outcome.
Second, if we know, that there's definitely has to be a solution. Then, we may assume, that it has to be the smallest possible value, as I said before it may bring the most value to the result
205
-
204
-
199
-
195
-
195
-
195
-
188
-
188
-
188
-
188
-
187
-
183
-
182
-
181
-
181
-
176
-
176
-
175
-
162
-
161
-
159
-
159
-
157
-
157
-
156
-
155
-
155
-
154
-
153
-
151
-
149
-
149
-
149
-
147
-
146
-
143
-
141
-
141
-
137
-
137
-
136
-
135
-
134
-
133
-
133
-
131
-
Ok, I wasted my whole day on this problem, and finally found the bug. Anyone trying to code this in any language other than python will face the same issue;
I'll explain in-detail below
But here's the TL;DR
the bug comes down to how python and other languages do integer division, I was coding in C++, I believe most languages behave similarly
in C++, -1 / 2 = 0
in python -1 / 2 = -1;
so you'll have to adjust your code accordingly, I did this
=> mid = floor(left + (right - left) / 2.0)
so now lets talk about details and why this created a problem.
This difference in doing integer division created problem for smaller testcases, in longer testcase, the code would work fine.
but in testcases like A = [1,3], B = [2], or if either list is empty. i.e. A = [1], B = []; the ones actually mentioned on leetcode, it would give TLE
so why does it happens. well lets do a dry run for a smaller test case like;
=> A = [1,3], B = [2]
here
=> total = 3,
=> half = 1
we apply binary search on smaller list, therefore
=> left = 0, and right = 0
hence
=> mid1 = (left + right)/2 = 0 (i in the video)
=> mid1 = 0
=> mid2 = half - mid1 - 2 (j in the video)
=> mid2 = 1 - 0 - 2 = -1;
Now this makes
=> Aleft = 2
=> Aright = +inf
=> Bleft = -inf
=> Bright = 1
since Aleft > Bright
=> right = mid1 - 1 (or i - 1)
=> right = -1
now back to start of loop, we calculate mid again
=> mid1 = (left + right) / 2
=> mid1 = (0 + (-1))/2 = -1 / 2
and here's the issue, python would calculate this as -1, where as c++ and other languages will give you 0,
and if you haven't noticed we started with mid1 = 0, therefore, it will keep looping forever, until TLE.
to fix this, do this mid = floor(left + (right - left) / 2.0)
this is how python calculates integer division, it does float division and then takes floor.
this works fine for positive integers, there answer is same in python as other languages.
but for negative integers we find the mismatch.
the code works fine for larger inputs coz there your right is never negative
129
-
126
-
I will try to explain it in my own way-- please be patient and read it, hope you will get the intuition behind the algorithm.
There are 4 parts to it-
Part 1- sum of gas array>=sum of cost array--->
very intuitive, we should always have enough gas.
Part 2- we are keeping a total+=gas[i]-cost[i] for each i, and whenever it is <0 we are skipping that point and moving forward, making total 0--->
It means we ran out of gas if we started at some point which was <= current pos of i, so now we have to find a new starting position,
which wall be > curr pos of i.
Now think, why will this new start lie ahead of curr pos i, not anywhere before it, you could think, we started from point A------>B(total till +ve)------->C(total<0), as per this algo we try to find start ahead of C, what if we started from B and skipped A instead, well that won't work, You moved from A--------> B with some positive value(or 0), or else you would have stopped right at B and made total to 0. So add A improved our chances of having a positive total, so there is no point in looking for the new position start anywhere behind point C.
Part 3- When the total stays +ve, we dn't do anything to the start point, our start pointer points to the first index when our total became positive.
Again this is similar to the above explanation-l
ets suppose we start from X(-ve)--->Y(-ve)--->A(+ve)---->B(+ve)---->C(+ve), where C is the end of the array, our start(which is also the ans) would be A.
Why not B? why not C?
It is because we moved from A to B with some +ve value or atleast 0, whereas if we started from B we would have had only the value of B so earlier point added some value to our total, so its more favorable to help us reach the ans, hence earliest point is always better.
Part 4-- Why we just stop at point C and don t complete the cycle and check.
It is because from Part 1 we would have already identified that if the given set of inputs will have an ans, so if we have reached to Part 3 it means we surely have an ans, and it is mentioned in the question that there is only one valid ans, so we will always choose the most favorable ans-- which is also the fundamental idea of Greedy Algorithims. There is also a mathematical proof for this, that if we got a start point given our total gas >=total cost , we will be able to reach back to that point with just enough gas.
Hope this clears things out!
126
-
126
-
126
-
125
-
125
-
124
-
122
-
122
-
121
-
119
-
119
-
119
-
118
-
Neet's solution as of June 2022 TLEs.
To pass the Leetcode test cases you have to prune words from the prefix tree after you've found them. Here is the same as his solution with the addition of a `removeWord` method:
```python
class TrieNode:
def __init__(self):
self.children = {}
self.isWord = False
def addWord(self, word):
cur = self
for c in word:
if c not in cur.children:
cur.children[c] = TrieNode()
cur = cur.children[c]
cur.isWord = True
def pruneWord(self, word) -> None:
cur: TrieNode = self
nodeAndChildKey: list[tuple[TrieNode, str]] = []
for char in word:
nodeAndChildKey.append((cur, char))
cur = cur.children[char]
for parentNode, childKey in reversed(nodeAndChildKey):
targetNode = parentNode.children[childKey]
if len(targetNode.children) == 0:
del parentNode.children[childKey]
else:
return
class Solution:
def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
root = TrieNode()
for w in words:
root.addWord(w)
ROWS, COLS = len(board), len(board[0])
res, visit = [], set()
def dfs(r, c, node, word):
if (r < 0 or c < 0 or
r == ROWS or c == COLS or
board[r][c] not in node.children or (r, c) in visit):
return
visit.add((r, c))
node = node.children[board[r][c]]
word += board[r][c]
if node.isWord:
res.append(word)
node.isWord = False
root.pruneWord(word)
dfs(r + 1, c, node, word)
dfs(r - 1, c, node, word)
dfs(r, c + 1, node, word)
dfs(r, c - 1, node, word)
visit.remove((r, c))
for r in range(ROWS):
for c in range(COLS):
dfs(r, c, root, "")
return res
```
118
-
118
-
116
-
116
-
115
-
115
-
114
-
114
-
113
-
113
-
113
-
113
-
112
-
111
-
111
-
110
-
110
-
108
-
108
-
107
-
107
-
106
-
105
-
103
-
103
-
103
-
102
-
102
-
102
-
101
-
100
-
99
-
98
-
98
-
97
-
97
-
96
-
95
-
95
-
95
-
95
-
94
-
94
-
93
-
93
-
93
-
93
-
92
-
92
-
91
-
91
-
90
-
90
-
89
-
88
-
87
-
87
-
87
-
86
-
86
-
85
-
83
-
82
-
81
-
80
-
80
-
80
-
79
-
79
-
78
-
77
-
77
-
77
-
76
-
76
-
76
-
76
-
75
-
75
-
75
-
75
-
74
-
74
-
74
-
73
-
73
-
73
-
72
-
72
-
72
-
72
-
71
-
70
-
70
-
70
-
70
-
69
-
69
-
69
-
69
-
68
-
68
-
68
-
68
-
68
-
67
-
67
-
66
-
65
-
65
-
65
-
65
-
65
-
65
-
64
-
64
-
64
-
64
-
63
-
63
-
63
-
63
-
63
-
62
-
61
-
61
-
61
-
60
-
60
-
59
-
59
-
58
-
58
-
57
-
57
-
57
-
56
-
56
-
55
-
55
-
55
-
54
-
54
-
54
-
54
-
54
-
54
-
53
-
53
-
53
-
52
-
52
-
52
-
52
-
51
-
51
-
50
-
49
-
48
-
48
-
This could have been a good opportunity to introduce lambda syntax:
```
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
operatorMap = {
"+": lambda l,r: l + r,
"*": lambda l,r: l * r,
"-": lambda l,r: l - r,
"/": lambda l,r: int(l / r),
}
stack = []
for token in tokens:
if token in operatorMap:
right = stack.pop()
left = stack.pop()
token = operatorMap[token](left, right)
stack.append(int(token))
return stack.pop()
```
48
-
48
-
48
-
48
-
48
-
48
-
47
-
47
-
46
-
46
-
46
-
45
-
45
-
45
-
45
-
45
-
45
-
44
-
44
-
44
-
44
-
44
-
44
-
44
-
44
-
44
-
43
-
43
-
43
-
43
-
43
-
43
-
42
-
42
-
42
-
41
-
41
-
40
-
40
-
40
-
39
-
39
-
39
-
39
-
38
-
38
-
38
-
37
-
37
-
37
-
37
-
37
-
37
-
37
-
37
-
36
-
36
-
36
-
36
-
36
-
36
-
36
-
36
-
36
-
35
-
35
-
35
-
35
-
35
-
35
-
34
-
34
-
34
-
34
-
34
-
34
-
34
-
34
-
34
-
34
-
34
-
34
-
33
-
33
-
33
-
33
-
33
-
33
-
32
-
32
-
32
-
32
-
32
-
32
-
31
-
31
-
31
-
31
-
31
-
31
-
31
-
31
-
30
-
The O(1) memory solution:
def countVowelPermutation(self, n: int) -> int:
a, e, i, o, u = 1, 1, 1, 1, 1
for _ in range(n - 1):
a, e, i, o, u = e + i + u, a + i, e + o, i, i + o
return (a + e + i + o + u) % (10**9 + 7)
30
-
30
-
30
-
30
-
30
-
29
-
29
-
29
-
29
-
29
-
28
-
28
-
28
-
28
-
28
-
28
-
28
-
27
-
27
-
27
-
27
-
27
-
27
-
27
-
27
-
27
-
26
-
26
-
26
-
26
-
26
-
26
-
26
-
26
-
26
-
26
-
26
-
25
-
25
-
25
-
25
-
25
-
25
-
25
-
25
-
24
-
24
-
24
-
24
-
24
-
24
-
24
-
24
-
24
-
24
-
24
-
24
-
24
-
24
-
24
-
24
-
24
-
24
-
24
-
23
-
23
-
23
-
23
-
23
-
23
-
23
-
23
-
23
-
23
-
Algorithm questions are just a trick to filter out candidates according to your own implicit biases.
How? Because the way you ask the question, word the question, and provide feedback during the interview are completely ignored factors that shape how an interview actually goes.
Additionally, the content of these questions are completely irrelevant to actual day to day development work.
The part that is supposed to be evaluated by these questions, is how effectively a candidate approaches problem solving. Unfortunately, objectively measuring that within the scope of a single interview, is difficult. Speed in an interview doesn't mean you found the best developer. You just found a good interviewer. Possibly someone who managed to memorize the right stuff for that specific round of interviews.
The most reliable method of evaluating software engineers or any job applicant for that matter, is analyzing their track record. Sure, people can cheat on that, but you ask probing questions in the interview to verify how much they know about the work and accomplishments they claim. Unfortunately, that forces interviewers to do actual work.
23
-
23
-
23
-
22
-
22
-
22
-
22
-
22
-
22
-
22
-
22
-
22
-
21
-
21
-
21
-
21
-
21
-
21
-
21
-
21
-
21
-
21
-
21
-
21
-
21
-
20
-
20
-
20
-
20
-
20
-
20
-
20
-
20
-
20
-
20
-
20
-
20
-
20
-
20
-
19
-
19
-
19
-
19
-
19
-
19
-
19
-
19
-
19
-
19
-
19
-
19
-
19
-
19
-
19
-
19
-
19
-
19
-
19
-
19
-
19
-
19
-
19
-
18
-
18
-
18
-
18
-
18
-
18
-
18
-
18
-
18
-
18
-
18
-
18
-
18
-
18
-
18
-
18
-
18
-
18
-
18
-
18
-
18
-
17
-
17
-
17
-
17
-
Btw, I wanted to point out a possible bug someone may make. At first, I originally wrote line 20 as:
cache[r, c] = 1 + helper(aux(r, c + 1), helper(r + 1, c + 1), helper(r + 1, c))
to make it more concise, but it was failing half the tests. However, I realized that it was because you ALWAYS want to make recursive calls to the right diag down. By putting those recursive calls inside the if statement, you only make those recursive calls when you hit a '1'. If you hit a '0', your recursive functions stops there, and it doesnt call any more. Thats why you have to keep them separate
17
-
17
-
17
-
17
-
17
-
17
-
17
-
17
-
17
-
17
-
17
-
17
-
17
-
17
-
17
-
16
-
16
-
16
-
16
-
16
-
16
-
16
-
16
-
16
-
16
-
16
-
16
-
16
-
16
-
16
-
16
-
15
-
15
-
15
-
15
-
15
-
15
-
15
-
15
-
15
-
15
-
15
-
15
-
15
-
15
-
15
-
15
-
15
-
15
-
15
-
15
-
15
-
15
-
15
-
15
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
14
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
4:58 To answer your question about why Google doesn't migrate to the open-source variants of Google-internal tools (e.g., why Google doesn't migrate from Borg to Kubernetes), I believe it's because:
1. The cost of migration is not worth it โ given how much infrastructure and other Google assets (existing SWE knowledge, additional tooling, integrations with other Google-internal tools, etc.) are built on top of the old, Google-internal tool.
2. Open-source tool roadmaps are steered/influenced by other companies (e.g., Google doesn't have 100% control over what new features Kubernetes will support in the coming years).
My guess is that 1 is the main reason โ since some Google products DO use open-source tools (i.e., some Google products use Kubernetes).
(That said, it's hard to make general statements about Google, since Google is so big and each team is actually quite different.)
Great video, BTW. I learned a ton!
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
13
-
12
-
12
-
12
-
12
-
12
-
12
-
12
-
12
-
12
-
12
-
12
-
12
-
12
-
12
-
12
-
12
-
12
-
12
-
12
-
12
-
12
-
12
-
12
-
12
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
11
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
10
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
9
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
8
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
The thing is binary search is about if a condition comes True at a particular assume_point and if it is obvious that the condition will also be True for all the points below assume_point we can skip the points and traverse greater than it.
for example here
s="qobftgcueho" p="obue" removable array=[5,3,0,6,4,9,10,7,2,8]
k=? (max no of removable characters)
At 1st iteration in BinarySearch:
middle=4
so we are checking here that even after removing all the values in "removable array[:middle+1]" , is p a subsequence of s
i.e.; removing 5,3,0,6,4 index values from s.
Then s becomes s="obueho" and p="obue".Now still p is a subsequence of s which means k value will be greater than or equal to middle+1. So no need to traverse in the removed array below middle.
After 2nd iteration :
middle=7
so we are checking here that even after removing all the values in "removable array[:middle+1]" , is p a subsequence of s
i.e.; removing 5,3,0,4,6,9,10,7 index values from s.
Then s becomes s="obe" and p="obue".Now p is not a subsequence of s which means k value will be lesser than middle+1. So no need to traverse in the removed array above middle.
After 3rd iteration:
middle=5
removing 5,3,0,4,6,9 s="obueo" . p is a subsequence of s.So k will be greater than or equal to middle+1.
After 4th iteration:
middle=6
removing 5,3,0,4,6,9,10 s="obue" . p is a subsequence of s.So k will be greater than or equal to middle+1.
After this left>right.Iteration ends
k=middle+1 . ie.k=7
So using this binary search concept, we can able to do this in 4 iterations instead of 7(in case of linear).
Binary search is not always about sorted arrays.
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
7
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
Iterative solution instead of DFS:
num_row = len(island)
num_col = len(island[0])
directions = ((1, 0), (0, 1), (-1, 0), (0, -1))
perimeter = 0
for r in range(num_row):
for c in range(num_col):
if grid[r][c] == 1:
for x, y in directions:
neigh_x, neigh_y = r+x, y+c
if not (0 <= neigh_x < num_row and 0 <= neigh_y < num_col):
perimeter += 1
elif (0 <= neigh_x < num_row and 0 <= neigh_y < num_col) and grid[neigh_x][neigh_y] == 0:
perimeter += 1
return perimeter
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
6
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
I love how your videos are always so damn clear :) ! Thanks alot
Btw, here is a weird(?) quicksort version that beats 93%:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
count=list(Counter(nums).items())
def quick(l,r):
pivot,p = count[r][1],l
for i in range(l,r):
if pivot>=count[i][1]:
count[i], count[p] = count[p], count[i]
p+=1
count[r], count[p] = count[p], count[r]
if p>len(count)-k:
return quick(l,p-1)
if p<len(count)-k:
return quick(p+1,r)
else:
return p
ind=quick(0,len(count)-1)
return [k for i,(k,_) in enumerate(count) if i>=ind]
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
5
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
4
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
Here's the equivalent C++ code -
//t.c - O(26*N)
class Solution {
public:
int characterReplacement(string s, int k) {
int start=0, end=0, n=s.size(), mx=-1, cnt, ans=1, temp=-1;
char c;
vector<int> count(26, 0);
if(!n || k<0)
return 0;
while(end<n){
count[s[end]-'A']++;
mx=*max_element(count.begin(), count.end());
if(end-start+1-mx>k){
ans=max(ans, end-start);
count[s[start]-'A']--;
start++;
}
end++;
}
ans=max(ans, end-start);
return ans;
}
};
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
The thing about abstraction feel kinda weird. To me, google exposes waaaay more of how things work than most orgs, especially if theyโre built on public clouds. Like, you can see how racks/servers are organized in a way you typically wouldnโt think about elsewhere. You can see the code for everything - databases, distributed processing, VMs, whatever. A lot of the most unique stuff isnโt open source but the papers have been published to the public - spanner, flume, mapreduce, Zanzibar, etc - so you can kinda see how things work from the outside. Itโs pretty awesome.
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
I watched this video till 5:35 and was able to code it myself. Thanks.
C++ Guys:
class Solution {
public:
struct Compare{
bool operator()(pair<char,int>a,pair<char,int>b){
return a.second<b.second;
}
};
string reorganizeString(string s) {
unordered_map<char,int>mp;
for(int i=0;i<s.size();i++)
mp[s[i]]++;
priority_queue<pair<char,int>, vector<pair<char,int>>,Compare>pq;
for(auto it:mp)
pq.push({it.first,it.second});
string ans;
char prev='\0';
while(!pq.empty()){
pair<char,int>top=pq.top();
pq.pop();
if(top.first!=prev){
prev=top.first;
ans+=top.first;
top.second--;
if(top.second>0)
pq.push(top);
}
else if(!pq.empty()){
pair<char,int>top2=pq.top();
pq.pop();
prev=top2.first;
ans+=top2.first;
top2.second--;
if(top2.second>0)
pq.push(top2);
pq.push(top);
}
else
return "";
}
return ans;
}
};
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
for anyone who needs java version
public boolean canFinish(int numCourses, int[][] prerequisites) {
// 1) prerequisite map: be careful of course that without prerequisites data in the given array
HashMap<Integer, ArrayList<Integer>> prereq = new HashMap<>(); // course, prerequisites
for (int i = 0; i < numCourses; i++) {
prereq.put(i, new ArrayList<Integer>());
}
for (int[] prerequisite : prerequisites) {
prereq.get(prerequisite[0]).add(prerequisite[1]);
}
// 2) visited course set
HashSet<Integer> visited = new HashSet<>(); // course
// 3) dfs every course
for (int i = 0; i < numCourses; i++) {
if (!dfs(i, prereq, visited)) return false;
}
return true;
}
private boolean dfs(int course, HashMap<Integer, ArrayList<Integer>> prereq, HashSet<Integer> visited) {
if (visited.contains(course)) return false;
if (prereq.get(course).isEmpty()) return true;
visited.add(course);
for (int pre : prereq.get(course)) {
if (!dfs(pre, prereq, visited)) return false;
}
visited.remove(course);
prereq.put(course, new ArrayList<Integer>());
return true;
}
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1