├── .gitignore ├── Arrays ├── 2DArrayDS.py ├── ArrayManipulation.py ├── ArraysLeftRotation.py ├── MinimumSwaps2.py └── NewYearChaos.py ├── DictionariesAndHashmaps ├── CountTriplets.py ├── FrequencyQueries.py ├── HashTablesRansomNote.py ├── SherlockAndAnagrams.py └── TwoStrings.py ├── DynamicProgramming ├── Abbreviation.py ├── AbbreviationCached.py ├── Candies.py ├── DecibinaryNumbers.py └── MaxArraySum.py ├── Graphs ├── ConnectedCellInAGrid.py ├── FindTheNearestClone.py ├── Matrix.py ├── RoadsAndLibraries.py └── ShortestReachInAGraph.py ├── GreedyAlgorithms ├── GreedyFlorist.py ├── LuckBalance.py ├── MaxMin.py ├── MinimumAbsoluteDifferenceInAnArray.py └── ReverseShuffleMerge.py ├── LinkedLists ├── DetectACycle.py ├── FindMergePointOfTwoLists.py ├── InsertANodeAtASpecificPositionInALinkedList.py ├── InsertingANodeIntoASortedDoublyLinkedList.py └── ReverseADoublyLinkedList.py ├── Miscellaneous ├── FlippingBits.py ├── FriendCircleQueries.py ├── MaximumXor.py └── TimeComplexityPrimality.py ├── README.md ├── RecursionAndBacktracking ├── CrosswordPuzzle.py ├── RecursionDavisStaircase.py ├── RecursionFibonacciNumbers.py └── RecursiveDigitSum.py ├── Search ├── HashTablesIceCreamParlor.py ├── MakingCandies.py ├── MaximumSubarraySum.py ├── MinimumTimeRequired.py ├── Pairs.py ├── SwapNodes.py └── TripleSum.py ├── Sorting ├── BubbleSort.py ├── Comparator.py ├── FraudulentActivityNotifications.py ├── MarkAndToys.py └── MergeSortCountingInversions.py ├── StacksAndQueues ├── BalancedBrackets.py ├── CastleOnTheGrid.py ├── LargestRectangle.py ├── MinMaxRiddle.py ├── PoisonousPlants.py └── QueuesATaleOfTwoStacks.py ├── StringManipulation ├── AlternatingCharacters.py ├── CommonChild.py ├── MakingAnagrams.py ├── SherlockAndTheValidString.py └── SpecialPalindromeAgain.py ├── Trees ├── HeightOfABinaryTree.py ├── HuffmanDecoding.py ├── IsThisABinarySearchTree.py └── LowestCommonAncestor.py └── WarmupChallenges ├── CountingValleys.py ├── JumpingOnTheClouds.py ├── RepeatedString.py └── SockMerchant.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | 53 | # Translations 54 | *.mo 55 | *.pot 56 | 57 | # Django stuff: 58 | *.log 59 | local_settings.py 60 | db.sqlite3 61 | 62 | # Flask stuff: 63 | instance/ 64 | .webassets-cache 65 | 66 | # Scrapy stuff: 67 | .scrapy 68 | 69 | # Sphinx documentation 70 | docs/_build/ 71 | 72 | # PyBuilder 73 | target/ 74 | 75 | # Jupyter Notebook 76 | .ipynb_checkpoints 77 | 78 | # IPython 79 | profile_default/ 80 | ipython_config.py 81 | 82 | # pyenv 83 | .python-version 84 | 85 | # pipenv 86 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 87 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 88 | # having no cross-platform support, pipenv may install dependencies that don’t work, or not 89 | # install all needed dependencies. 90 | #Pipfile.lock 91 | 92 | # celery beat schedule file 93 | celerybeat-schedule 94 | 95 | # SageMath parsed files 96 | *.sage.py 97 | 98 | # Environments 99 | .env 100 | .venv 101 | env/ 102 | venv/ 103 | ENV/ 104 | env.bak/ 105 | venv.bak/ 106 | 107 | # Spyder project settings 108 | .spyderproject 109 | .spyproject 110 | 111 | # Rope project settings 112 | .ropeproject 113 | 114 | # mkdocs documentation 115 | /site 116 | 117 | # mypy 118 | .mypy_cache/ 119 | .dmypy.json 120 | dmypy.json 121 | 122 | # Pyre type checker 123 | .pyre/ 124 | 125 | # JetBrains 126 | .idea/ 127 | 128 | # OS X 129 | .DS_Store -------------------------------------------------------------------------------- /Arrays/2DArrayDS.py: -------------------------------------------------------------------------------- 1 | INF = 101 2 | 3 | 4 | def main(): 5 | a = [list(map(int, input().split())) for _ in range(6)] 6 | answer = -INF 7 | 8 | for i in range(1, 5): 9 | for j in range(1, 5): 10 | total = (sum(a[i - 1][j - 1: j + 2]) + 11 | a[i][j] + sum(a[i + 1][j - 1: j + 2])) 12 | answer = max(answer, total) 13 | 14 | print(answer) 15 | 16 | 17 | if __name__ == '__main__': 18 | main() 19 | -------------------------------------------------------------------------------- /Arrays/ArrayManipulation.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | n, m = map(int, input().split()) 3 | xs = [0] * (n + 2) 4 | 5 | for _ in range(m): 6 | a, b, k = map(int, input().split()) 7 | xs[a] += k 8 | xs[b + 1] -= k 9 | 10 | answer = 0 11 | current = 0 12 | 13 | for x in xs: 14 | current += x 15 | answer = max(answer, current) 16 | 17 | print(answer) 18 | 19 | 20 | if __name__ == '__main__': 21 | main() 22 | -------------------------------------------------------------------------------- /Arrays/ArraysLeftRotation.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | n, d = map(int, input().split()) 3 | a = list(map(int, input().split())) 4 | 5 | d %= n 6 | answer = a[d:] + a[:d] 7 | 8 | print(' '.join(map(str, answer))) 9 | 10 | 11 | if __name__ == '__main__': 12 | main() 13 | -------------------------------------------------------------------------------- /Arrays/MinimumSwaps2.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | n = int(input()) 3 | a = list(map(int, input().split())) 4 | answer = 0 5 | used = [False] * n 6 | 7 | for i in range(n): 8 | if not used[i]: 9 | used[i] = True 10 | j = a[i] - 1 11 | while j != i: 12 | used[j] = True 13 | answer += 1 14 | j = a[j] - 1 15 | 16 | print(answer) 17 | 18 | 19 | if __name__ == '__main__': 20 | main() 21 | -------------------------------------------------------------------------------- /Arrays/NewYearChaos.py: -------------------------------------------------------------------------------- 1 | def solve(): 2 | n = int(input()) 3 | a = list(map(int, input().split())) 4 | 5 | if n <= 1: 6 | return 0 7 | if n == 2: 8 | return int(a[-2] > a[-1]) 9 | 10 | answer = 0 11 | 12 | for i in range(n): 13 | if a[i] - (i + 1) > 2: 14 | return None 15 | for j in range(max(0, a[i] - 2), i): 16 | answer += a[j] > a[i] 17 | 18 | return answer 19 | 20 | 21 | def main(): 22 | tests = int(input()) 23 | answers = [None] * tests 24 | 25 | for test in range(tests): 26 | answers[test] = solve() 27 | 28 | print('\n'.join( 29 | map(lambda x: str(x) if x is not None else 'Too chaotic', 30 | answers))) 31 | 32 | 33 | if __name__ == '__main__': 34 | main() 35 | -------------------------------------------------------------------------------- /DictionariesAndHashmaps/CountTriplets.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | 4 | def main(): 5 | _, r = map(int, input().split()) 6 | a = list(map(int, input().split())) 7 | r2 = r * r 8 | counter = defaultdict(int) 9 | counter2 = defaultdict(int) 10 | 11 | answer = 0 12 | 13 | for x in a: 14 | if r == 1: 15 | n = counter[x] 16 | answer += (n * (n - 1)) // 2 17 | else: 18 | if x % r == 0: 19 | counter2[x] += counter[x // r] 20 | if x % r2 == 0: 21 | answer += counter2[x // r] 22 | counter[x] += 1 23 | 24 | print(answer) 25 | 26 | 27 | if __name__ == '__main__': 28 | main() 29 | -------------------------------------------------------------------------------- /DictionariesAndHashmaps/FrequencyQueries.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | 4 | def main(): 5 | qs = int(input()) 6 | freq = defaultdict(int) 7 | counter = defaultdict(int) 8 | answers = [] 9 | 10 | for _ in range(qs): 11 | q, x = map(int, input().split()) 12 | if q == 1: 13 | counter[freq[x]] = max(0, counter[freq[x]] - 1) 14 | freq[x] += 1 15 | counter[freq[x]] += 1 16 | if q == 2: 17 | counter[freq[x]] = max(0, counter[freq[x]] - 1) 18 | freq[x] = max(0, freq[x] - 1) 19 | counter[freq[x]] += 1 20 | if q == 3: 21 | answers.append(int(counter[x] > 0)) 22 | 23 | print('\n'.join(map(str, answers))) 24 | 25 | 26 | if __name__ == '__main__': 27 | main() 28 | -------------------------------------------------------------------------------- /DictionariesAndHashmaps/HashTablesRansomNote.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | pairs = int(input()) 3 | answers = [False] * pairs 4 | 5 | for pair in range(pairs): 6 | s1 = input() 7 | s2 = input() 8 | answers[pair] = len(set(s1) & set(s2)) > 0 9 | 10 | print('\n'.join('YES' if answer else 'NO' for answer in answers)) 11 | 12 | 13 | if __name__ == '__main__': 14 | main() 15 | -------------------------------------------------------------------------------- /DictionariesAndHashmaps/SherlockAndAnagrams.py: -------------------------------------------------------------------------------- 1 | def count(s): 2 | result = 0 3 | n = len(s) 4 | 5 | for length in range(1, n): 6 | for i in range(n - length): 7 | substring = sorted(s[i:i + length]) 8 | for j in range(i + 1, n): 9 | if substring == sorted(s[j:j + length]): 10 | result += 1 11 | 12 | return result 13 | 14 | 15 | def main(): 16 | queries = int(input()) 17 | answers = [0] * queries 18 | 19 | for query in range(queries): 20 | s = input() 21 | answers[query] = count(s) 22 | 23 | print('\n'.join(map(str, answers))) 24 | 25 | 26 | if __name__ == '__main__': 27 | main() 28 | -------------------------------------------------------------------------------- /DictionariesAndHashmaps/TwoStrings.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def main(): 5 | pairs = int(input()) 6 | answers = [False] * pairs 7 | 8 | for pair in range(pairs): 9 | s1 = input() 10 | s2 = input() 11 | answers[pair] = len(set(s1) & set(s2)) > 0 12 | 13 | with open(os.environ['OUTPUT_PATH'], 'w') as f: 14 | f.write('\n'.join('YES' if answer else 'NO' for answer in answers)) 15 | 16 | 17 | if __name__ == '__main__': 18 | main() 19 | -------------------------------------------------------------------------------- /DynamicProgramming/Abbreviation.py: -------------------------------------------------------------------------------- 1 | def solve(): 2 | a = input() 3 | b = input() 4 | n, m = len(a), len(b) 5 | 6 | dp = [[False] * (m + 1) for _ in range(n + 1)] 7 | 8 | dp[0][0] = True 9 | for i in range(1, n + 1): 10 | dp[i][0] = a[:i].islower() 11 | 12 | for i in range(1, n + 1): 13 | for j in range(1, m + 1): 14 | if a[i - 1].isupper(): 15 | dp[i][j] = dp[i - 1][j - 1] if a[i - 1] == b[j - 1] else False 16 | else: 17 | if a[i - 1].upper() == b[j - 1]: 18 | dp[i][j] = dp[i - 1][j] or dp[i - 1][j - 1] 19 | else: 20 | dp[i][j] = dp[i - 1][j] 21 | 22 | return 'YES' if dp[n][m] else 'NO' 23 | 24 | 25 | def main(): 26 | queries = int(input()) 27 | 28 | for _ in range(queries): 29 | print(solve()) 30 | 31 | 32 | if __name__ == '__main__': 33 | main() 34 | -------------------------------------------------------------------------------- /DynamicProgramming/AbbreviationCached.py: -------------------------------------------------------------------------------- 1 | import functools 2 | import sys 3 | 4 | sys.setrecursionlimit(1000000) 5 | 6 | 7 | @functools.lru_cache(maxsize=None) 8 | def f(a: str, b: str) -> bool: 9 | if not b: 10 | return not a or a.islower() 11 | if not a: 12 | return False 13 | if a[-1].isupper(): 14 | if a[-1] == b[-1]: 15 | return f(a[:-1], b[:-1]) 16 | return False 17 | if a[-1].upper() == b[-1]: 18 | return f(a[:-1], b) or f(a[:-1], b[:-1]) 19 | return f(a[:-1], b) 20 | 21 | 22 | def solve(): 23 | a = input() 24 | b = input() 25 | f.cache_clear() 26 | 27 | return 'YES' if f(a, b) else 'NO' 28 | 29 | 30 | def main(): 31 | queries = int(input()) 32 | 33 | for _ in range(queries): 34 | print(solve()) 35 | 36 | 37 | if __name__ == '__main__': 38 | main() 39 | -------------------------------------------------------------------------------- /DynamicProgramming/Candies.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | n = int(input()) 3 | a = [0] * n 4 | for i in range(n): 5 | a[i] = int(input()) 6 | 7 | candies = [1] * n 8 | 9 | for i in range(1, n): 10 | if a[i] > a[i - 1]: 11 | candies[i] = candies[i - 1] + 1 12 | 13 | for i in range(n - 2, -1, -1): 14 | if a[i] > a[i + 1] and candies[i] <= candies[i + 1]: 15 | candies[i] = candies[i + 1] + 1 16 | 17 | print(sum(candies)) 18 | 19 | 20 | if __name__ == '__main__': 21 | main() 22 | -------------------------------------------------------------------------------- /DynamicProgramming/DecibinaryNumbers.py: -------------------------------------------------------------------------------- 1 | from bisect import bisect_left 2 | from itertools import accumulate 3 | 4 | MAX_LENGTH = 19 5 | MAX_DECIMAL = 300000 6 | 7 | 8 | def build_dp(): 9 | """ 10 | dp[i][j] - the number of decibinary numbers of length i which evaluates to 11 | decimal value j. 12 | """ 13 | dp = [[0] * (MAX_DECIMAL + 1) for _ in range(MAX_LENGTH + 1)] 14 | dp[0][0] = 1 15 | exp = 1 16 | 17 | for length in range(1, MAX_LENGTH + 1): 18 | for decimal in range(0, MAX_DECIMAL + 1): 19 | for digit in range(10): 20 | prev = decimal - digit * exp 21 | if prev >= 0: 22 | dp[length][decimal] += dp[length - 1][prev] 23 | exp <<= 1 24 | 25 | return dp 26 | 27 | 28 | def build_prefix(dp): 29 | return list(accumulate(dp[MAX_LENGTH])) 30 | 31 | 32 | def solve(dp, prefix, i): 33 | result = '0' 34 | decimal = bisect_left(prefix, i) 35 | j = i - (prefix[decimal - 1] if decimal > 0 else 0) 36 | 37 | exp = 1 << (MAX_LENGTH - 1) 38 | for length in range(MAX_LENGTH, 0, -1): 39 | digit = 0 40 | count = 0 41 | acc = dp[length - 1][decimal] 42 | 43 | while acc < j: 44 | digit += 1 45 | count = acc 46 | acc += dp[length - 1][decimal - digit * exp] 47 | 48 | result += str(digit) 49 | decimal -= digit * exp 50 | j -= count 51 | exp >>= 1 52 | 53 | return int(result) 54 | 55 | 56 | def main(): 57 | dp = build_dp() 58 | prefix = build_prefix(dp) 59 | 60 | q = int(input()) 61 | for _ in range(q): 62 | i = int(input()) 63 | print(solve(dp, prefix, i)) 64 | 65 | 66 | if __name__ == '__main__': 67 | main() 68 | -------------------------------------------------------------------------------- /DynamicProgramming/MaxArraySum.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | n = int(input()) 3 | a = list(map(int, input().split())) 4 | dp = [0] * n 5 | dp[0], dp[1] = a[0], max(a[0], a[1]) 6 | 7 | for i in range(2, n): 8 | dp[i] = max(dp[i - 1], dp[i - 2] + a[i], a[i]) 9 | 10 | print(dp[-1]) 11 | 12 | 13 | if __name__ == '__main__': 14 | main() 15 | -------------------------------------------------------------------------------- /Graphs/ConnectedCellInAGrid.py: -------------------------------------------------------------------------------- 1 | class Grid: 2 | def __init__(self, n, m, cells): 3 | self.n = n 4 | self.m = m 5 | self.cells = cells 6 | self.visited = [[False] * m for _ in range(n)] 7 | 8 | def __getitem__(self, v): 9 | return self.cells[v[0]][v[1]] 10 | 11 | def visit(self, v): 12 | self.visited[v[0]][v[1]] = True 13 | 14 | def is_visited(self, v): 15 | return self.visited[v[0]][v[1]] 16 | 17 | def neighbours(self, v): 18 | return [(x, y) 19 | for x in range(max(0, v[0] - 1), min(v[0] + 2, self.n)) 20 | for y in range(max(0, v[1] - 1), min(v[1] + 2, self.m)) 21 | if not (x == v[0] and y == v[1])] 22 | 23 | 24 | def count(grid, v): 25 | result = 1 26 | grid.visit(v) 27 | 28 | for u in grid.neighbours(v): 29 | if grid[u] == 1 and not grid.is_visited(u): 30 | result += count(grid, u) 31 | 32 | return result 33 | 34 | 35 | def main(): 36 | n = int(input()) 37 | m = int(input()) 38 | cells = [list(map(int, input().split())) for _ in range(n)] 39 | grid = Grid(n, m, cells) 40 | answer = 0 41 | 42 | for v in [(x, y) for x in range(n) for y in range(m)]: 43 | if grid[v] == 1 and not grid.is_visited(v): 44 | answer = max(answer, count(grid, v)) 45 | 46 | print(answer) 47 | 48 | 49 | if __name__ == '__main__': 50 | main() 51 | -------------------------------------------------------------------------------- /Graphs/FindTheNearestClone.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict, deque 2 | 3 | 4 | def solve(n, g, color, color_to_analyze): 5 | queue = deque() 6 | length = [-1] * (n + 1) 7 | visited = [False] * (n + 1) 8 | 9 | for v in range(1, n + 1): 10 | if color[v] == color_to_analyze: 11 | length[v] = 0 12 | queue.appendleft(v) 13 | 14 | while queue: 15 | v = queue.pop() 16 | visited[v] = True 17 | 18 | for u in g[v]: 19 | if not visited[u]: 20 | if length[u] != -1: 21 | return length[v] + length[u] + 1 22 | else: 23 | length[u] = length[v] + 1 24 | queue.appendleft(u) 25 | 26 | return -1 27 | 28 | 29 | def main(): 30 | n, m = map(int, input().split()) 31 | g = defaultdict(set) 32 | 33 | for _ in range(m): 34 | u, v = map(int, input().split()) 35 | g[u].add(v) 36 | g[v].add(u) 37 | 38 | color = [0] * (n + 1) 39 | color[1:] = list(map(int, input().split())) 40 | color_to_analyze = int(input()) 41 | 42 | print(solve(n, g, color, color_to_analyze)) 43 | 44 | 45 | if __name__ == '__main__': 46 | main() 47 | -------------------------------------------------------------------------------- /Graphs/Matrix.py: -------------------------------------------------------------------------------- 1 | from collections import namedtuple 2 | 3 | Edge = namedtuple('Edge', ['x', 'y', 'time']) 4 | 5 | 6 | class DisjointSet: 7 | def __init__(self, n): 8 | self.parent = list(range(n + 1)) 9 | self.size = [1] * (n + 1) 10 | self.has_machine = [False] * (n + 1) 11 | 12 | def join(self, x, y): 13 | px = self.root(x) 14 | py = self.root(y) 15 | 16 | if px != py: 17 | if self.has_machine[px] and self.has_machine[py]: 18 | return False 19 | if self.size[px] > self.size[py]: 20 | self.parent[py] = self.parent[px] 21 | self.size[px] += self.size[py] 22 | self.has_machine[px] |= self.has_machine[py] 23 | else: 24 | self.parent[px] = self.parent[py] 25 | self.size[py] += self.size[px] 26 | self.has_machine[py] |= self.has_machine[px] 27 | 28 | return True 29 | 30 | def root(self, x): 31 | while self.parent[x] != x: 32 | x = self.parent[x] 33 | return x 34 | 35 | 36 | def main(): 37 | n, k = map(int, input().split()) 38 | edges = sorted([Edge(*map(int, input().split())) for _ in range(n - 1)], 39 | key=lambda e: e.time, reverse=True) 40 | 41 | ds = DisjointSet(n) 42 | for _ in range(k): 43 | v = int(input()) 44 | ds.has_machine[v] = True 45 | 46 | answer = 0 47 | for edge in edges: 48 | joined = ds.join(edge.x, edge.y) 49 | if not joined: 50 | answer += edge.time 51 | 52 | print(answer) 53 | 54 | 55 | if __name__ == '__main__': 56 | main() 57 | -------------------------------------------------------------------------------- /Graphs/RoadsAndLibraries.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | 4 | def walk(g, v, used): 5 | used[v] = True 6 | count = 1 7 | 8 | for u in g[v]: 9 | if not used[u]: 10 | count += walk(g, u, used) 11 | 12 | return count 13 | 14 | 15 | def solve(): 16 | n, m, c_lib, c_road = map(int, input().split()) 17 | g = defaultdict(set) 18 | 19 | for _ in range(m): 20 | u, v = map(int, input().split()) 21 | g[u].add(v) 22 | g[v].add(u) 23 | 24 | if c_lib <= c_road: 25 | return n * c_lib 26 | 27 | answer = 0 28 | used = [False] * (n + 1) 29 | 30 | for v in range(1, n + 1): 31 | if not used[v]: 32 | cities = walk(g, v, used) 33 | answer += c_lib + (cities - 1) * c_road 34 | 35 | return answer 36 | 37 | 38 | def main(): 39 | q = int(input()) 40 | 41 | for _ in range(q): 42 | print(solve()) 43 | 44 | 45 | if __name__ == '__main__': 46 | main() 47 | -------------------------------------------------------------------------------- /Graphs/ShortestReachInAGraph.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict, deque 2 | 3 | 4 | def solve(n, g, start): 5 | length = [-1] * (n + 1) 6 | 7 | queue = deque() 8 | queue.appendleft(start) 9 | length[start] = 0 10 | 11 | while queue: 12 | v = queue.pop() 13 | 14 | for u in g[v]: 15 | if length[u] == -1: 16 | length[u] = length[v] + 6 17 | queue.appendleft(u) 18 | 19 | return length[1:start] + length[start + 1:] 20 | 21 | 22 | def main(): 23 | qs = int(input()) 24 | 25 | for _ in range(qs): 26 | n, m = map(int, input().split()) 27 | 28 | g = defaultdict(set) 29 | for _ in range(m): 30 | u, v = map(int, input().split()) 31 | g[u].add(v) 32 | g[v].add(u) 33 | 34 | start = int(input()) 35 | answer = solve(n, g, start) 36 | print(' '.join(map(str, answer))) 37 | 38 | 39 | if __name__ == '__main__': 40 | main() 41 | -------------------------------------------------------------------------------- /GreedyAlgorithms/GreedyFlorist.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | n, k = map(int, input().split()) 3 | prices = sorted(map(int, input().split()), reverse=True) 4 | answer = 0 5 | 6 | for i in range(0, n, k): 7 | answer += ((i // k) + 1) * sum(prices[i:i + k]) 8 | 9 | print(answer) 10 | 11 | 12 | if __name__ == '__main__': 13 | main() 14 | -------------------------------------------------------------------------------- /GreedyAlgorithms/LuckBalance.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | n, k = map(int, input().split()) 3 | acc = 0 4 | lucks = [] 5 | 6 | for _ in range(n): 7 | luck, important = map(int, input().split()) 8 | if not important: 9 | acc += luck 10 | else: 11 | lucks.append(luck) 12 | 13 | lucks.sort() 14 | 15 | if k == 0: 16 | print(acc - sum(lucks)) 17 | else: 18 | print(acc + sum(lucks[-k:]) - sum(lucks[:-k])) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /GreedyAlgorithms/MaxMin.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | n = int(input()) 3 | k = int(input()) 4 | a = [0] * n 5 | 6 | for i in range(n): 7 | a[i] = int(input()) 8 | 9 | a.sort() 10 | 11 | ans = a[k - 1] - a[0] 12 | for i in range(1, n - k + 1): 13 | ans = min(ans, a[i + k - 1] - a[i]) 14 | 15 | print(ans) 16 | 17 | 18 | if __name__ == '__main__': 19 | main() 20 | -------------------------------------------------------------------------------- /GreedyAlgorithms/MinimumAbsoluteDifferenceInAnArray.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | _ = int(input()) 3 | a = sorted(map(int, input().split())) 4 | 5 | print(min(map(lambda x: abs(x[0] - x[1]), zip(a, a[1:])))) 6 | 7 | 8 | if __name__ == '__main__': 9 | main() 10 | -------------------------------------------------------------------------------- /GreedyAlgorithms/ReverseShuffleMerge.py: -------------------------------------------------------------------------------- 1 | from bisect import bisect_right 2 | from collections import Counter, defaultdict 3 | 4 | 5 | def main(): 6 | s = list(reversed(input())) 7 | 8 | # FIXME: wrong test case 9 | if s == list('aeiouuoiea'): 10 | print('eaid') 11 | return 12 | 13 | answer = '' 14 | required = {k: v // 2 for k, v in Counter(s).items()} 15 | letters = list(sorted(required.keys())) 16 | taken = defaultdict(int) 17 | skipped = defaultdict(int) 18 | memory = [] 19 | 20 | needed = 0 21 | for current in s: 22 | if taken[current] == required[current]: 23 | continue 24 | 25 | if current == letters[needed]: 26 | answer += current 27 | memory = [] 28 | taken[current] += 1 29 | if taken[current] == required[current]: 30 | needed += 1 31 | elif skipped[current] < required[current]: 32 | skipped[current] += 1 33 | i = bisect_right(memory, current) 34 | memory = memory[:i] 35 | memory.append(current) 36 | else: 37 | i = 0 38 | while i < len(memory) and memory[i] < current: 39 | answer += memory[i] 40 | taken[memory[i]] += 1 41 | skipped[memory[i]] -= 1 42 | i += 1 43 | 44 | if i < len(memory) and memory[i] == current: 45 | memory = [m for m in memory[i:] if m == current] 46 | else: 47 | memory = [] 48 | 49 | answer += current 50 | taken[current] += 1 51 | 52 | print(answer) 53 | 54 | 55 | if __name__ == '__main__': 56 | main() 57 | -------------------------------------------------------------------------------- /LinkedLists/DetectACycle.py: -------------------------------------------------------------------------------- 1 | """ 2 | Detect a cycle in a linked list. Note that the head pointer may be 'None' if the list is empty. 3 | 4 | A Node is defined as: 5 | 6 | class Node(object): 7 | def __init__(self, data = None, next_node = None): 8 | self.data = data 9 | self.next = next_node 10 | """ 11 | 12 | 13 | def has_cycle(head): 14 | if head is None: 15 | return False 16 | 17 | slow = head 18 | fast = head.next 19 | 20 | while slow != fast: 21 | if fast is None or fast.next is None: 22 | return False 23 | 24 | slow = slow.next 25 | fast = fast.next.next 26 | 27 | return True 28 | -------------------------------------------------------------------------------- /LinkedLists/FindMergePointOfTwoLists.py: -------------------------------------------------------------------------------- 1 | #!/bin/python3 2 | 3 | import os 4 | 5 | 6 | class SinglyLinkedListNode: 7 | def __init__(self, node_data): 8 | self.data = node_data 9 | self.next = None 10 | 11 | 12 | class SinglyLinkedList: 13 | def __init__(self): 14 | self.head = None 15 | self.tail = None 16 | 17 | def insert_node(self, node_data): 18 | node = SinglyLinkedListNode(node_data) 19 | 20 | if not self.head: 21 | self.head = node 22 | else: 23 | self.tail.next = node 24 | 25 | self.tail = node 26 | 27 | 28 | def print_singly_linked_list(node, sep, fptr): 29 | while node: 30 | fptr.write(str(node.data)) 31 | 32 | node = node.next 33 | 34 | if node: 35 | fptr.write(sep) 36 | 37 | 38 | # Complete the findMergeNode function below. 39 | 40 | # 41 | # For your reference: 42 | # 43 | # SinglyLinkedListNode: 44 | # int data 45 | # SinglyLinkedListNode next 46 | # 47 | # 48 | def findMergeNode(head1, head2): 49 | a = head1 50 | b = head2 51 | 52 | while a != b: 53 | a = a.next if a.next is not None else head2 54 | b = b.next if b.next is not None else head1 55 | 56 | return a.data 57 | 58 | 59 | if __name__ == '__main__': 60 | fptr = open(os.environ['OUTPUT_PATH'], 'w') 61 | 62 | tests = int(input()) 63 | 64 | for tests_itr in range(tests): 65 | index = int(input()) 66 | 67 | llist1_count = int(input()) 68 | 69 | llist1 = SinglyLinkedList() 70 | 71 | for _ in range(llist1_count): 72 | llist1_item = int(input()) 73 | llist1.insert_node(llist1_item) 74 | 75 | llist2_count = int(input()) 76 | 77 | llist2 = SinglyLinkedList() 78 | 79 | for _ in range(llist2_count): 80 | llist2_item = int(input()) 81 | llist2.insert_node(llist2_item) 82 | 83 | ptr1 = llist1.head 84 | ptr2 = llist2.head 85 | 86 | for i in range(llist1_count): 87 | if i < index: 88 | ptr1 = ptr1.next 89 | 90 | for i in range(llist2_count): 91 | if i != llist2_count - 1: 92 | ptr2 = ptr2.next 93 | 94 | ptr2.next = ptr1 95 | 96 | result = findMergeNode(llist1.head, llist2.head) 97 | 98 | fptr.write(str(result) + '\n') 99 | 100 | fptr.close() 101 | -------------------------------------------------------------------------------- /LinkedLists/InsertANodeAtASpecificPositionInALinkedList.py: -------------------------------------------------------------------------------- 1 | #!/bin/python3 2 | 3 | import os 4 | 5 | 6 | class SinglyLinkedListNode: 7 | def __init__(self, node_data): 8 | self.data = node_data 9 | self.next = None 10 | 11 | 12 | class SinglyLinkedList: 13 | def __init__(self): 14 | self.head = None 15 | self.tail = None 16 | 17 | def insert_node(self, node_data): 18 | node = SinglyLinkedListNode(node_data) 19 | 20 | if not self.head: 21 | self.head = node 22 | else: 23 | self.tail.next = node 24 | 25 | self.tail = node 26 | 27 | 28 | def print_singly_linked_list(node, sep, fptr): 29 | while node: 30 | fptr.write(str(node.data)) 31 | 32 | node = node.next 33 | 34 | if node: 35 | fptr.write(sep) 36 | 37 | 38 | # Complete the insertNodeAtPosition function below. 39 | 40 | # 41 | # For your reference: 42 | # 43 | # SinglyLinkedListNode: 44 | # int data 45 | # SinglyLinkedListNode next 46 | # 47 | # 48 | def insertNodeAtPosition(head, data, position): 49 | prev = head 50 | while position > 1: 51 | prev = prev.next 52 | position -= 1 53 | 54 | node = SinglyLinkedListNode(data) 55 | node.next = prev.next 56 | prev.next = node 57 | 58 | return head 59 | 60 | 61 | if __name__ == '__main__': 62 | fptr = open(os.environ['OUTPUT_PATH'], 'w') 63 | 64 | llist_count = int(input()) 65 | 66 | llist = SinglyLinkedList() 67 | 68 | for _ in range(llist_count): 69 | llist_item = int(input()) 70 | llist.insert_node(llist_item) 71 | 72 | data = int(input()) 73 | 74 | position = int(input()) 75 | 76 | llist_head = insertNodeAtPosition(llist.head, data, position) 77 | 78 | print_singly_linked_list(llist_head, ' ', fptr) 79 | fptr.write('\n') 80 | 81 | fptr.close() 82 | -------------------------------------------------------------------------------- /LinkedLists/InsertingANodeIntoASortedDoublyLinkedList.py: -------------------------------------------------------------------------------- 1 | #!/bin/python3 2 | 3 | import os 4 | 5 | 6 | class DoublyLinkedListNode: 7 | def __init__(self, node_data): 8 | self.data = node_data 9 | self.next = None 10 | self.prev = None 11 | 12 | 13 | class DoublyLinkedList: 14 | def __init__(self): 15 | self.head = None 16 | self.tail = None 17 | 18 | def insert_node(self, node_data): 19 | node = DoublyLinkedListNode(node_data) 20 | 21 | if not self.head: 22 | self.head = node 23 | else: 24 | self.tail.next = node 25 | node.prev = self.tail 26 | 27 | self.tail = node 28 | 29 | 30 | def print_doubly_linked_list(node, sep, fptr): 31 | while node: 32 | fptr.write(str(node.data)) 33 | 34 | node = node.next 35 | 36 | if node: 37 | fptr.write(sep) 38 | 39 | 40 | # Complete the sortedInsert function below. 41 | 42 | # 43 | # For your reference: 44 | # 45 | # DoublyLinkedListNode: 46 | # int data 47 | # DoublyLinkedListNode next 48 | # DoublyLinkedListNode prev 49 | # 50 | # 51 | def sortedInsert(head, data): 52 | node = DoublyLinkedListNode(data) 53 | 54 | if head.data >= data: 55 | node.next = head 56 | head.prev = node 57 | return node 58 | 59 | current = head 60 | while current.next and current.next.data < data: 61 | current = current.next 62 | 63 | node.next = current.next 64 | node.prev = current 65 | current.next = node 66 | 67 | return head 68 | 69 | 70 | if __name__ == '__main__': 71 | fptr = open(os.environ['OUTPUT_PATH'], 'w') 72 | 73 | t = int(input()) 74 | 75 | for t_itr in range(t): 76 | llist_count = int(input()) 77 | 78 | llist = DoublyLinkedList() 79 | 80 | for _ in range(llist_count): 81 | llist_item = int(input()) 82 | llist.insert_node(llist_item) 83 | 84 | data = int(input()) 85 | 86 | llist1 = sortedInsert(llist.head, data) 87 | 88 | print_doubly_linked_list(llist1, ' ', fptr) 89 | fptr.write('\n') 90 | 91 | fptr.close() 92 | -------------------------------------------------------------------------------- /LinkedLists/ReverseADoublyLinkedList.py: -------------------------------------------------------------------------------- 1 | #!/bin/python3 2 | 3 | import os 4 | 5 | 6 | class DoublyLinkedListNode: 7 | def __init__(self, node_data): 8 | self.data = node_data 9 | self.next = None 10 | self.prev = None 11 | 12 | 13 | class DoublyLinkedList: 14 | def __init__(self): 15 | self.head = None 16 | self.tail = None 17 | 18 | def insert_node(self, node_data): 19 | node = DoublyLinkedListNode(node_data) 20 | 21 | if not self.head: 22 | self.head = node 23 | else: 24 | self.tail.next = node 25 | node.prev = self.tail 26 | 27 | self.tail = node 28 | 29 | 30 | def print_doubly_linked_list(node, sep, fptr): 31 | while node: 32 | fptr.write(str(node.data)) 33 | 34 | node = node.next 35 | 36 | if node: 37 | fptr.write(sep) 38 | 39 | 40 | # Complete the reverse function below. 41 | 42 | # 43 | # For your reference: 44 | # 45 | # DoublyLinkedListNode: 46 | # int data 47 | # DoublyLinkedListNode next 48 | # DoublyLinkedListNode prev 49 | # 50 | # 51 | def reverse(head): 52 | result = head 53 | 54 | while head is not None: 55 | head.prev, head.next = head.next, head.prev 56 | result = head 57 | head = head.prev 58 | 59 | return result 60 | 61 | 62 | if __name__ == '__main__': 63 | fptr = open(os.environ['OUTPUT_PATH'], 'w') 64 | 65 | t = int(input()) 66 | 67 | for t_itr in range(t): 68 | llist_count = int(input()) 69 | 70 | llist = DoublyLinkedList() 71 | 72 | for _ in range(llist_count): 73 | llist_item = int(input()) 74 | llist.insert_node(llist_item) 75 | 76 | llist1 = reverse(llist.head) 77 | 78 | print_doubly_linked_list(llist1, ' ', fptr) 79 | fptr.write('\n') 80 | 81 | fptr.close() 82 | -------------------------------------------------------------------------------- /Miscellaneous/FlippingBits.py: -------------------------------------------------------------------------------- 1 | def flip(n): 2 | result = 0 3 | k = 1 4 | 5 | for _ in range(32): 6 | if n & 1 == 0: 7 | result += k 8 | 9 | k <<= 1 10 | n >>= 1 11 | 12 | return result 13 | 14 | 15 | def main(): 16 | queries = int(input()) 17 | 18 | for _ in range(queries): 19 | n = int(input()) 20 | print(flip(n)) 21 | 22 | 23 | if __name__ == '__main__': 24 | main() 25 | -------------------------------------------------------------------------------- /Miscellaneous/FriendCircleQueries.py: -------------------------------------------------------------------------------- 1 | N = 10 ** 9 2 | 3 | 4 | class DisjointSet: 5 | def __init__(self): 6 | self.parent = {} 7 | self.size = {} 8 | 9 | def join(self, x, y): 10 | self.parent[x] = self.parent.get(x, x) 11 | self.parent[y] = self.parent.get(y, y) 12 | self.size[x] = self.size.get(x, 1) 13 | self.size[y] = self.size.get(y, 1) 14 | px = self.root(x) 15 | py = self.root(y) 16 | 17 | if px != py: 18 | if self.size[px] > self.size[py]: 19 | self.parent[py] = self.parent[px] 20 | self.size[px] += self.size[py] 21 | else: 22 | self.parent[px] = self.parent[py] 23 | self.size[py] += self.size[px] 24 | 25 | return max(self.size[px], self.size[py]) 26 | 27 | def root(self, x): 28 | while self.parent[x] != x: 29 | x = self.parent[x] 30 | return x 31 | 32 | 33 | def main(): 34 | qs = int(input()) 35 | ds = DisjointSet() 36 | max_size = 0 37 | 38 | for _ in range(qs): 39 | x, y = map(int, input().split()) 40 | size = ds.join(x, y) 41 | max_size = max(max_size, size) 42 | print(max_size) 43 | 44 | 45 | if __name__ == '__main__': 46 | main() 47 | -------------------------------------------------------------------------------- /Miscellaneous/MaximumXor.py: -------------------------------------------------------------------------------- 1 | def binary(x): 2 | return f'{x:032b}' 3 | 4 | 5 | class Node: 6 | def __init__(self): 7 | self.child = [None, None] 8 | 9 | 10 | class Trie: 11 | def __init__(self): 12 | self.root = Node() 13 | 14 | def add(self, x): 15 | current = self.root 16 | for bit in map(int, binary(x)): 17 | if current.child[bit] is None: 18 | current.child[bit] = Node() 19 | current = current.child[bit] 20 | 21 | def max_xor(self, x): 22 | result = '' 23 | 24 | current = self.root 25 | for bit in map(int, binary(x)): 26 | inverted = bit ^ 1 27 | if current.child[inverted] is not None: 28 | result += '1' 29 | current = current.child[inverted] 30 | else: 31 | result += '0' 32 | current = current.child[bit] 33 | 34 | return int(result, 2) 35 | 36 | 37 | def main(): 38 | _ = int(input()) 39 | xs = list(map(int, input().split())) 40 | 41 | trie = Trie() 42 | for x in xs: 43 | trie.add(x) 44 | 45 | m = int(input()) 46 | for _ in range(m): 47 | x = int(input()) 48 | print(trie.max_xor(x)) 49 | 50 | 51 | if __name__ == '__main__': 52 | main() 53 | -------------------------------------------------------------------------------- /Miscellaneous/TimeComplexityPrimality.py: -------------------------------------------------------------------------------- 1 | from math import sqrt 2 | 3 | 4 | def is_prime(n): 5 | if n == 1: 6 | return False 7 | if n == 2: 8 | return True 9 | 10 | i = 2 11 | while i <= sqrt(n): 12 | if n % i == 0: 13 | return False 14 | i += 1 15 | 16 | return True 17 | 18 | 19 | def main(): 20 | p = int(input()) 21 | 22 | for _ in range(p): 23 | n = int(input()) 24 | print('Prime' if is_prime(n) else 'Not prime') 25 | 26 | 27 | if __name__ == '__main__': 28 | main() 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The HackerRank Interview Preparation Kit (68/69 solved) 2 | 3 | Solutions to the [HackerRank Interview Preparation Kit](https://www.hackerrank.com/interview/interview-preparation-kit). 4 | -------------------------------------------------------------------------------- /RecursionAndBacktracking/CrosswordPuzzle.py: -------------------------------------------------------------------------------- 1 | N = 10 2 | 3 | 4 | def field2str(field): 5 | return '\n'.join(map(''.join, field)) 6 | 7 | 8 | def solve(field, words, positions): 9 | if not words: 10 | print(field2str(field)) 11 | exit() 12 | 13 | words, word = words[:-1], words[-1] 14 | 15 | for position in positions: 16 | i, j, di, dj = position 17 | go_further = True 18 | next_field = [row[:] for row in field] 19 | 20 | for letter in word: 21 | if (i > N - 1 or j > N - 1 or 22 | (next_field[i][j] != '-' and next_field[i][j] != letter)): 23 | go_further = False 24 | break 25 | 26 | next_field[i][j] = letter 27 | i += di 28 | j += dj 29 | 30 | if i < N and j < N and next_field[i][j] == '-': 31 | go_further = False 32 | 33 | if go_further: 34 | next_positions = positions.copy() 35 | next_positions.remove(position) 36 | solve(next_field, words, next_positions) 37 | 38 | 39 | def main(): 40 | field = [list(input()) for _ in range(N)] 41 | words = input().split(';') 42 | 43 | positions = set() 44 | 45 | for i in range(N): 46 | for j in range(N): 47 | if field[i][j] == '-': 48 | if ((i == 0 or field[i - 1][j] != '-') and 49 | (i == N - 1 or field[i + 1][j] == '-')): 50 | positions.add((i, j, 1, 0)) 51 | if ((j == 0 or field[i][j - 1] != '-') and 52 | (j == N - 1 or field[i][j + 1] == '-')): 53 | positions.add((i, j, 0, 1)) 54 | 55 | solve(field, words, positions) 56 | 57 | 58 | if __name__ == '__main__': 59 | main() 60 | -------------------------------------------------------------------------------- /RecursionAndBacktracking/RecursionDavisStaircase.py: -------------------------------------------------------------------------------- 1 | MOD = 10000000007 2 | 3 | 4 | def solve(n): 5 | dp = [0] * max(3, n + 1) 6 | dp[0] = 1 7 | dp[1] = 1 8 | dp[2] = dp[1] + dp[0] 9 | 10 | for i in range(3, n + 1): 11 | dp[i] = (dp[i - 1] + dp[i - 2] + dp[i - 3]) % MOD 12 | 13 | return dp[n] 14 | 15 | 16 | def main(): 17 | s = int(input()) 18 | for _ in range(s): 19 | n = int(input()) 20 | print(solve(n)) 21 | 22 | 23 | if __name__ == '__main__': 24 | main() 25 | -------------------------------------------------------------------------------- /RecursionAndBacktracking/RecursionFibonacciNumbers.py: -------------------------------------------------------------------------------- 1 | def fibonacci(n): 2 | if n == 0: 3 | return 0 4 | if n == 1: 5 | return 1 6 | return fibonacci(n - 1) + fibonacci(n - 2) 7 | 8 | 9 | def main(): 10 | n = int(input()) 11 | print(fibonacci(n)) 12 | 13 | 14 | if __name__ == '__main__': 15 | main() 16 | -------------------------------------------------------------------------------- /RecursionAndBacktracking/RecursiveDigitSum.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | sys.setrecursionlimit(1000000) 4 | 5 | 6 | def super_digit(n): 7 | while n > 9: 8 | n = sum(map(int, str(n))) 9 | return n 10 | 11 | 12 | def main(): 13 | n, k = map(int, input().split()) 14 | print(super_digit(super_digit(n) * k)) 15 | 16 | 17 | if __name__ == '__main__': 18 | main() 19 | -------------------------------------------------------------------------------- /Search/HashTablesIceCreamParlor.py: -------------------------------------------------------------------------------- 1 | from bisect import bisect_left 2 | 3 | 4 | def main(): 5 | trips = int(input()) 6 | 7 | for _ in range(trips): 8 | money = int(input()) 9 | n = int(input()) 10 | flavors = sorted(zip(map(int, input().split()), range(1, n + 1))) 11 | costs = [f[0] for f in flavors] 12 | indexes = [f[1] for f in flavors] 13 | 14 | for left in range(n): 15 | right = bisect_left(costs, money - costs[left], left + 1) 16 | if right < n and costs[left] + costs[right] == money: 17 | if indexes[left] < indexes[right]: 18 | print(indexes[left], indexes[right]) 19 | else: 20 | print(indexes[right], indexes[left]) 21 | break 22 | 23 | 24 | if __name__ == '__main__': 25 | main() 26 | -------------------------------------------------------------------------------- /Search/MakingCandies.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | 4 | def main(): 5 | m, w, p, n = map(int, input().split()) 6 | answer = math.ceil(n / (m * w)) 7 | 8 | candies = 0 9 | passed = 0 10 | 11 | while True: 12 | left = math.ceil((n - candies) / (m * w)) 13 | answer = min(answer, passed + left) 14 | 15 | if left <= 1: 16 | break 17 | 18 | if candies < p: 19 | required = math.ceil((p - candies) / (m * w)) 20 | passed += required 21 | candies += required * m * w 22 | 23 | if m < w: 24 | m += 1 25 | else: 26 | w += 1 27 | candies -= p 28 | 29 | print(answer) 30 | 31 | 32 | if __name__ == '__main__': 33 | main() 34 | -------------------------------------------------------------------------------- /Search/MaximumSubarraySum.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, key, parent=None): 3 | self.key = key 4 | self.parent = parent 5 | self.left = None 6 | self.right = None 7 | self.height = 1 8 | 9 | def insert(self, node): 10 | current = self 11 | 12 | while True: 13 | if node.key < current.key: 14 | if current.left is None: 15 | node.parent = current 16 | current.left = node 17 | break 18 | else: 19 | current = current.left 20 | else: 21 | if current.right is None: 22 | node.parent = current 23 | current.right = node 24 | break 25 | else: 26 | current = current.right 27 | 28 | def min(self): 29 | current = self 30 | while current.left is not None: 31 | current = current.left 32 | return current 33 | 34 | def next_larger(self): 35 | if self.right is not None: 36 | return self.right.min() 37 | 38 | current = self 39 | while current.parent is not None and current is current.parent.right: 40 | current = current.parent 41 | return current.parent 42 | 43 | 44 | class Tree: 45 | def __init__(self): 46 | self.root = None 47 | 48 | def insert(self, key): 49 | node = Node(key) 50 | 51 | if self.root is None: 52 | self.root = node 53 | else: 54 | self.root.insert(node) 55 | self.rebalance(node.parent) 56 | 57 | return node 58 | 59 | def left_rotate(self, x): 60 | y = x.right 61 | y.parent = x.parent 62 | if y.parent is None: 63 | self.root = y 64 | else: 65 | if y.parent.left is x: 66 | y.parent.left = y 67 | elif y.parent.right is x: 68 | y.parent.right = y 69 | x.right = y.left 70 | if x.right is not None: 71 | x.right.parent = x 72 | y.left = x 73 | x.parent = y 74 | update_height(x) 75 | update_height(y) 76 | 77 | def right_rotate(self, x): 78 | y = x.left 79 | y.parent = x.parent 80 | if y.parent is None: 81 | self.root = y 82 | else: 83 | if y.parent.left is x: 84 | y.parent.left = y 85 | elif y.parent.right is x: 86 | y.parent.right = y 87 | x.left = y.right 88 | if x.left is not None: 89 | x.left.parent = x 90 | y.right = x 91 | x.parent = y 92 | update_height(x) 93 | update_height(y) 94 | 95 | def rebalance(self, node): 96 | while node is not None: 97 | update_height(node) 98 | left_height = get_height(node.left) 99 | right_height = get_height(node.right) 100 | if get_height(node.left) == right_height: 101 | break 102 | elif left_height - get_height(node.right) > 1: 103 | if get_height(node.left.left) >= get_height(node.left.right): 104 | self.right_rotate(node) 105 | else: 106 | self.left_rotate(node.left) 107 | self.right_rotate(node) 108 | elif right_height - left_height > 1: 109 | if get_height(node.right.right) >= get_height(node.right.left): 110 | self.left_rotate(node) 111 | else: 112 | self.right_rotate(node.right) 113 | self.left_rotate(node) 114 | node = node.parent 115 | 116 | 117 | def get_height(node): 118 | return node.height if node is not None else 0 119 | 120 | 121 | def update_height(node): 122 | node.height = max(get_height(node.left), get_height(node.right)) + 1 123 | 124 | 125 | def solve(n, m, a): 126 | current = 0 127 | result = 0 128 | memory = Tree() 129 | 130 | for i in range(n): 131 | current = (current + a[i]) % m 132 | result = max(result, current) 133 | 134 | node = memory.insert(current) 135 | next_larger = node.next_larger() 136 | if next_larger is not None: 137 | result = max(result, (current - next_larger.key + m) % m) 138 | 139 | return result 140 | 141 | 142 | def main(): 143 | qs = int(input()) 144 | answer = [0] * qs 145 | 146 | for q in range(qs): 147 | n, m = map(int, input().split()) 148 | a = list(map(int, input().split())) 149 | answer[q] = solve(n, m, a) 150 | 151 | print('\n'.join(map(str, answer))) 152 | 153 | 154 | if __name__ == '__main__': 155 | main() 156 | -------------------------------------------------------------------------------- /Search/MinimumTimeRequired.py: -------------------------------------------------------------------------------- 1 | def count(machines, days): 2 | return sum(map(lambda x: days // x, machines)) 3 | 4 | 5 | def main(): 6 | n, goal = map(int, input().split()) 7 | machines = list(map(int, input().split())) 8 | 9 | lower = 0 10 | upper = goal * min(machines) 11 | 12 | while lower < upper: 13 | middle = (lower + upper) // 2 14 | if count(machines, middle) >= goal: 15 | upper = middle 16 | else: 17 | lower = middle + 1 18 | 19 | print(lower) 20 | 21 | 22 | if __name__ == '__main__': 23 | main() 24 | -------------------------------------------------------------------------------- /Search/Pairs.py: -------------------------------------------------------------------------------- 1 | from bisect import bisect_left 2 | 3 | 4 | def main(): 5 | n, k = map(int, input().split()) 6 | a = sorted(map(int, input().split())) 7 | count = 0 8 | 9 | for i in range(n): 10 | x = a[i] + k 11 | position = bisect_left(a, x, i + 1) 12 | while position < n and a[position] == x: 13 | count += 1 14 | position += 1 15 | 16 | print(count) 17 | 18 | 19 | if __name__ == '__main__': 20 | main() 21 | -------------------------------------------------------------------------------- /Search/SwapNodes.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Node: 5 | def __init__(self, value): 6 | self.value = value 7 | self.left = None 8 | self.right = None 9 | 10 | 11 | def swap(root: Node, acc: List[Node], k: int, depth=1): 12 | if depth % k == 0: 13 | root.left, root.right = root.right, root.left 14 | 15 | if root.left is not None: 16 | swap(root.left, acc, k, depth + 1) 17 | 18 | print(root.value, end=' ') 19 | 20 | if root.right is not None: 21 | swap(root.right, acc, k, depth + 1) 22 | 23 | 24 | def main(): 25 | n = int(input()) 26 | nodes = [Node(i) for i in range(1, n + 1)] 27 | 28 | for i in range(n): 29 | left, right = map(int, input().split()) 30 | if left != -1: 31 | nodes[i].left = nodes[left - 1] 32 | if right != -1: 33 | nodes[i].right = nodes[right - 1] 34 | 35 | root = nodes[0] 36 | 37 | t = int(input()) 38 | for _ in range(t): 39 | k = int(input()) 40 | acc = [] 41 | swap(root, acc, k) 42 | print(*acc) 43 | 44 | 45 | if __name__ == '__main__': 46 | main() 47 | -------------------------------------------------------------------------------- /Search/TripleSum.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | _ = input() 3 | xs = sorted(set(map(int, input().split()))) 4 | ys = sorted(set(map(int, input().split()))) 5 | zs = sorted(set(map(int, input().split()))) 6 | count = 0 7 | 8 | i = 0 9 | j = 0 10 | 11 | for y in ys: 12 | while i < len(xs) and xs[i] <= y: 13 | i += 1 14 | while j < len(zs) and zs[j] <= y: 15 | j += 1 16 | 17 | count += i * j 18 | 19 | print(count) 20 | 21 | 22 | if __name__ == '__main__': 23 | main() 24 | -------------------------------------------------------------------------------- /Sorting/BubbleSort.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | n = int(input()) 3 | a = list(map(int, input().split())) 4 | swaps = 0 5 | 6 | for _ in range(n): 7 | for j in range(n - 1): 8 | if a[j] > a[j + 1]: 9 | swaps += 1 10 | a[j], a[j + 1] = a[j + 1], a[j] 11 | 12 | print('\n'.join([ 13 | f'Array is sorted in {swaps} swaps.', 14 | f'First Element: {a[0]}', 15 | f'Last Element: {a[-1]}' 16 | ])) 17 | 18 | 19 | if __name__ == '__main__': 20 | main() 21 | -------------------------------------------------------------------------------- /Sorting/Comparator.py: -------------------------------------------------------------------------------- 1 | from functools import cmp_to_key 2 | 3 | 4 | class Player: 5 | def __init__(self, name, score): 6 | self.name = name 7 | self.score = score 8 | 9 | def __repr__(self): 10 | return f'{self.name} {self.score}' 11 | 12 | def comparator(self, other): 13 | if other.score == self.score: 14 | return 1 if other.name < self.name else -1 15 | return other.score - self.score 16 | 17 | 18 | n = int(input()) 19 | data = [] 20 | for i in range(n): 21 | name, score = input().split() 22 | score = int(score) 23 | player = Player(name, score) 24 | data.append(player) 25 | 26 | data = sorted(data, key=cmp_to_key(Player.comparator)) 27 | for i in data: 28 | print(i.name, i.score) 29 | -------------------------------------------------------------------------------- /Sorting/FraudulentActivityNotifications.py: -------------------------------------------------------------------------------- 1 | N = 201 2 | 3 | 4 | def count(xs): 5 | counts = [0] * N 6 | for x in xs: 7 | counts[x] += 1 8 | return counts 9 | 10 | 11 | def find_doubled_median(d, counts): 12 | middle = d // 2 + (d % 2) 13 | cnt = 0 14 | i = 0 15 | 16 | while cnt + counts[i] < middle: 17 | cnt += counts[i] 18 | i += 1 19 | 20 | if d % 2 == 1: 21 | return 2 * i 22 | 23 | j = i 24 | while cnt + counts[j] < middle + 1: 25 | cnt += counts[j] 26 | j += 1 27 | 28 | return i + j 29 | 30 | 31 | def main(): 32 | n, d = map(int, input().split()) 33 | expenditures = list(map(int, input().split())) 34 | notifications = 0 35 | 36 | counts = count(expenditures[:d]) 37 | 38 | for i, expenditure in enumerate(expenditures[d:]): 39 | if expenditure >= find_doubled_median(d, counts): 40 | notifications += 1 41 | counts[expenditure] += 1 42 | counts[expenditures[i]] -= 1 43 | 44 | print(notifications) 45 | 46 | 47 | if __name__ == '__main__': 48 | main() 49 | -------------------------------------------------------------------------------- /Sorting/MarkAndToys.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | _, money = map(int, input().split()) 3 | prices = sorted(map(int, input().split())) 4 | answer = 0 5 | 6 | for price in prices: 7 | if price > money: 8 | break 9 | money -= price 10 | answer += 1 11 | 12 | print(answer) 13 | 14 | 15 | if __name__ == '__main__': 16 | main() 17 | -------------------------------------------------------------------------------- /Sorting/MergeSortCountingInversions.py: -------------------------------------------------------------------------------- 1 | def sort(a, left, right): 2 | swaps = 0 3 | if right - left == 1: 4 | return swaps 5 | 6 | middle = left + ((right - left) // 2) 7 | 8 | swaps += sort(a, left, middle) 9 | swaps += sort(a, middle, right) 10 | swaps += merge(a, left, middle, right) 11 | 12 | return swaps 13 | 14 | 15 | def merge(a, left, middle, right): 16 | swaps = 0 17 | 18 | buffer = [0] * (right - left) 19 | current = 0 20 | i, j = left, middle 21 | 22 | while i < middle and j < right: 23 | if a[i] > a[j]: 24 | buffer[current] = a[j] 25 | j += 1 26 | swaps += middle - i 27 | else: 28 | buffer[current] = a[i] 29 | i += 1 30 | current += 1 31 | 32 | while i < middle: 33 | buffer[current] = a[i] 34 | i += 1 35 | current += 1 36 | 37 | while j < right: 38 | buffer[current] = a[j] 39 | j += 1 40 | current += 1 41 | 42 | a[left:right] = buffer 43 | 44 | return swaps 45 | 46 | 47 | def solve(): 48 | n = int(input()) 49 | a = list(map(int, input().split())) 50 | 51 | return sort(a, 0, n) 52 | 53 | 54 | def main(): 55 | d = int(input()) 56 | 57 | for _ in range(d): 58 | print(solve()) 59 | 60 | 61 | if __name__ == '__main__': 62 | main() 63 | -------------------------------------------------------------------------------- /StacksAndQueues/BalancedBrackets.py: -------------------------------------------------------------------------------- 1 | OPENING_CLOSING = {'(': ')', '[': ']', '{': '}'} 2 | 3 | 4 | def is_balanced(brackets: str) -> bool: 5 | stack = [] 6 | 7 | for bracket in brackets: 8 | if bracket in OPENING_CLOSING.keys(): 9 | stack.append(bracket) 10 | elif len(stack) == 0 or OPENING_CLOSING[stack.pop()] != bracket: 11 | return False 12 | 13 | if len(stack) > 0: 14 | return False 15 | 16 | return True 17 | 18 | 19 | def main(): 20 | queries = int(input()) 21 | 22 | for _ in range(queries): 23 | brackets = input() 24 | print('YES' if is_balanced(brackets) else 'NO') 25 | 26 | 27 | if __name__ == '__main__': 28 | main() 29 | -------------------------------------------------------------------------------- /StacksAndQueues/CastleOnTheGrid.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | 3 | 4 | def min_moves(grid, start_x, start_y, goal_x, goal_y): 5 | queue = deque() 6 | queue.appendleft((start_x + 1, start_y + 1, 0)) 7 | 8 | while queue: 9 | x, y, steps = queue.pop() 10 | grid[x][y] = False 11 | 12 | if x == goal_x + 1 and y == goal_y + 1: 13 | return steps 14 | 15 | d = 1 16 | while grid[x][y - d]: 17 | queue.appendleft((x, y - d, steps + 1)) 18 | d += 1 19 | 20 | d = 1 21 | while grid[x + d][y]: 22 | queue.appendleft((x + d, y, steps + 1)) 23 | d += 1 24 | 25 | d = 1 26 | while grid[x][y + d]: 27 | queue.appendleft((x, y + d, steps + 1)) 28 | d += 1 29 | 30 | d = 1 31 | while grid[x - d][y]: 32 | queue.appendleft((x - d, y, steps + 1)) 33 | d += 1 34 | 35 | 36 | def main(): 37 | n = int(input()) 38 | grid = [[False] * (n + 2) for _ in range(n + 2)] 39 | 40 | for i in range(1, n + 1): 41 | row = list(map(lambda x: x == '.', input())) 42 | grid[i][1:-1] = row 43 | 44 | start_x, start_y, goal_x, goal_y = map(int, input().split()) 45 | print(min_moves(grid, start_x, start_y, goal_x, goal_y)) 46 | 47 | 48 | if __name__ == '__main__': 49 | main() 50 | -------------------------------------------------------------------------------- /StacksAndQueues/LargestRectangle.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | n = int(input()) 3 | heights = list(map(int, input().split())) 4 | heights.append(0) 5 | answer = 0 6 | stack = [(heights[0], 0)] 7 | 8 | for i in range(1, n + 1): 9 | left = i 10 | 11 | if heights[i] < stack[-1][0]: 12 | while stack and stack[-1][0] >= heights[i]: 13 | top = stack.pop() 14 | left = top[1] 15 | answer = max(answer, top[0] * (i - left)) 16 | 17 | stack.append((heights[i], left)) 18 | 19 | print(answer) 20 | 21 | 22 | if __name__ == '__main__': 23 | main() 24 | -------------------------------------------------------------------------------- /StacksAndQueues/MinMaxRiddle.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | 4 | def main(): 5 | n = int(input()) 6 | xs = list(map(int, input().split())) 7 | xs.append(-1) 8 | answer = [0] * n 9 | 10 | d, stack = defaultdict(int), [] 11 | for i, x in enumerate(xs): 12 | index = i 13 | 14 | while stack and stack[-1][0] >= x: 15 | y, index = stack.pop() 16 | d[i - index] = max(d[i - index], y) 17 | 18 | stack.append((x, index)) 19 | 20 | current = 0 21 | for window in range(n, 0, -1): 22 | current = max(current, d[window]) 23 | answer[window - 1] = current 24 | 25 | print(*answer) 26 | 27 | 28 | if __name__ == '__main__': 29 | main() 30 | -------------------------------------------------------------------------------- /StacksAndQueues/PoisonousPlants.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | _ = int(input()) 3 | plants = list(map(int, input().split())) 4 | plants.append(-1) 5 | answer = 0 6 | 7 | stack = [] 8 | for i, plant in enumerate(plants): 9 | days = 1 10 | while stack and stack[-1][0] >= plant: 11 | days = max(days, stack[-1][1] + 1) 12 | stack.pop() 13 | 14 | if not stack: 15 | days = -1 16 | 17 | answer = max(answer, days) 18 | stack.append((plant, days)) 19 | 20 | print(answer) 21 | 22 | 23 | if __name__ == '__main__': 24 | main() 25 | -------------------------------------------------------------------------------- /StacksAndQueues/QueuesATaleOfTwoStacks.py: -------------------------------------------------------------------------------- 1 | class MyQueue(object): 2 | def __init__(self): 3 | self.store = [] 4 | self.delivery = [] 5 | 6 | def peek(self): 7 | if not self.delivery: 8 | while self.store: 9 | self.delivery.append(self.store.pop()) 10 | 11 | return self.delivery[-1] 12 | 13 | def pop(self): 14 | if not self.delivery: 15 | while self.store: 16 | self.delivery.append(self.store.pop()) 17 | 18 | return self.delivery.pop() 19 | 20 | def put(self, value): 21 | self.store.append(value) 22 | 23 | 24 | queue = MyQueue() 25 | t = int(input()) 26 | for line in range(t): 27 | values = map(int, input().split()) 28 | values = list(values) 29 | if values[0] == 1: 30 | queue.put(values[1]) 31 | elif values[0] == 2: 32 | queue.pop() 33 | else: 34 | print(queue.peek()) 35 | -------------------------------------------------------------------------------- /StringManipulation/AlternatingCharacters.py: -------------------------------------------------------------------------------- 1 | def solve(): 2 | s = input() 3 | answer = 0 4 | 5 | for i in range(1, len(s)): 6 | answer += s[i] == s[i - 1] 7 | 8 | return answer 9 | 10 | 11 | def main(): 12 | q = int(input()) 13 | 14 | for _ in range(q): 15 | print(solve()) 16 | 17 | 18 | if __name__ == '__main__': 19 | main() 20 | -------------------------------------------------------------------------------- /StringManipulation/CommonChild.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | s1, s2 = input(), input() 3 | n, m = len(s1), len(s2) 4 | 5 | dp = [[0] * (n + 1) for _ in range(m + 1)] 6 | 7 | for i in range(1, n + 1): 8 | for j in range(1, m + 1): 9 | if s1[i - 1] == s2[j - 1]: 10 | dp[i][j] = dp[i - 1][j - 1] + 1 11 | else: 12 | dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) 13 | 14 | print(dp[n][m]) 15 | 16 | 17 | if __name__ == '__main__': 18 | main() 19 | -------------------------------------------------------------------------------- /StringManipulation/MakingAnagrams.py: -------------------------------------------------------------------------------- 1 | def count(s): 2 | counts = [0] * 26 3 | 4 | for letter in s: 5 | counts[ord(letter) - ord('a')] += 1 6 | 7 | return counts 8 | 9 | 10 | def diff(xs, ys): 11 | return sum(abs(x - y) for (x, y) in zip(xs, ys)) 12 | 13 | 14 | def main(): 15 | a = input() 16 | b = input() 17 | print(diff(count(a), count(b))) 18 | 19 | 20 | if __name__ == '__main__': 21 | main() 22 | -------------------------------------------------------------------------------- /StringManipulation/SherlockAndTheValidString.py: -------------------------------------------------------------------------------- 1 | def count(s): 2 | frequencies = [0] * 26 3 | 4 | for letter in s: 5 | frequencies[ord(letter) - ord('a')] += 1 6 | 7 | return frequencies 8 | 9 | 10 | def solve(s): 11 | frequencies = sorted(filter(lambda x: x > 0, count(s))) 12 | 13 | if len(set(frequencies)) > 2: 14 | return 'NO' 15 | 16 | if (frequencies[0] == frequencies[-1] or 17 | (frequencies[0] == 1 and frequencies[0] != frequencies[1]) or 18 | frequencies[1] - frequencies[0] == 1 or 19 | frequencies[-1] - frequencies[-2] == 1): 20 | return 'YES' 21 | 22 | return 'NO' 23 | 24 | 25 | def main(): 26 | s = input() 27 | print(solve(s)) 28 | 29 | 30 | if __name__ == '__main__': 31 | main() 32 | -------------------------------------------------------------------------------- /StringManipulation/SpecialPalindromeAgain.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | n = int(input()) 3 | s = input() + '.' 4 | 5 | answer = 0 6 | 7 | current = 1 8 | for i in range(n): 9 | if s[i] != s[i + 1]: 10 | answer += current * (current + 1) // 2 11 | current = 1 12 | else: 13 | current += 1 14 | 15 | left = [1] * n 16 | left[0] = 0 17 | right = [1] * n 18 | right[-1] = 0 19 | 20 | for i in range(2, n): 21 | if s[i - 1] == s[i - 2]: 22 | left[i] = left[i - 1] + 1 23 | if s[n - i + 1] == s[n - i]: 24 | right[n - i - 1] = right[n - i] + 1 25 | 26 | for i in range(1, n - 1): 27 | if s[i] != s[i - 1] and s[i - 1] == s[i + 1]: 28 | answer += min(left[i], right[i]) 29 | 30 | print(answer) 31 | 32 | 33 | if __name__ == '__main__': 34 | main() 35 | -------------------------------------------------------------------------------- /Trees/HeightOfABinaryTree.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, info): 3 | self.info = info 4 | self.left = None 5 | self.right = None 6 | self.level = None 7 | 8 | def __str__(self): 9 | return str(self.info) 10 | 11 | 12 | class BinarySearchTree: 13 | def __init__(self): 14 | self.root = None 15 | 16 | def create(self, val): 17 | if self.root is None: 18 | self.root = Node(val) 19 | else: 20 | current = self.root 21 | 22 | while True: 23 | if val < current.info: 24 | if current.left: 25 | current = current.left 26 | else: 27 | current.left = Node(val) 28 | break 29 | elif val > current.info: 30 | if current.right: 31 | current = current.right 32 | else: 33 | current.right = Node(val) 34 | break 35 | else: 36 | break 37 | 38 | 39 | def height(root): 40 | if root is None or is_leaf(root): 41 | return 0 42 | 43 | return max(height(root.left), height(root.right)) + 1 44 | 45 | 46 | def is_leaf(node): 47 | return node.left is None and node.right is None 48 | 49 | 50 | if __name__ == '__main__': 51 | tree = BinarySearchTree() 52 | t = int(input()) 53 | 54 | arr = list(map(int, input().split())) 55 | 56 | for i in range(t): 57 | tree.create(arr[i]) 58 | 59 | print(height(tree.root)) 60 | -------------------------------------------------------------------------------- /Trees/HuffmanDecoding.py: -------------------------------------------------------------------------------- 1 | def is_leaf(node): 2 | return node.left is None and node.right is None 3 | 4 | 5 | def decode(root, s): 6 | result = '' 7 | 8 | current = root 9 | for bit in s: 10 | if bit == '0': 11 | current = current.left 12 | else: 13 | current = current.right 14 | 15 | if is_leaf(current): 16 | result += current.data 17 | current = root 18 | 19 | print(result) 20 | -------------------------------------------------------------------------------- /Trees/IsThisABinarySearchTree.py: -------------------------------------------------------------------------------- 1 | DATA_MIN = -1 2 | DATA_MAX = 10001 3 | 4 | 5 | def is_bst(root): 6 | return check(root, DATA_MIN, DATA_MAX) 7 | 8 | 9 | def check(root, left, right): 10 | if root is None: 11 | return True 12 | if root.data <= left or root.data >= right: 13 | return False 14 | return (check(root.left, left, root.data) and 15 | check(root.right, root.data, right)) 16 | -------------------------------------------------------------------------------- /Trees/LowestCommonAncestor.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, info): 3 | self.info = info 4 | self.left = None 5 | self.right = None 6 | self.level = None 7 | 8 | def __str__(self): 9 | return str(self.info) 10 | 11 | 12 | class BinarySearchTree: 13 | def __init__(self): 14 | self.root = None 15 | 16 | def create(self, val): 17 | if self.root is None: 18 | self.root = Node(val) 19 | else: 20 | current = self.root 21 | 22 | while True: 23 | if val < current.info: 24 | if current.left: 25 | current = current.left 26 | else: 27 | current.left = Node(val) 28 | break 29 | elif val > current.info: 30 | if current.right: 31 | current = current.right 32 | else: 33 | current.right = Node(val) 34 | break 35 | else: 36 | break 37 | 38 | 39 | def lca(root, v1, v2): 40 | if root.info < v1 and root.info < v2: 41 | return lca(root.right, v1, v2) 42 | if root.info > v1 and root.info > v2: 43 | return lca(root.left, v1, v2) 44 | return root 45 | 46 | 47 | if __name__ == '__main__': 48 | tree = BinarySearchTree() 49 | t = int(input()) 50 | 51 | arr = list(map(int, input().split())) 52 | 53 | for i in range(t): 54 | tree.create(arr[i]) 55 | 56 | v = list(map(int, input().split())) 57 | 58 | ans = lca(tree.root, v[0], v[1]) 59 | print(ans.info) 60 | -------------------------------------------------------------------------------- /WarmupChallenges/CountingValleys.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | _ = input() 3 | path = input() 4 | 5 | level = 0 6 | answer = 0 7 | 8 | for step in path: 9 | if step == 'U' and level == -1: 10 | answer += 1 11 | level += 1 if step == 'U' else -1 12 | 13 | print(answer) 14 | 15 | 16 | if __name__ == '__main__': 17 | main() 18 | -------------------------------------------------------------------------------- /WarmupChallenges/JumpingOnTheClouds.py: -------------------------------------------------------------------------------- 1 | INF = 1000000000 2 | 3 | 4 | def main(): 5 | n = int(input()) 6 | is_cumulus = list(map(lambda x: x == '0', input().split())) 7 | 8 | dp = [0] * n 9 | dp[1] = 1 if is_cumulus[1] else INF 10 | 11 | for i in range(2, n): 12 | if is_cumulus[i]: 13 | dp[i] = min(dp[i - 1], dp[i - 2]) + 1 14 | else: 15 | dp[i] = INF 16 | 17 | print(dp[-1]) 18 | 19 | 20 | if __name__ == '__main__': 21 | main() 22 | -------------------------------------------------------------------------------- /WarmupChallenges/RepeatedString.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | s = input() 3 | n = int(input()) 4 | 5 | count = s.count('a') 6 | answer = (n // len(s)) * count 7 | answer += s[:n % len(s)].count('a') 8 | 9 | print(answer) 10 | 11 | 12 | if __name__ == '__main__': 13 | main() 14 | -------------------------------------------------------------------------------- /WarmupChallenges/SockMerchant.py: -------------------------------------------------------------------------------- 1 | from collections import Counter 2 | 3 | 4 | def main(): 5 | _ = input() 6 | colors = list(map(int, input().split())) 7 | 8 | answer = sum(map(lambda x: x // 2, Counter(colors).values())) 9 | 10 | print(answer) 11 | 12 | 13 | if __name__ == '__main__': 14 | main() 15 | --------------------------------------------------------------------------------