├── README.md ├── graph_algorithm ├── .bfs.py.swp ├── bfs.py ├── bfs_queue.py ├── count_nodes.py ├── count_vertices.py ├── dfs.py ├── height_tree.py ├── height_tree_v2.py ├── interative_dfs.py ├── k_cores_graph.py ├── minimun_initial_vertices.py ├── mother_vertex.py ├── num_trees.py ├── path_rectangle.py ├── shorest_path_prime.py ├── transitive_matrix.py └── water_jug.py ├── search_algorithm ├── .find_closest_pair_from_two_sorted_array.py.swp ├── best_first_search.py ├── binary_search.py ├── binary_search_least_comparision.py ├── ceil_value.py ├── count_occurrence.py ├── count_one_in_sorted_binary_array.py ├── diff_adjacent_element_one.py ├── element_appear_one_in_sorted_array.py ├── fibonacci_search.py ├── find_element.py ├── find_first_repeating_element.py ├── find_k_closest_elements.py ├── find_missing_and_repeating_number.py ├── find_pair_sum_closest_x.py ├── find_pair_with_given_difference.py ├── fixed_point.py ├── floor_value.py ├── floor_value_in_sorted_array.py ├── intersection_of_three_sorted_array.py ├── k_largest_elements.py ├── largest_three_elements.py ├── majority_elemnents.py ├── make_array_elements_equal_minimum_cost.py ├── maximun_in_zizag_array.py ├── median_of_two_sorted_array.py ├── minimum_in_sorted_rotated_array.py ├── minimum_required_time.py ├── minimum_rotated_array.py ├── minimun_comparision_min_max.py ├── quick_selection.py ├── recursive_linear_search.py ├── recursive_substring_search.py ├── search_in_rotated_sorted_array.py ├── search_in_rotated_sorted_array_v2.py ├── smallest_and_second_smallest.py ├── smallest_difference_triplet.py ├── sublist_search.py ├── sum_closest_zero.py ├── sum_closest_zero_v2.py ├── sum_of_consecutive_numbers.py ├── three_closest_elements.py └── triplets_sum_to_zero.py └── sort_algorithm ├── adjacent_swaps.py ├── binary_insertion_sort.py ├── bitonic_sort.py ├── bubble_sort.py ├── bucket_sort.py ├── check_sorted_array.py ├── closest_pair.py ├── cocktail_sort.py ├── comb_sort.py ├── conditional_swapping.py ├── conflict_threads.py ├── consecutive_numbers.py ├── count_all_pairs_difference.py ├── count_distinct_occurrences_subsequence.py ├── count_inversion.py ├── count_sort.py ├── count_surpasser.py ├── cycle_sort.py ├── even_odd_sort.py ├── external_sort.py ├── gnome_sort.py ├── greatest_product.py ├── heap_sort.py ├── insertion_sort.py ├── iterative_quick_sort.py ├── kth_smallest.py ├── largest_3_multiple.py ├── length_sort.py ├── lomuto_partition_quick_sort.py ├── max_diff.py ├── maximum_height_pyramid.py ├── maximum_interval_overlap.py ├── maximum_product_triplet.py ├── merge_sort.py ├── merge_sort_linked_list.py ├── minimum_difference.py ├── minimum_sum_diff.py ├── minimum_swaps.py ├── minimum_swaps_2_positions.py ├── minimum_swaps_identical_array.py ├── minimum_unsorted_subarray.py ├── nearly_sorted_array.py ├── noble_integer.py ├── number_pairs_xy_yx.py ├── odd_even_sort.py ├── overlap_interval.py ├── pancake_sort.py ├── pancake_sorting_question.py ├── pigeonhole_sort.py ├── possible_triangle.py ├── quick_sort.py ├── quick_sort_doubly_linked_list.py ├── quick_sort_reducing_worst_case.py ├── radix_sort.py ├── rearrange_pos_neg.py ├── recursive_bubble_sort.py ├── recursive_insertion_sort.py ├── reversing_subarray.py ├── selection_sort.py ├── sextuplets.py ├── shell_sort.py ├── smallest_diff_pair.py ├── smallest_diff_triplet.py ├── sort_array_012s.py ├── sort_big_int.py ├── sort_dates.py ├── sort_element_by_frequency.py ├── sort_n_number_n2.py ├── sort_one_swap.py ├── sort_square_array.py ├── sort_using_max.py ├── sort_waveform.py ├── sort_without_copy.py ├── sorted_array_given_equation.py ├── stooge_sort.py ├── three_way_merge_sort.py ├── three_way_quick_sort.py ├── tim_sort.py ├── tree_sort.py ├── triplet_sum_zero.py └── worst_case_mergesort.py /README.md: -------------------------------------------------------------------------------- 1 | # Giới thiệu 2 | Để chuẩn bị cho quá trình phỏng vấn ở những công ty lớn các bạn cần phải review lại kiến thức data structure and algorithm. Trong bộ sưu tập này, mình cài đặt lại các data structure cơ bản cũng nhưng chỉ ra các ưu điểm và khuyết điểm của mỗi loại. Quá trình phỏng vấn ở mỗi công ty thường sẽ không yêu cầu kiến thức trọng mà sẽ chú trọng đến những topic basic nhưng với độ khó tắng dần. 3 | 4 | # Searching Algorithm 5 | - Given two linked lists, the task is to check whether the first list is present in 2nd list or not. 6 | 7 | -------------------------------------------------------------------------------- /graph_algorithm/.bfs.py.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pbcquoc/coding-interview-python/9dfd2a96f629e78684a972a2fdfda3cd831b6ce8/graph_algorithm/.bfs.py.swp -------------------------------------------------------------------------------- /graph_algorithm/bfs.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | class Graph(): 4 | def __init__(self): 5 | self.graph = defaultdict(list) 6 | 7 | def add_edge(self, u, v): 8 | self.graph[u].append(v) 9 | 10 | def BFS(self, s): 11 | visited = [False]*(max(self.graph) + 1) 12 | queue = [] 13 | 14 | queue.append(s) 15 | visited[s] = True 16 | 17 | while queue: 18 | s = queue.pop(0) 19 | print(s, end=' ') 20 | 21 | for i in self.graph[s]: 22 | if visited[i] == False: 23 | queue.append(i) 24 | visited[i] = True 25 | 26 | g = Graph() 27 | g.add_edge(0, 1) 28 | g.add_edge(0, 2) 29 | g.add_edge(1, 2) 30 | g.add_edge(2, 0) 31 | g.add_edge(2, 3) 32 | g.add_edge(3, 3) 33 | g.BFS(2) 34 | 35 | -------------------------------------------------------------------------------- /graph_algorithm/bfs_queue.py: -------------------------------------------------------------------------------- 1 | import queue 2 | 3 | def addEdge(g, u, v): 4 | g[u].append(v) 5 | g[v].append(u) 6 | 7 | def BFSSingleSource(g, s): 8 | q = queue.Queue() 9 | 10 | q.put(s) 11 | 12 | d[s] = 0 13 | colour[s] = 'green' 14 | 15 | while(not q.empty()): 16 | u = q.get() 17 | 18 | print(u, end=' ') 19 | 20 | i = 0 21 | while i < len(g[u]): 22 | if colour[g[u][i]] == 'white': 23 | colour[g[u][i]] = 'green' 24 | d[g[u][i]] = d[u] + 1 25 | p[g[u][i]] = u 26 | 27 | q.put(g[u][i]) 28 | 29 | i += 1 30 | 31 | colour[u] = 'dark_green' 32 | 33 | def BFSFull(g, n): 34 | 35 | colour = ['white']*n 36 | d = [0]*n 37 | p = [-1]*n 38 | 39 | for i in range(n): 40 | if colour[i] == 'white': 41 | BFSSingleSource(g, i) 42 | 43 | n = 7 44 | colour = [None] * n 45 | d = [None] * n 46 | p = [None] * n 47 | 48 | # The Graph vector 49 | g = [[] for i in range(n)] 50 | 51 | addEdge(g, 0, 1) 52 | addEdge(g, 0, 2) 53 | addEdge(g, 1, 3) 54 | addEdge(g, 1, 4) 55 | addEdge(g, 2, 5) 56 | addEdge(g, 2, 6) 57 | 58 | BFSFull(g, n) 59 | 60 | -------------------------------------------------------------------------------- /graph_algorithm/count_nodes.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | 3 | adj = [[] for i in range(10001)] 4 | 5 | def addEdge(v, w): 6 | adj[v].append(w) 7 | adj[w].append(v) 8 | 9 | def BFS(s, l): 10 | V = 100 11 | visited = [False]*V 12 | level = [0]*V 13 | 14 | queue = deque() 15 | 16 | visited[s] = True 17 | queue.append(s) 18 | level[s] = 0 19 | 20 | while len(queue) > 0: 21 | s = queue.popleft() 22 | 23 | for i in adj[s]: 24 | if not visited[i]: 25 | level[i] = level[s] + 1 26 | visited[i] = True 27 | queue.append(i) 28 | 29 | count = 0 30 | for i in range(V): 31 | if level[i] == l: 32 | count += 1 33 | 34 | return count 35 | 36 | addEdge(0, 1) 37 | addEdge(0, 2) 38 | addEdge(1, 3) 39 | addEdge(2, 4) 40 | addEdge(2, 5) 41 | 42 | level = 2 43 | 44 | print(BFS(0, level)) 45 | -------------------------------------------------------------------------------- /graph_algorithm/count_vertices.py: -------------------------------------------------------------------------------- 1 | class Graph: 2 | def __init__(self, V): 3 | self.V = V 4 | self.adj = [[] for i in range(V)] 5 | 6 | def addEdge(self, u, v): 7 | self.adj[u].append(v) 8 | 9 | def countPaths(self, s, d): 10 | visited = [False]*self.V 11 | 12 | pathCount = [0] 13 | 14 | self.countPathsUtil(s, d, visited, pathCount) 15 | return pathCount[0] 16 | 17 | def countPathsUtil(self, u, d, visited, pathCount): 18 | 19 | visited[u] = True 20 | 21 | if u==d: 22 | pathCount[0] += 1 23 | 24 | else: 25 | i = 0 26 | 27 | while i < len(self.adj[u]): 28 | if not visited[self.adj[u][i]]: 29 | self.countPathsUtil(self.adj[u][i], d, visited, pathCount) 30 | 31 | i+=1 32 | 33 | visited[u] = False 34 | 35 | 36 | g = Graph(4) 37 | g.addEdge(0, 1) 38 | g.addEdge(0, 2) 39 | g.addEdge(0, 3) 40 | g.addEdge(2, 0) 41 | g.addEdge(2, 1) 42 | g.addEdge(1, 3) 43 | 44 | s = 2 45 | d = 3 46 | 47 | print(g.countPaths(s, d)) 48 | -------------------------------------------------------------------------------- /graph_algorithm/dfs.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | class Graph(): 4 | def __init__(self): 5 | self.graph = defaultdict(list) 6 | 7 | def add_edge(self, u, v): 8 | self.graph[u].append(v) 9 | 10 | def dfs_util(self, v, visited): 11 | visited.add(v) 12 | 13 | print(v, end=' ') 14 | 15 | for neighbour in self.graph[v]: 16 | if neighbour not in visited: 17 | self.dfs_util(neighbour, visited) 18 | 19 | 20 | def dfs(self, v): 21 | visited = set() 22 | self.dfs_util(v, visited) 23 | 24 | 25 | g = Graph() 26 | g.add_edge(0, 1) 27 | g.add_edge(0, 2) 28 | g.add_edge(1, 2) 29 | g.add_edge(2, 0) 30 | g.add_edge(2, 3) 31 | g.add_edge(3, 3) 32 | 33 | g.dfs(2) 34 | 35 | -------------------------------------------------------------------------------- /graph_algorithm/height_tree.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | 3 | MAX = 1001 4 | 5 | adj = [[] for i in range(MAX)] 6 | 7 | def build_tree(arr, n): 8 | root_index = 0 9 | 10 | for i in range(n): 11 | if arr[i] == -1: 12 | root_index = i 13 | else: 14 | adj[i].append(arr[i]) 15 | adj[arr[i]].append(i) 16 | 17 | return root_index 18 | 19 | def BFS(start): 20 | vis = {} 21 | 22 | q = deque() 23 | max_level_reached = 0 24 | 25 | q.append([start, 0]) 26 | 27 | p = [] 28 | 29 | while len(q) > 0: 30 | p = q.popleft() 31 | vis[p[0]] = 1 32 | 33 | max_level_reached = max(max_level_reached, p[1]) 34 | 35 | for i in range(len(adj[p[0]])): 36 | 37 | if adj[p[0]][i] not in vis: 38 | q.append([adj[p[0]][i], p[1] + 1]) 39 | 40 | return max_level_reached 41 | 42 | parent = [-1, 0, 1, 2, 3] 43 | 44 | # Number of nodes in tree 45 | n = len(parent) 46 | 47 | root_index = build_tree(parent, n) 48 | ma = BFS(root_index) 49 | 50 | print(ma) 51 | -------------------------------------------------------------------------------- /graph_algorithm/height_tree_v2.py: -------------------------------------------------------------------------------- 1 | def fillHeight(p, node, visited, height): 2 | if p[node] == -1: 3 | visited[node] = 1 4 | return 0 5 | 6 | if visited[node]: 7 | return height[node] 8 | 9 | visited[node] = 1 10 | height[node] = 1 + fillHeight(p, p[node], visited, height) 11 | 12 | return height[node] 13 | 14 | def findHeight(parent, n): 15 | ma = 0 16 | 17 | visited = [0]*n 18 | height = [0]*n 19 | 20 | for i in range(n): 21 | if not visited[i]: 22 | height[i] = fillHeight(parent, i, visited, height) 23 | 24 | ma = max(ma, height[i]) 25 | 26 | 27 | return ma 28 | 29 | parent = [-1, 0, 0, 0, 3, 1, 1, 2] 30 | n = len(parent) 31 | 32 | print("Height of N-ary Tree =", findHeight(parent, n)) 33 | -------------------------------------------------------------------------------- /graph_algorithm/interative_dfs.py: -------------------------------------------------------------------------------- 1 | class Graph: 2 | def __init__(self, V): 3 | self.V = V 4 | self.adj = [[] for i in range(V)] 5 | 6 | def addEdge(self, v, w): 7 | self.adj[v].append(w) 8 | 9 | def DFS(self, s): 10 | visited = [False for i in range(self.V)] 11 | 12 | stack = [] 13 | 14 | stack.append(s) 15 | while len(stack): 16 | s = stack[-1] 17 | stack.pop() 18 | 19 | if not visited[s]: 20 | print(s, end=' ') 21 | visited[s] = True 22 | 23 | for node in self.adj[s]: 24 | if not visited[node]: 25 | stack.append(node) 26 | 27 | 28 | g = Graph(5); # Total 5 vertices in graph 29 | g.addEdge(1, 0); 30 | g.addEdge(0, 2); 31 | g.addEdge(2, 1); 32 | g.addEdge(0, 3); 33 | g.addEdge(1, 4); 34 | 35 | g.DFS(0) 36 | -------------------------------------------------------------------------------- /graph_algorithm/k_cores_graph.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | class Graph: 4 | def __init__(self): 5 | self.graph = defaultdict(list) 6 | 7 | def addEdge(self, u, v): 8 | self.graph[u].append(v) 9 | self.graph[v].append(u) 10 | 11 | def DFSUtil(self, v, visited, vDegree, k): 12 | visited.add(v) 13 | 14 | for i in self.graph[v]: 15 | if vDegree[v] < k: 16 | vDegree[i] -= 1 17 | 18 | if i not in visited: 19 | self.DFSUtil(i, visited, vDegree, k) 20 | 21 | 22 | def printKCores(self, k): 23 | visit = set() 24 | degree = defaultdict(int) 25 | 26 | for i in list(self.graph): 27 | degree[i] = len(self.graph[i]) 28 | 29 | for i in list(self.graph): 30 | if i not in visit: 31 | self.DFSUtil(i, visit, degree, k) 32 | 33 | for i in list(self.graph): 34 | if degree[i] >= k: 35 | print('\n[{}]'.format(i), end=' ') 36 | 37 | for j in self.graph[i]: 38 | if degree[j] >= k: 39 | print('-> {}'.format(j), end=' ') 40 | 41 | print() 42 | 43 | k = 3 44 | g1 = Graph() 45 | g1.addEdge(0, 1) 46 | g1.addEdge(0, 2) 47 | g1.addEdge(1, 2) 48 | g1.addEdge(1, 5) 49 | g1.addEdge(2, 3) 50 | g1.addEdge(2, 4) 51 | g1.addEdge(2, 5) 52 | g1.addEdge(2, 6) 53 | g1.addEdge(3, 4) 54 | g1.addEdge(3, 6) 55 | g1.addEdge(3, 7) 56 | g1.addEdge(4, 6) 57 | g1.addEdge(4, 7) 58 | g1.addEdge(5, 6) 59 | g1.addEdge(5, 8) 60 | g1.addEdge(6, 7) 61 | g1.addEdge(6, 8) 62 | g1.printKCores(k) 63 | -------------------------------------------------------------------------------- /graph_algorithm/minimun_initial_vertices.py: -------------------------------------------------------------------------------- 1 | MAX = 100 2 | 3 | def dfs(n, m, visit, adj, N, M): 4 | visit[n][m] = 1 5 | 6 | if n + 1 < N and adj[n][m] >= adj[n+1][m] and not visit[n+1][m]: 7 | dfs(n+1, m, visit, adj, N, M) 8 | 9 | if m + 1 < M and adj[n][m] >= adj[n][m+1] and not visit[n][m+1]: 10 | dfs(n, m+1, visit, adj, N, M) 11 | 12 | if n - 1 >= 0 and adj[n][m] >= adj[n-1][m] and not visit[n-1][m]: 13 | dfs(n-1, m, visit, adj, N, M) 14 | 15 | if m - 1 >= 0 and adj[n][m] >= adj[n][m-1] and not visit[n][m-1]: 16 | dfs(n, m-1, visit, adj, N, M) 17 | 18 | 19 | def printMinSources(adj, N, M): 20 | x = [] 21 | 22 | for i in range(N): 23 | for j in range(M): 24 | x.append([adj[i][j], [i, j]]) 25 | 26 | x.sort() 27 | 28 | visit = [[False for i in range(MAX)] for i in range(N)] 29 | 30 | for i in range(len(x) - 1, -1, -1): 31 | if not visit[x[i][1][0]][x[i][1][1]]: 32 | print('{} {}'.format(x[i][1][0], x[i][1][1])) 33 | 34 | dfs(x[i][1][0], x[i][1][1], visit, adj, N, M) 35 | 36 | N = 2 37 | M = 2 38 | 39 | adj = [ [ 3, 3 ], [ 1, 1 ] ] 40 | 41 | printMinSources(adj, N, M) 42 | 43 | -------------------------------------------------------------------------------- /graph_algorithm/mother_vertex.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | class Graph(): 4 | def __init__(self, vertices): 5 | self.V = vertices 6 | self.graph = defaultdict(list) 7 | 8 | def dfs_util(self, v, visited): 9 | visited[v] = True 10 | for i in self.graph[v]: 11 | if visited[i] == False: 12 | self.dfs_util(i, visited) 13 | 14 | 15 | def add_edge(self, v, w): 16 | self.graph[v].append(w) 17 | 18 | def find_mother(self): 19 | visited = [False]*self.V 20 | 21 | v = 0 22 | 23 | for i in range(self.V): 24 | if visited[i] == False: 25 | self.dfs_util(i, visited) 26 | v = i 27 | 28 | 29 | visited = [False]*self.V 30 | self.dfs_util(v, visited) 31 | 32 | if any(i==False for i in visited): 33 | return -1 34 | else: 35 | return v 36 | 37 | g = Graph(7) 38 | g.add_edge(0, 1) 39 | g.add_edge(0, 2) 40 | g.add_edge(1, 3) 41 | g.add_edge(4, 1) 42 | g.add_edge(6, 4) 43 | g.add_edge(5, 6) 44 | g.add_edge(5, 2) 45 | g.add_edge(6, 0) 46 | 47 | print('mother vertex: {}'.format(g.find_mother())) 48 | -------------------------------------------------------------------------------- /graph_algorithm/num_trees.py: -------------------------------------------------------------------------------- 1 | def addEdge(adj,u,v): 2 | adj[u].append(v) 3 | adj[v].append(u) 4 | 5 | def DFSUtil(u, adj, visited): 6 | visited[u] = True 7 | 8 | for i in range(len(adj[u])): 9 | if visited[adj[u][i]] == False: 10 | DFSUtil(adj[u][i], adj, visited) 11 | 12 | def countTrees(adj, V): 13 | visited = [False]*V 14 | res = 0 15 | for u in range(V): 16 | if (visited[u] == False): 17 | DFSUtil(u, adj, visited) 18 | res += 1 19 | 20 | return res 21 | 22 | V = 5 23 | adj = [[] for i in range(V)] 24 | addEdge(adj, 0, 1) 25 | addEdge(adj, 0, 2) 26 | addEdge(adj, 3, 4) 27 | 28 | print(countTrees(adj, V)) 29 | -------------------------------------------------------------------------------- /graph_algorithm/path_rectangle.py: -------------------------------------------------------------------------------- 1 | import math 2 | import queue 3 | 4 | def is_possible(m, n, k, r, X, Y): 5 | rect = [[0]*n for i in range(m)] 6 | 7 | for i in range(m): 8 | for j in range(n): 9 | for p in range(k): 10 | if math.sqrt((pow((X[p] -1 -i), 2) + pow((Y[p] -1 -j), 2))) <= r: 11 | rect[i][j] = -1 12 | 13 | 14 | if rect[0][0] == -1: 15 | return False 16 | 17 | qu = queue.Queue() 18 | 19 | rect[0][0] = 1 20 | qu.put([0, 0]) 21 | 22 | while (not qu.empty()): 23 | arr = qu.get() 24 | 25 | elex = arr[0] 26 | eley = arr[1] 27 | 28 | if elex > 0 and eley > 0 and rect[elex - 1][eley - 1] == 0: 29 | rect[elex - 1][eley - 1] = 1 30 | v = [elex - 1, eley - 1] 31 | qu.put(v) 32 | 33 | if elex > 0 and rect[elex -1][eley] == 0: 34 | rect[elex - 1][eley] = 1 35 | v = [elex -1, eley] 36 | qu.put(v) 37 | 38 | if elex > 0 and eley < n -1 and rect[elex -1][eley + 1] == 0: 39 | rect[elex - 1][eley + 1] = 1 40 | v = [elex - 1, eley + 1] 41 | qu.put(v) 42 | 43 | if eley > 0 and rect[elex][eley -1] == 0: 44 | rect[elex][eley - 1] = 1 45 | v = [elex, eley - 1] 46 | qu.put(v) 47 | 48 | if eley < n -1 and rect[elex][eley + 1] == 0: 49 | rect[elex][eley + 1] = 1 50 | v = [elex, eley + 1] 51 | qu.put(v) 52 | 53 | if elex < m - 1 and eley > 0 and rect[elex + 1][eley - 1] == 0: 54 | rect[elex + 1][eley - 1] = 1 55 | v = [elex + 1, eley - 1] 56 | qu.put(v) 57 | 58 | if elex < m - 1 and rect[elex + 1][eley] == 0: 59 | rect[elex + 1][eley] = 1 60 | v = [elex + 1, eley] 61 | qu.put(v) 62 | 63 | if elex < m -1 and eley < n - 1 and rect[elex + 1][eley + 1] == 0: 64 | rect[elex + 1][eley + 1] = 1 65 | v = [elex + 1, eley + 1] 66 | qu.put(v) 67 | 68 | return rect[m - 1][n - 1] == 1 69 | 70 | m1 = 5 71 | n1 = 5 72 | k1 = 2 73 | r1 = 1 74 | X1 = [1, 3] 75 | Y1 = [3, 3] 76 | 77 | # Function call 78 | if (is_possible(m1, n1, k1, r1, X1, Y1)): 79 | print("Possible") 80 | else: 81 | print("Not Possible") 82 | 83 | # Test case 2 84 | m2 = 5 85 | n2 = 5 86 | k2 = 2 87 | r2 = 1 88 | X2 = [1, 1] 89 | Y2 = [2, 3] 90 | 91 | # Function call 92 | if (is_possible(m2, n2, k2, r2, X2, Y2)): 93 | print("Possible") 94 | else: 95 | print("Not Possible") 96 | -------------------------------------------------------------------------------- /graph_algorithm/shorest_path_prime.py: -------------------------------------------------------------------------------- 1 | import queue 2 | 3 | class Graph: 4 | 5 | def __init__(self, V): 6 | self.V = V 7 | self.l = [[] for i in range(V)] 8 | 9 | 10 | def addedge(self, V1, V2): 11 | self.l[V1].append(V2) 12 | self.l[V2].append(V1) 13 | 14 | def bfs(self, in1, in2): 15 | visited = [0]*self.V 16 | 17 | que = queue.Queue() 18 | visited[in1] = 1 19 | que.put(in1) 20 | 21 | while not que.empty(): 22 | p = que.queue[0] 23 | que.get() 24 | 25 | i = 0 26 | while i < len(self.l[p]): 27 | if not visited[self.l[p][i]]: 28 | visited[self.l[p][i]] = visited[p] + 1 29 | que.put(self.l[p][i]) 30 | 31 | if self.l[p][i] == in2: 32 | return visited[self.l[p][i]] - 1 33 | 34 | i += 1 35 | 36 | 37 | 38 | def SieveOfEratosthenes(v): 39 | 40 | n = 9999 41 | prime = [True] * (n + 1) 42 | 43 | p = 2 44 | while p*p <= n: 45 | if prime[p] == True: 46 | for i in range(p*p, n + 1, p): 47 | prime[i] = False 48 | p += 1 49 | 50 | for p in range(1000, n + 1): 51 | if prime[p]: 52 | v.append(p) 53 | 54 | 55 | def compare(num1, num2): 56 | s1 = str(num1) 57 | s2 = str(num2) 58 | c = 0 59 | if s1[0] != s2[0]: 60 | c += 1 61 | 62 | if s1[1] != s2[1]: 63 | c += 1 64 | 65 | if s1[2] != s2[2]: 66 | c += 1 67 | 68 | if s1[3] != s2[3]: 69 | c += 1 70 | 71 | return c==1 72 | 73 | def shortestPath(num1, num2): 74 | pset = [] 75 | 76 | SieveOfEratosthenes(pset) 77 | 78 | g = Graph(len(pset)) 79 | for i in range(len(pset)): 80 | for j in range(i+1, len(pset)): 81 | if compare(pset[i], pset[j]): 82 | g.addedge(i, j) 83 | 84 | in1, in2 = None, None 85 | 86 | for j in range(len(pset)): 87 | if pset[j] == num1: 88 | in1 = j 89 | 90 | for j in range(len(pset)): 91 | if pset[j] == num2: 92 | in2 = j 93 | 94 | return g.bfs(in1, in2) 95 | 96 | num1 = 1033 97 | num2 = 8179 98 | 99 | print(shortestPath(num1, num2)) 100 | -------------------------------------------------------------------------------- /graph_algorithm/transitive_matrix.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | class Graph: 4 | def __init__(self, vertices): 5 | self.V = vertices 6 | 7 | self.graph = defaultdict(list) 8 | 9 | self.tc = [[0 for j in range(self.V)] for i in range(self.V)] 10 | 11 | def addEdge(self, u, v): 12 | self.graph[u].append(v) 13 | 14 | 15 | def DFSUtil(self, s, v): 16 | if (s==v): 17 | if (v in self.graph[s]): 18 | self.tc[s][v] = 1 19 | else: 20 | self.tc[s][v] = 1 21 | 22 | for i in self.graph[v]: 23 | if self.tc[s][i] == 0: 24 | if s==i: 25 | self.tc[s][i] = 1 26 | else: 27 | self.DFSUtil(s, i) 28 | 29 | def transitiveClosure(self): 30 | for i in range(self.V): 31 | self.DFSUtil(i, i) 32 | print(self.tc) 33 | 34 | g = Graph(4) 35 | g.addEdge(0, 1) 36 | g.addEdge(0, 2) 37 | g.addEdge(1, 2) 38 | g.addEdge(2, 0) 39 | g.addEdge(2, 3) 40 | g.addEdge(3, 3) 41 | 42 | g.transitiveClosure() 43 | 44 | 45 | -------------------------------------------------------------------------------- /graph_algorithm/water_jug.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | 3 | def BFS(a, b, target): 4 | m = {} 5 | isSolvable = False 6 | 7 | path = [] 8 | q = deque() 9 | 10 | q.append((0, 0)) 11 | 12 | while len(q) > 0: 13 | u = q.popleft() 14 | 15 | if (u[0], u[1]) in m : 16 | continue 17 | 18 | if u[0] > a or u[1] > b or u[0] < 0 or u[1] < 0: 19 | continue 20 | 21 | path.append([u[0], u[1]]) 22 | 23 | m[(u[0], u[1])] = 1 24 | 25 | if u[0] == target or u[1] == target: 26 | isSolvable = True 27 | 28 | if (u[0] == target): 29 | if (u[1] != 0): 30 | path.append([u[0], 0]) 31 | else: 32 | if (u[0] != 0): 33 | path.append([0, u[1]]) 34 | 35 | sz = len(path) 36 | for i in range(sz): 37 | print("(", path[i][0], ",", path[i][1], ")") 38 | 39 | break 40 | 41 | q.append([u[0], b]) 42 | q.append([a, u[1]]) 43 | 44 | for ap in range(max(a, b) + 1): 45 | c = u[0] + ap 46 | d = u[1] - ap 47 | 48 | if c == a or (d == 0 and d >= 0): 49 | q.append([c, d]) 50 | 51 | c = u[0] - ap 52 | d = u[1] + ap 53 | 54 | if (c == 0 and c >= 0) or d == b: 55 | q.append([c, d]) 56 | 57 | q.append([a, 0]) 58 | q.append([0, b]) 59 | 60 | if not isSolvable: 61 | print('No solution') 62 | 63 | 64 | Jug1, Jug2, target = 4, 3, 2 65 | BFS(Jug1, Jug2, target) 66 | -------------------------------------------------------------------------------- /search_algorithm/.find_closest_pair_from_two_sorted_array.py.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pbcquoc/coding-interview-python/9dfd2a96f629e78684a972a2fdfda3cd831b6ce8/search_algorithm/.find_closest_pair_from_two_sorted_array.py.swp -------------------------------------------------------------------------------- /search_algorithm/best_first_search.py: -------------------------------------------------------------------------------- 1 | """ 2 | Thuật toán best first search 3 | """ 4 | from queue import PriorityQueue 5 | v = 14 6 | graph = [[] for _ in range(v)] 7 | 8 | def best_first_search(source, target, v): 9 | visited = [False]*v 10 | pq = PriorityQueue() 11 | pq.put((0, source)) 12 | while !pq.empty(): 13 | u = pq.get()[1] 14 | if u == target: 15 | break 16 | for v, c in graph[v]: 17 | if visited[v] == False: 18 | visited[v] = True 19 | pq.put((c, v)) 20 | 21 | def addedge(x, y, cost): 22 | graph[x].append((y, cost)) 23 | graph[y].append((x, cost)) 24 | 25 | 26 | addedge(0, 1, 3) 27 | addedge(0, 2, 6) 28 | addedge(0, 3, 5) 29 | addedge(1, 4, 9) 30 | addedge(1, 5, 8) 31 | addedge(2, 6, 12) 32 | addedge(2, 7, 14) 33 | addedge(3, 8, 7) 34 | addedge(8, 9, 5) 35 | addedge(8, 10, 6) 36 | addedge(9, 11, 1) 37 | addedge(9, 12, 10) 38 | addedge(9, 13, 2) 39 | 40 | source = 0 41 | target = 9 42 | best_first_search(source, target, v) 43 | -------------------------------------------------------------------------------- /search_algorithm/binary_search.py: -------------------------------------------------------------------------------- 1 | def binary_search(arr, l, r, x): 2 | while l <= r: 3 | mid = (l+r)//2 4 | if x > arr[mid]: 5 | l = mid + 1 6 | elif x < arr[mid]: 7 | r = mid - 1 8 | else: 9 | return mid 10 | return -1 11 | 12 | # Driver Code 13 | arr = [ 2, 3, 4, 10, 40 ] 14 | x = 10 15 | 16 | # Function call 17 | result = binary_search(arr, 0, len(arr)-1, x) 18 | 19 | if result != -1: 20 | print ("Element is present at index % d" % result) 21 | else: 22 | print ("Element is not present in array") 23 | -------------------------------------------------------------------------------- /search_algorithm/binary_search_least_comparision.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a sorted array of N distinct elements. Find a key in the array using least number of comparisons. (Do you think binary search is optimal to search a key in sorted array?) 3 | """ 4 | def binary_search(arr, l, r, key): 5 | while (r - l > 1): 6 | m = (l+r)//2 7 | if key > arr[m]: 8 | l = m 9 | else: 10 | r = m 11 | 12 | if arr[l] == key: 13 | return l 14 | elif arr[r] == key: 15 | return r 16 | else: 17 | return -1 18 | 19 | arr = [1,2] 20 | key = 2 21 | r = binary_search(arr, 0, len(arr) -1, key) 22 | print(r) 23 | -------------------------------------------------------------------------------- /search_algorithm/ceil_value.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tìm ceil value của x trong sorted array 3 | Cách 1: dùng linear search, sử lý edge case khi x bé hơn phần tử nhỏ nhất, tìm phần tử a[i] <= x <= a[i+1], hoặc không tìm thấy 4 | Cách 2: dùng binary search 5 | """ 6 | 7 | def ceil_value(arr, x, l, r): 8 | if arr[r] < x: 9 | return -1 10 | if arr[l] > x: 11 | return arr[l] 12 | 13 | while (r > l + 1): 14 | m = (l+r)//2 15 | if x < arr[m]: 16 | r = m 17 | else: 18 | l = m 19 | 20 | if arr[l] == x: 21 | return arr[l] 22 | else: 23 | return arr[r] 24 | 25 | def ceil_value_v2(arr, x, l, r): 26 | if x < arr[l]: 27 | return arr[l] 28 | if x > arr[r]: 29 | return -1 30 | 31 | m = (l+r)//2 32 | 33 | if arr[m]==x: 34 | return arr[m] 35 | 36 | if x < arr[m]: 37 | if m-1 >= l and x > arr[m-1]: 38 | return arr[m] 39 | else: 40 | return ceil_value_v2(arr, x, l, m-1) 41 | else: 42 | if m+1 <= r and x < arr[m+1]: 43 | return arr[m+1] 44 | else: 45 | return ceil_value_v2(arr, x, m+1, r) 46 | 47 | 48 | 49 | arr = [1, 2, 8, 10, 10, 12, 19] 50 | x = 0 51 | print(ceil_value(arr, x, 0, len(arr)-1)) 52 | print(ceil_value_v2(arr, x, 0, len(arr)-1)) 53 | -------------------------------------------------------------------------------- /search_algorithm/count_occurrence.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a sorted array with possible duplicate elements. Find number of occurrences of input ‘key’ in log N time. 3 | """ 4 | 5 | def find_right(arr, l, r, key): 6 | while r - l > 1: 7 | m = (l+r)//2 8 | if key < arr[m]: 9 | r = m 10 | else: 11 | l = m 12 | 13 | if arr[l] == key: 14 | return l 15 | elif arr[r] == key: 16 | return r 17 | else: 18 | return -1 19 | 20 | def find_left(arr, l, r, key): 21 | while r - l > 1: 22 | m = (l+r)//2 23 | if key <= arr[m]: 24 | r = m 25 | else: 26 | l =m 27 | 28 | if arr[l] == key: 29 | return l 30 | elif arr[r] == key: 31 | return r 32 | else: 33 | return -1 34 | 35 | arr = [1,1,2,3,3,4,5,5,7,9] 36 | key = 3 37 | 38 | l = find_left(arr, 0, len(arr)-1, key) 39 | r = find_right(arr, 0, len(arr)-1, key) 40 | print(r - l + 1) 41 | -------------------------------------------------------------------------------- /search_algorithm/count_one_in_sorted_binary_array.py: -------------------------------------------------------------------------------- 1 | """ 2 | Đếm số 1 trong 1 dãy số bao gồm 0 và 1 trong một chuỗi sắp xếp theo tứ tự không tăng 3 | - Dùng binary search 4 | """ 5 | def count_ones(arr, l, r): 6 | while(l < r): 7 | m = (l+r)//2 8 | 9 | if arr[m] - arr[m+1] == 1: 10 | return m+1 11 | 12 | if arr[m] == 0: 13 | return count_ones(arr, l, m-1) 14 | else: 15 | return count_ones(arr, m+1, r) 16 | 17 | arr=[1, 1, 0, 0, 0, 0, 0] 18 | print(count_ones(arr, 0, len(arr)-1)) 19 | -------------------------------------------------------------------------------- /search_algorithm/diff_adjacent_element_one.py: -------------------------------------------------------------------------------- 1 | """ 2 | tìm một phần tử x cho trước trong một mảng khi biết diff giữa 2 phần tử kế nhau luôn là 1 3 | Solution: 4 | Bắt đầu từ bên trái, so sánh phần tử hiện tại với x, mỗi lần jump một khoảng bằng diff của phần tử hiện tại vơi x, vì chúng ta biết rằng phần tử x phải ở vị trí ít nhất cách phần tử hiện tại là diff. 5 | """ 6 | def search(arr, x): 7 | i = 0 8 | while i < len(arr): 9 | if arr[i] == x: 10 | return i 11 | 12 | i = i + abs(arr[i] - x) 13 | return -1 14 | 15 | arr = [8 ,7, 6, 7, 6, 5, 4, 3, 2, 3, 4, 3 ] 16 | x = 3 17 | print(search(arr, x)) 18 | -------------------------------------------------------------------------------- /search_algorithm/element_appear_one_in_sorted_array.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tìm phần tử xuất hiện một lần duy nhất trong dãy đã sắp xếp 3 | """ 4 | 5 | 6 | def search(arr, low, high): 7 | if high < low: 8 | return 9 | if high==low: 10 | return arr[high] 11 | 12 | mid = (low + high)//2 13 | 14 | if mid % 2 ==0: 15 | if arr[mid] == arr[mid+1]: 16 | return search(arr, mid+2, high) 17 | else: 18 | return search(arr, low, mid) 19 | else: 20 | if arr[mid] == arr[mid -1]: 21 | return search(arr, mid+1, high) 22 | else: 23 | return search(arr, low, mid-1) 24 | 25 | 26 | arr = [1, 1, 2, 4, 4, 5, 5, 6, 6] 27 | 28 | # Function call 29 | result = search(arr, 0, len(arr)-1) 30 | print(result) 31 | -------------------------------------------------------------------------------- /search_algorithm/fibonacci_search.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a sorted array arr[] of size n and an element x to be searched in it. Return index of x if it is present in array else return -1. 3 | 4 | Fibonacci Search divides given array in unequal parts 5 | Binary Search uses division operator to divide range. Fibonacci Search doesn’t use /, but uses + and -. The division operator may be costly on some CPUs. 6 | Fibonacci Search examines relatively closer elements in subsequent steps. So when input array is big that cannot fit in CPU cache or even in RAM, Fibonacci Search can be useful. 7 | """ 8 | 9 | def fibonaccian_search(arr, x, n): 10 | fib2 = 0 11 | fib1 = 1 12 | fib0 = fib1 + fib2 13 | while fib0 < n: 14 | fib2 = fib1 15 | fib1 = fib0 16 | fib0 = fib1 + fib2 17 | 18 | offset = -1 19 | while fib0 > 1: 20 | i = min(offset + fib2, n - 1) 21 | if (x > arr[i]): 22 | fib0 = fib1 23 | fib1 = fib2 24 | fib2 = fib0 - fib1 25 | offset = i 26 | elif (x < arr[i]): 27 | fib0 = fib2 28 | fib1 = fib1 - fib2 29 | fib2 = fib0 - fib1 30 | else: 31 | return i 32 | 33 | if arr[offset + 1]== x: 34 | return offset + 1 35 | 36 | return -1 37 | # Driver Code 38 | arr = [10] 39 | n = len(arr) 40 | x = 10 41 | print("Found at index:", fibonaccian_search(arr, x, n)) 42 | -------------------------------------------------------------------------------- /search_algorithm/find_element.py: -------------------------------------------------------------------------------- 1 | """Tìm phần tử lớn hơn các phần tử phía trước và nhỏ hơn các phần tử phía sau nó 2 | https://www.geeksforgeeks.org/find-the-element-before-which-all-the-elements-are-smaller-than-it-and-after-which-all-are-greater-than-it/ 3 | Solution: 4 | O(n) 5 | dùng mảng tạo leftmax lưu giá trị lớn nhất từ đầu đến vị trí thứ i-1, và mảng tạm rightmin lưu giá trị nhỏ nhất từ cuối về trước i - 1, 6 | sau đó tại mỗi vị trí i trong mảng, kiểm tra xem nó có thỏa điều kiện yêu cầu hay không 7 | """ 8 | def find_element(arr): 9 | left_max = [0]*len(arr) 10 | left_max[0] = float('-inf') 11 | 12 | right_min = [0]*len(arr) 13 | right_min[-1] = float('+inf') 14 | 15 | 16 | for i in range(1, len(arr)): 17 | left_max[i] = max(left_max[i-1], arr[i-1]) 18 | 19 | for i in range(len(arr)-2, -1, -1): 20 | right_min[i] = min(right_min[i+1], arr[i+1]) 21 | 22 | for i in range(1, len(arr)-1): 23 | if left_max[i] < arr[i] < right_min[i]: 24 | return arr[i] 25 | 26 | arr = [5, 1, 4, 3, 6, 8, 10, 7, 9] 27 | 28 | rs = find_element(arr) 29 | print(rs) 30 | 31 | -------------------------------------------------------------------------------- /search_algorithm/find_first_repeating_element.py: -------------------------------------------------------------------------------- 1 | """ 2 | Cho một dãy số, tìm phần tử lặp lại mà xuất hiện sớm nhất trong dãy? 3 | Scan từ phải qua trái, cập nhật minimun index khi mà phần tử hiện tại đã được duyệt qua 4 | """ 5 | 6 | def printFirstRepeating(arr, n): 7 | min_index = -1 8 | 9 | myset = dict() 10 | 11 | for i in range(len(arr)-1, -1, -1): 12 | if arr[i] in myset: 13 | min_index = i 14 | else: 15 | myset[arr[i]] = 1 16 | 17 | return min_index 18 | 19 | 20 | 21 | # Driver Code 22 | arr = [10, 5, 3, 4, 3, 5, 6] 23 | 24 | n = len(arr) 25 | print(printFirstRepeating(arr, n)) 26 | -------------------------------------------------------------------------------- /search_algorithm/find_k_closest_elements.py: -------------------------------------------------------------------------------- 1 | """ 2 | Cho dãy đã sorted, số k và x, trả về k số gần với x nhất 3 | Tìm crossover point bằng binary search, crossover point là vị trí mà tại đó phần tử phía trước nhỏ hơn và phía sau lớn hơn 4 | Từ điểm crossover lấy k phần tử nhỏ nhất về bên 2 đầu. 5 | """ 6 | 7 | def binary_search(arr, x, l, r): 8 | m = (l+r)//2 9 | 10 | if l == r -1 and arr[l] <= arr[m] < arr[r]: 11 | return l 12 | 13 | if arr[m] <= x: 14 | return binary_search(arr, x, m, r) 15 | else: 16 | return binary_search(arr, x, l, m) 17 | 18 | 19 | def findClosestElements(arr, k, x): 20 | """ 21 | :type arr: List[int] 22 | :type k: int 23 | :type x: int 24 | :rtype: List[int] 25 | """ 26 | 27 | if x <= arr[0]: 28 | return arr[:k] 29 | 30 | if x >= arr[-1]: 31 | return arr[-k:] 32 | 33 | l = binary_search(arr, x, 0, len(arr)-1) 34 | 35 | r = l + 1 36 | 37 | count = 0 38 | while count < k and l >= 0 and r < len(arr): 39 | if x - arr[l] <= arr[r] - x: 40 | l = l - 1 41 | elif x -arr[l] > arr[r] - x: 42 | r = r + 1 43 | 44 | count = count + 1 45 | 46 | while count < k and l >= 0: 47 | l = l -1 48 | count += 1 49 | 50 | while count < k and r < len(arr): 51 | r = r + 1 52 | count += 1 53 | 54 | return arr[l+1:r] 55 | 56 | arr =[12, 16, 22, 30, 35, 39, 42,45, 48, 50, 53, 55, 56] 57 | x = 35 58 | k = 4 59 | 60 | print(findClosestElements(arr, k, x)) 61 | -------------------------------------------------------------------------------- /search_algorithm/find_missing_and_repeating_number.py: -------------------------------------------------------------------------------- 1 | """ 2 | Cho n số có giá trị từ 1-n, trong đó có một số bị missing và 1 số xuất hiện 2 lần. 3 | Tìm 2 số đó 4 | Cách 1: sort và tìm missing + repeating 5 | """ 6 | 7 | def find_two_number(arr): 8 | arr = sorted(arr) 9 | for i in range(len(arr)-1): 10 | if arr[i+1] - arr[i] 11 | 12 | arr = [7, 3, 4, 5, 5, 6, 2] 13 | print(find_two_number(arr)) 14 | -------------------------------------------------------------------------------- /search_algorithm/find_pair_sum_closest_x.py: -------------------------------------------------------------------------------- 1 | """ 2 | cho một dãy được sắp sếp, tìm 2 số sao cho tổng gần x cho trước nhất 3 | - 4 | """ 5 | def closest_pair(arr, x): 6 | l, r = 0, len(arr) - 1 7 | diff = 99999 8 | 9 | while l < r: 10 | if abs(arr[l] + arr[r] - x) < diff: 11 | rs_l = l 12 | rs_r = r 13 | diff = abs(arr[l] + arr[r] - x) 14 | 15 | if (arr[l] + arr[r] > x): 16 | r -= 1 17 | else: 18 | l += 1 19 | 20 | return arr[rs_l], arr[rs_r] 21 | arr = [10, 22, 28, 29, 30, 40] 22 | x = 54 23 | print(closest_pair(arr, x)) 24 | -------------------------------------------------------------------------------- /search_algorithm/find_pair_with_given_difference.py: -------------------------------------------------------------------------------- 1 | """ 2 | Cho một dãy chưa được sắp sếp, và số diff 3 | tìm một cặp sao cho difference của 2 số bằng số diff 4 | """ 5 | 6 | def find_pair(arr, diff): 7 | d = set() 8 | for i in range(len(arr)): 9 | x1 = diff + arr[i] 10 | x2 = arr[i] - diff 11 | 12 | if x1 not in d: 13 | d.add(arr[i]) 14 | else: 15 | return arr[i], x1 16 | 17 | if x2 not in d: 18 | d.add(arr[i]) 19 | else: 20 | return arr[i], x2 21 | return -1 22 | 23 | arr = [1, 8, 30, 40, 100] 24 | diff = 10 25 | 26 | print(find_pair(arr, diff)) 27 | -------------------------------------------------------------------------------- /search_algorithm/fixed_point.py: -------------------------------------------------------------------------------- 1 | """ 2 | Cho dãy tăng dần, tìm vị trí mà a[i] = i 3 | """ 4 | def binary_search(arr, l, r): 5 | m = (l+r)//2 6 | if arr[m] == m: 7 | return m 8 | 9 | if m < arr[m]: 10 | return binary_search(arr, 0, m -1) 11 | else: 12 | return binary_search(arr, m + 1, r) 13 | 14 | arr = [-10, -1, 0, 3, 10, 11, 30, 50, 100] 15 | print(binary_search(arr, 0, len(arr)-1)) 16 | -------------------------------------------------------------------------------- /search_algorithm/floor_value.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given an array of N distinct integers, find floor value of input 'key'. Say, A = {-1, 2, 3, 5, 6, 8, 9, 10} and key = 7, we should return 6 as outcome. 3 | """ 4 | 5 | def floor(arr, l, r, key): 6 | while r - l > 1: 7 | m = (l+r)//2 8 | if arr[m] <= key: 9 | l = m 10 | else: 11 | r = m 12 | 13 | if arr[r] == key: 14 | return arr[r] 15 | else: 16 | return arr[l] 17 | 18 | arr = [1,2,5,6,7,9,10] 19 | key = 10 20 | r = floor(arr, 0, len(arr)-1, key) 21 | print(r) 22 | -------------------------------------------------------------------------------- /search_algorithm/floor_value_in_sorted_array.py: -------------------------------------------------------------------------------- 1 | """ 2 | Cho một dãy số đã được sắp sếp, và số x. tìm số nằm trong dãy sao cho số đó <= x 3 | Solution: 4 | dùng binary search 5 | """ 6 | def floor_value(arr, low, high, x): 7 | if x < arr[0]: 8 | return -1 9 | if x > arr[-1]: 10 | return arr[-1] 11 | 12 | while (low < high): 13 | m = (low + high)//2 14 | if arr[m] == x: 15 | return arr[m] 16 | if arr[m] < x < arr[m+1]: 17 | return arr[m] 18 | 19 | elif arr[m] < x: 20 | low = m 21 | else: 22 | high = m 23 | 24 | 25 | arr = [1, 2, 4, 6, 10, 12, 14] 26 | x = 13 27 | rs = floor_value(arr, 0, len(arr) - 1, x) 28 | print(rs) 29 | -------------------------------------------------------------------------------- /search_algorithm/intersection_of_three_sorted_array.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tìm intersection của 3 dãy số đã sắp xếp 3 | Dùng thủ tực merge producer 4 | """ 5 | def find_common(arr1, arr2, arr3): 6 | i, j, z = 0, 0, 0 7 | rs = set() 8 | while(i < len(arr1) and j < len(arr2) and z < len(arr3)): 9 | if (arr1[i]==arr2[j]==arr3[z]): 10 | rs.add(arr1[i]) 11 | i += 1 12 | j += 1 13 | z += 1 14 | elif arr1[i] < arr2[j]: 15 | i += 1 16 | elif arr2[j] < arr3[z]: 17 | j += 1 18 | else: 19 | z += 1 20 | 21 | return rs 22 | 23 | ar1 = [1, 5, 10, 20, 40, 80] 24 | ar2 = [6, 7, 20, 80, 100] 25 | ar3 = [3, 4, 15, 20, 30, 70, 80, 120] 26 | 27 | print(find_common(ar1, ar2, ar3)) 28 | -------------------------------------------------------------------------------- /search_algorithm/k_largest_elements.py: -------------------------------------------------------------------------------- 1 | """ 2 | tìm k phần tử lớn nhất 3 | cách 1: 4 | modify bubble sort để chỉ cần chạy k lần 5 | cách 2: sử dụng tmp_arr lưu lại k phần từ đầu, 6 | - tính min của tmp_arr 7 | - so sánh phần tử từ k đến n với min 8 | - nếu phần từ i lớn hơn min, thay arr[i] vào vị trí min 9 | cách 3: 10 | - sort array 11 | - lấy k phần tử lớn nhất 12 | """ 13 | 14 | def bubble_k_time(arr, k): 15 | for i in range(k): 16 | for j in range(len(arr) - i - 1): 17 | if arr[j] > arr[j+1]: 18 | arr[j], arr[j+1] = arr[j+1], arr[j] 19 | 20 | return arr[-k:] 21 | 22 | def temporary_arr(arr, k): 23 | temp_arr = arr[:k] 24 | min_idx = temp_arr.index(min(temp_arr)) 25 | 26 | for i in range(k, len(arr)): 27 | if arr[i] > temp_arr[min_idx]: 28 | temp_arr[min_idx] = arr[i] 29 | min_idx = temp_arr.index(min(temp_arr)) 30 | 31 | return temp_arr 32 | 33 | 34 | 35 | arr = [1, 23, 12, 9, 30, 2, 50] 36 | k = 3 37 | print(bubble_k_time(arr, k)) 38 | print(temporary_arr(arr, k)) 39 | -------------------------------------------------------------------------------- /search_algorithm/largest_three_elements.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tìm 3 phần tử lớn nhất trong dãy 3 | """ 4 | def three_largest(arr): 5 | first=second=third = -999999 6 | for x in arr: 7 | if (x > first): 8 | third = second 9 | second=first 10 | first = x 11 | elif (x > second): 12 | third = second 13 | second = x 14 | elif (x > third): 15 | third = x 16 | 17 | return first, second, third 18 | 19 | arr = [12, 13, 1, 10, 34, 1] 20 | 21 | print(three_largest(arr)) 22 | -------------------------------------------------------------------------------- /search_algorithm/majority_elemnents.py: -------------------------------------------------------------------------------- 1 | """ 2 | cho dãy số có kích thước là n, tìm phần tử xuất hiện nhiều hơn n//3 lần, 3 | Cách 1: 4 | Boyer-Moore-Majority-Vote-algorithm 5 | ý tưởng là nểu phần tử đó là majority thì khi cancel những phần tử khác thì sẽ còn lại chính nó 6 | """ 7 | def bm(nums): 8 | count1, count2, cand1, cand2 = 0, 0, None, None 9 | for n in nums: 10 | if n == cand1: 11 | count1 += 1 12 | elif n == cand2: 13 | count2 += 1 14 | elif count1 == 0: 15 | cand1 = n 16 | count1 = 1 17 | elif count2 == 0: 18 | cand2 = n 19 | count2 = 1 20 | else: 21 | count1 -= 1 22 | count2 -= 1 23 | 24 | return [x for x in (cand1, cand2) if nums.count(x) > len(nums)//3] 25 | 26 | arr = [3,2,3] 27 | print(bm(arr)) 28 | -------------------------------------------------------------------------------- /search_algorithm/make_array_elements_equal_minimum_cost.py: -------------------------------------------------------------------------------- 1 | """ 2 | Cho một dãy, cần làm cho các số trong dãy bằng nhau với minimum cost, cost được tính bằng tổng abs(x-y) 3 | https://www.geeksforgeeks.org/make-array-elements-equal-minimum-cost/ 4 | Solution: 5 | Hàm cost có dạng unimodal function, kiểu U-shape, Do đó có thể dùng ternary search để tìm maximum or minimum 6 | """ 7 | def cost(arr, x): 8 | c = 0 9 | for e in arr: 10 | c += abs(x- e) 11 | 12 | return c 13 | 14 | def minimum_cost(arr): 15 | high, low = max(arr), min(arr) 16 | while(high - low > 2): 17 | m1 = low + (high-low)//3 18 | m2 = high - (high-low)//3 19 | 20 | cost1 = cost(arr, m1) 21 | cost2 = cost(arr, m2) 22 | 23 | 24 | if cost1 < cost2: 25 | high = m2 26 | else: 27 | low = m1 28 | 29 | print(high, low) 30 | 31 | return cost(arr, (low+high)//2) 32 | 33 | arr = [1, 100, 101] 34 | 35 | print(minimum_cost(arr)) 36 | -------------------------------------------------------------------------------- /search_algorithm/maximun_in_zizag_array.py: -------------------------------------------------------------------------------- 1 | """Tìm phần tử lớn nhất trong dãy số đầu tiên là tăng sau đó thì giảm dần 2 | """ 3 | def binary_search(arr, l, r): 4 | if l == r: 5 | return arr[l] 6 | 7 | if l == r -1: 8 | return max(arr[l], arr[r]) 9 | 10 | m = (l+r)//2 11 | 12 | if arr[m-1] < arr[m] > arr[m+1]: 13 | return arr[m] 14 | 15 | if arr[m] > arr[m+1]: 16 | return binary_search(arr, l, m) 17 | else: 18 | return binary_search(arr, m, r) 19 | 20 | arr = [1, 3, 50, 10, 9, 7, 6] 21 | print(binary_search(arr, 0, len(arr)-1)) 22 | -------------------------------------------------------------------------------- /search_algorithm/median_of_two_sorted_array.py: -------------------------------------------------------------------------------- 1 | ar1 = [1, 12, 15, 26, 38] 2 | ar2 = [2, 13, 17, 30, 45] 3 | 4 | arr = [0]*len(ar1)*2 5 | 6 | def merge(): 7 | i, j, k = 0, 0, 0 8 | while i < len(ar1) and j < len(ar2): 9 | print(i, j, k) 10 | if ar1[i] < ar2[j]: 11 | arr[k] = ar1[i] 12 | i += 1 13 | else: 14 | arr[k] = ar2[j] 15 | j += 1 16 | k += 1 17 | 18 | while i < len(ar1): 19 | arr[k] = ar1[i] 20 | k += 1 21 | i += 1 22 | 23 | while j < len(ar2): 24 | arr[k] = ar2[j] 25 | k += 1 26 | j += 1 27 | 28 | -------------------------------------------------------------------------------- /search_algorithm/minimum_in_sorted_rotated_array.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tìm phần tử nhỏ nhất trong một dãy số được sắp xếp bị xoay ở vị trí chưa biết. 3 | Dãy số có thể chứa các phần tử bị lặp 4 | """ 5 | 6 | def binary_search(arr): 7 | l, r = 0, len(arr) - 1 8 | while l < r: 9 | m = (l+r)//2 10 | if arr[m] > arr[r]: 11 | l = m + 1 12 | elif arr[m] < arr[r]: 13 | r = m 14 | else: 15 | r -= 1 16 | 17 | return arr[l] 18 | 19 | arr = [2,2,2,0,1] 20 | print(binary_search(arr)) 21 | -------------------------------------------------------------------------------- /search_algorithm/minimum_required_time.py: -------------------------------------------------------------------------------- 1 | """ 2 | có n máy, mỗi máy cần số ngày khác nhau để tao ra một sản phẩm, tìm số ngày ít nhất để tạo ra m sản phẩm khi cả n máy chạy đồng thời 3 | https://www.geeksforgeeks.org/minimum-time-required-produce-m-items/ 4 | """ 5 | 6 | import math 7 | 8 | def find_items(machines, days): 9 | items = 0 10 | for m in machines: 11 | items += days//m 12 | 13 | return items 14 | 15 | def min_time(machines, goal): 16 | min_day = goal*math.floor(min(machines)/len(machines)) 17 | max_day = goal*math.ceil(max(machines)/len(machines)) 18 | 19 | while (min_day < max_day): 20 | mid = (min_day + max_day)//2 21 | 22 | items = find_items(machines, mid) 23 | if items < goal: 24 | min_day = mid + 1 25 | else: 26 | max_day = mid 27 | 28 | return max_day 29 | 30 | 31 | arr = [2, 3] 32 | m = 5 33 | rs = min_time(arr, m) 34 | print(rs) 35 | -------------------------------------------------------------------------------- /search_algorithm/minimum_rotated_array.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given a sorted array of distinct elements, and the array is rotated at an unknown position. Find minimum element in the array. 3 | """ 4 | 5 | def minimun(arr, l, r): 6 | while r - l > 1: 7 | m = (l+r)//2 8 | if arr[m] > arr[r]: 9 | l = m 10 | elif arr[m] < arr[l]: 11 | r = m 12 | print(arr[l:r]) 13 | 14 | return arr[r] 15 | 16 | arr = [4,6,8,1,2,3] 17 | r = minimun(arr, 0, len(arr)-1) 18 | print(r) 19 | -------------------------------------------------------------------------------- /search_algorithm/minimun_comparision_min_max.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tìm min và max sử dụng ít so sánh nhất ? 3 | chia dãy thì 2 nữa left và right, đệ quy tìm min, max trên 2 nữa đó. 4 | """ 5 | 6 | def min_max(arr, l, r): 7 | if l == r: 8 | return arr[l], arr[r] 9 | elif l == r - 1: 10 | if arr[l] > arr[r]: 11 | return arr[r], arr[l] 12 | else: 13 | return arr[l], arr[r] 14 | else: 15 | m = (l+r)//2 16 | left_min, left_max = min_max(arr, l, m) 17 | right_min, right_max = min_max(arr, m + 1, r) 18 | 19 | return min(left_min, right_min), max(left_max, right_max) 20 | 21 | arr = [2,3,1,6,0,0,9] 22 | 23 | print(min_max(arr, 0, len(arr)-1)) 24 | 25 | -------------------------------------------------------------------------------- /search_algorithm/quick_selection.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tìm phần tử nhỏ nhất thứ k trong dãy chưa được sắp xếp. 3 | Sử dụng tư tưởng giống như quicksort 4 | """ 5 | 6 | -------------------------------------------------------------------------------- /search_algorithm/recursive_linear_search.py: -------------------------------------------------------------------------------- 1 | def rec_search(arr, l, r, key): 2 | if arr[l] == key: 3 | return l 4 | elif arr[r] == key: 5 | return r 6 | else: 7 | rec_search(arr, l+1, r-1, key) 8 | 9 | return -1 10 | 11 | arr = [12, 34, 54, 2, 3] 12 | n = len(arr) 13 | x = 3 14 | r = rec_search(arr, 0, n-1, x) 15 | print(r) 16 | 17 | -------------------------------------------------------------------------------- /search_algorithm/recursive_substring_search.py: -------------------------------------------------------------------------------- 1 | def match(text, pat, text_index, pat_index): 2 | if pat_index == len(pat): 3 | return 1 4 | 5 | if text_index == len(text): 6 | return 0 7 | 8 | if text[text_index] == pat[pat_index]: 9 | return match(text , pat, text_index + 1, pat_index+1) 10 | 11 | return 0 12 | 13 | 14 | def contains(text, pat, text_index, pat_index): 15 | if len(text) == text_index: 16 | return 0 17 | 18 | if text[text_index] == pat[pat_index]: 19 | if match(text, pat, text_index+1, pat_index+1): 20 | return 1 21 | return contains(text, pat, text_index+1, pat_index) 22 | 23 | print(contains("geeksforgeeks", "geeks", 0, 0)) 24 | print(contains("geeksforgeeks", "geeksquiz", 0, 0)) 25 | print(contains("geeksquizgeeks", "quiz", 0, 0)) 26 | -------------------------------------------------------------------------------- /search_algorithm/search_in_rotated_sorted_array.py: -------------------------------------------------------------------------------- 1 | def find_pivot(arr, l, r): 2 | while (l < r - 1): 3 | m = (l+r)//2 4 | if arr[m] > arr[r]: 5 | l = m 6 | if arr[m] < arr[l]: 7 | r = m 8 | return l 9 | 10 | def binary_search(arr, l, r, key): 11 | while(l <= r): 12 | m = (l+r)//2 13 | if arr[m] == key: 14 | return m 15 | if arr[m] < key: 16 | l = m + 1 17 | elif arr[m] > key: 18 | r = m - 1 19 | 20 | return -1 21 | 22 | arr1 = [5, 6, 7, 8, 9, 10, 1, 2, 3] 23 | n = len(arr1) 24 | key = 0 25 | 26 | pivot = find_pivot(arr1, 0, n-1) 27 | left = binary_search(arr1, 0, pivot, key) 28 | right = binary_search(arr1, pivot+1, n-1, key) 29 | print(left, right) 30 | -------------------------------------------------------------------------------- /search_algorithm/search_in_rotated_sorted_array_v2.py: -------------------------------------------------------------------------------- 1 | def search(arr, l, r, key): 2 | while l <= r: 3 | m = (l+r)//2 4 | if arr[m] == key: 5 | return m 6 | 7 | # arr[l..m] is sorted 8 | if arr[m] > arr[r]: 9 | if arr[l] <= key <= arr[m]: 10 | return search(arr, l, m - 1, key) 11 | return search(arr, m + 1, r, key) 12 | 13 | if arr[m] <= key <= arr[r] : 14 | return search(arr, m + 1, r, key) 15 | return search(arr, l, m - 1, key) 16 | return -1 17 | 18 | arr = [4, 5, 6, 7, 8, 9, 1, 2, 3] 19 | key = 4 20 | i = search(arr, 0, len(arr)-1, key) 21 | if i != -1: 22 | print ("Index: % d"% i) 23 | else: 24 | print ("Key not found") 25 | -------------------------------------------------------------------------------- /search_algorithm/smallest_and_second_smallest.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tìm phần tử nhỏ nhất và nhỏ nhì ? 3 | cách 1: 4 | sort rồi lấy 2 phần tử đầu 5 | cách 2: 6 | 1 vòng for tìm phần tử nhỏ nhất x 7 | 1 vòng for nữa tìm phần tử nhỏ nhất những lớn hơn x 8 | cách 3: 9 | 1 vòng for duy nhất, x luôn là phần từ nhỏ nhất, y 10 | """ 11 | 12 | def two_smallest(arr): 13 | x, y = 9999, 9999 14 | for i in arr: 15 | if i < x: 16 | y = x 17 | x = i 18 | elif i < y: 19 | y = i 20 | 21 | return x, y 22 | 23 | arr = [12, 13, 1, 10, 34, 2] 24 | 25 | print(two_smallest(arr)) 26 | -------------------------------------------------------------------------------- /search_algorithm/smallest_difference_triplet.py: -------------------------------------------------------------------------------- 1 | """ 2 | Cho 3 dãy, tìm bộ 3 số x, y, z sao cho mỗi số đến từ 3 dãy và có max(x, y, z) - min(x, y, z) nhỏ nhất 3 | Solution: 4 | Sort 3 dãy 5 | rồi dùng 3 pointers 6 | """ 7 | def smallest_diff_triplet(arr1, arr2, arr3): 8 | arr1.sort() 9 | arr2.sort() 10 | arr3.sort() 11 | 12 | res_min, res_max, res_mid = 0, 0, 0 13 | 14 | i, j, k = 0, 0, 0 15 | diff = 99999 16 | 17 | while (i < len(arr1) and j < len(arr2) and k < len(arr3)): 18 | s = arr1[i] + arr2[j] + arr3[k] 19 | maximum = max(arr1[i], arr2[j], arr3[k]) 20 | minimum = min(arr1[i], arr2[j], arr3[k]) 21 | 22 | if arr1[i] == minimum: 23 | i += 1 24 | elif arr2[j] == minimum: 25 | j += 1 26 | else: 27 | k += 1 28 | 29 | if diff > (maximum - minimum): 30 | diff = maximum - minimum 31 | res_max = maximum 32 | res_min = minimum 33 | res_mid = s - (maximum + minimum) 34 | 35 | return res_max, res_mid, res_min 36 | 37 | arr1 = [5, 2, 8] 38 | arr2 = [10, 7, 12] 39 | arr3 = [9, 14, 6] 40 | print(smallest_diff_triplet(arr1, arr2, arr3)) 41 | -------------------------------------------------------------------------------- /search_algorithm/sublist_search.py: -------------------------------------------------------------------------------- 1 | # Given two linked lists, the task is to check whether the first list is present in 2nd list or not. 2 | 3 | class Node: 4 | def __init__(self, value): 5 | self.value = value 6 | self.next = None 7 | 8 | 9 | def find_list(first, second): 10 | 11 | while second: 12 | ptr2 = second 13 | ptr1 = first 14 | 15 | while ptr1: 16 | if not ptr2: 17 | return False 18 | elif ptr1.value == ptr2.value: 19 | ptr1 = ptr1.next 20 | ptr2 = ptr2.next 21 | else: 22 | break 23 | 24 | if not ptr1: 25 | return True 26 | 27 | second = second.next 28 | 29 | return False 30 | 31 | node_a = Node(1) 32 | node_a.next = Node(2) 33 | node_a.next.next = Node(3) 34 | node_a.next.next.next = Node(4) 35 | 36 | node_b = Node(1) 37 | node_b.next = Node(2) 38 | node_b.next.next = Node(1) 39 | node_b.next.next.next = Node(2) 40 | node_b.next.next.next.next = Node(5) 41 | node_b.next.next.next.next.next = Node(4) 42 | 43 | r = find_list(node_a, node_b) 44 | print(r) 45 | -------------------------------------------------------------------------------- /search_algorithm/sum_closest_zero.py: -------------------------------------------------------------------------------- 1 | def min_abs_pair(arr, l , r): 2 | min_s = abs(arr[0] + arr[-1]) 3 | res_l, res_r = l, r 4 | 5 | while l < r: 6 | s = abs(arr[l] + arr[r]) 7 | if s < min_s: 8 | min_s = s 9 | res_l = l 10 | res_r = r 11 | 12 | if s > 0: 13 | r -= 1 14 | else: 15 | l += 1 16 | 17 | return arr[res_l], arr[res_r] 18 | 19 | arr = [1, 60, -10, 70, -80, 85] 20 | arr = sorted(arr) 21 | print(min_abs_pair(arr, 0, len(arr)-1)) 22 | -------------------------------------------------------------------------------- /search_algorithm/sum_closest_zero_v2.py: -------------------------------------------------------------------------------- 1 | """ 2 | tìm tổng 2 số gần bằng zero nhất ? 3 | sau khi sort dãy số arr theo abs, 4 | tổng 2 số liên tiếp nhỏ nhất chính là 2 số cần tìm tại vì sau khi sort theo abs xong, giả sử số abs(a[0] + a[1]) sẽ luôn nhỏ hơn abs(a[0]) + a[2]), abs(a[0] + a[3]),.. do đó tại mỗi i chỉ cần xét 2 số liên tiếp 5 | """ 6 | def closest_zero(arr): 7 | min_s = abs(arr[0] + arr[1]) 8 | res_l, res_r = 0, 1 9 | 10 | for i in range(1, len(arr)): 11 | s = abs(arr[i] + arr[i-1]) 12 | if s < min_s: 13 | min_s = s 14 | res_l = i-1 15 | res_r = i 16 | 17 | return arr[res_l], arr[res_r] 18 | 19 | arr = [-1, 1, 60, -10, 70, -80, 85] 20 | arr = sorted(arr, key=lambda x: abs(x)) 21 | 22 | print(closest_zero(arr)) 23 | -------------------------------------------------------------------------------- /search_algorithm/sum_of_consecutive_numbers.py: -------------------------------------------------------------------------------- 1 | """ 2 | Cho số N, Tìm tất các cá khả năng của tổng d số liên tiếp bằng N 3 | https://www.geeksforgeeks.org/print-all-possible-consecutive-numbers-with-sum-n/ 4 | 5 | """ 6 | 7 | def consecutive_sum(N): 8 | count = 0 9 | s = 1 10 | end = 1 11 | start = 1 12 | 13 | while start <= N//2: 14 | if s < N: 15 | end += 1 16 | s += end 17 | 18 | elif s > N: 19 | s -= start 20 | start += 1 21 | else: 22 | print(list(range(start, end+1))) 23 | s-= start 24 | start += 1 25 | 26 | N = 15 27 | consecutive_sum(N) 28 | -------------------------------------------------------------------------------- /search_algorithm/three_closest_elements.py: -------------------------------------------------------------------------------- 1 | """ 2 | cho 3 dãy số đã được sắp sếp A, B, C, tìm kiếm 3 phần tử i, j, k, mỗi phần tử từ mỗi dãy số, sao cho max(abs(A[i]-B[j]), abs(B[j]-C[k]), abs(C[k]-A[i])) nhỏ nhất 3 | Solution: 4 | max(abs(A[i]-B[j]), abs(B[j]-C[k]), abs(C[k]-A[i])) chính là khoảng cách giữa phần tử nhỏ nhất và lớn nhất. 5 | """ 6 | def find_closest(A, B, C): 7 | diff = 9999 8 | rs_i, rs_j, rs_k = 0, 0, 0 9 | i, j, k = 0, 0, 0 10 | 11 | while (i < len(A) and j < len(B) and k < len(C)): 12 | minimum = min(A[i], min(B[j], C[k])) 13 | maximum = max(A[i], max(B[j], C[k])) 14 | 15 | if maximum - minimum < diff: 16 | diff = maximum - minimum 17 | rs_i, rs_j, rs_k = i, j, k 18 | 19 | if diff == 0: 20 | break 21 | 22 | if A[i] == minimum: 23 | i += 1 24 | elif B[j] == minimum: 25 | j += 1 26 | else: 27 | k += 1 28 | 29 | return A[rs_i], B[rs_j], C[rs_k] 30 | 31 | A = [1, 4, 10] 32 | B = [2, 15, 20] 33 | C = [10, 12] 34 | 35 | rs = find_closest(A,B,C) 36 | print(rs) 37 | 38 | -------------------------------------------------------------------------------- /search_algorithm/triplets_sum_to_zero.py: -------------------------------------------------------------------------------- 1 | """ 2 | Cho dãy số, tìm tổng 3 số bằng 0 3 | https://www.geeksforgeeks.org/find-triplets-array-whose-sum-equal-zero/ 4 | Solution:Dựa trên bài toán tìm tổng 2 số bằng 0 5 | """ 6 | 7 | def zero_triplet(arr): 8 | arr.sort() 9 | 10 | for i in range(0, len(arr) -1): 11 | l = i + 1 12 | r = len(arr) - 1 13 | x = arr[i] 14 | while (l < r): 15 | if (x + arr[l] + arr[r]==0): 16 | l += 1 17 | r -= 1 18 | print(x, arr[l], arr[r]) 19 | 20 | if (x + arr[l] + arr[r] < 0): 21 | l += 1 22 | else: 23 | r -= 1 24 | 25 | 26 | arr = [0, -1, 2, -3, 1] 27 | zero_triplet(arr) 28 | -------------------------------------------------------------------------------- /sort_algorithm/adjacent_swaps.py: -------------------------------------------------------------------------------- 1 | """ 2 | https://www.geeksforgeeks.org/number-swaps-sort-adjacent-swapping-allowed/ 3 | """ 4 | def merge(arr, tmp, left, mid, right): 5 | i = left 6 | j = mid 7 | k = left 8 | 9 | inv_count = 0 10 | while i <= mid -1 and j <= right: 11 | if arr[i] <= arr[j]: 12 | tmp[k] = arr[i] 13 | k+=1 14 | i+=1 15 | else: 16 | tmp[k] = arr[j] 17 | k+=1 18 | j+=1 19 | 20 | inv_count += (mid - i) 21 | 22 | while i <= mid - 1: 23 | tmp[k] = arr[i] 24 | k += 1 25 | i += 1 26 | 27 | while j <= right: 28 | tmp[k] = arr[j] 29 | k += 1 30 | j += 1 31 | 32 | 33 | for i in range(left, right+1): 34 | arr[i] = tmp[i] 35 | 36 | return inv_count 37 | 38 | def merge_sort(arr, tmp, left, right): 39 | inv_count = 0 40 | if left < right: 41 | mid = (left + right)//2 42 | 43 | inv_count += merge_sort(arr, tmp, left, mid) 44 | inv_count += merge_sort(arr, tmp, mid+1, right) 45 | inv_count += merge(arr, tmp, left, mid+1, right) 46 | 47 | return inv_count 48 | 49 | def inv_count(arr, n): 50 | tmp = [0]*n 51 | 52 | return merge_sort(arr, tmp, 0, n -1) 53 | 54 | arr = [1, 20, 6, 4, 5] 55 | print(inv_count(arr, len(arr))) 56 | 57 | -------------------------------------------------------------------------------- /sort_algorithm/binary_insertion_sort.py: -------------------------------------------------------------------------------- 1 | def binary_search(arr, val, start, end): 2 | if start==end: 3 | if arr[start] > val: 4 | return start 5 | else: 6 | return start + 1 7 | 8 | if start > end: 9 | return start 10 | 11 | mid = (start + end)//2 12 | if arr[mid] < val: 13 | return binary_search(arr, val, mid+1, end) 14 | elif arr[mid] > val: 15 | return binary_search(arr, val, start, mid - 1) 16 | else: 17 | return mid 18 | 19 | def insertion_sort(arr): 20 | for i in range(1, len(arr)): 21 | val = arr[i] 22 | j = binary_search(arr, val, 0, i -1) 23 | arr = arr[:j]+[val] + arr[j:i] + arr[i+1:] 24 | 25 | return arr 26 | 27 | print(insertion_sort([37, 23, 0, 31, 22, 17, 12, 72, 31, 46, 100, 88, 54])) 28 | 29 | 30 | -------------------------------------------------------------------------------- /sort_algorithm/bitonic_sort.py: -------------------------------------------------------------------------------- 1 | def compAndSwap(a, i, j, dire): 2 | if (dire==1 and a[i] > a[j]) or (dire==0 and a[i] < a[j]): 3 | a[i],a[j] = a[j],a[i] 4 | 5 | 6 | def bitonicMerge(a, low, cnt, dire): 7 | if cnt > 1: 8 | k = cnt//2 9 | for i in range(low , low+k): 10 | compAndSwap(a, i, i+k, dire) 11 | bitonicMerge(a, low, k, dire) 12 | bitonicMerge(a, low+k, k, dire) 13 | 14 | def bitonicSort(a, low, cnt,dire): 15 | if cnt > 1: 16 | k = cnt//2 17 | bitonicSort(a, low, k, 1) 18 | bitonicSort(a, low+k, k, 0) 19 | bitonicMerge(a, low, cnt, dire) 20 | 21 | 22 | def sort(a,N, up): 23 | bitonicSort(a,0, N, up) 24 | 25 | # Driver code to test above 26 | a = [3, 7, 4, 8, 6, 2, 1, 5] 27 | n = len(a) 28 | up = 1 29 | 30 | sort(a, n, up) 31 | print(a) 32 | -------------------------------------------------------------------------------- /sort_algorithm/bubble_sort.py: -------------------------------------------------------------------------------- 1 | """ 2 | liên tục swap 2 phần tử liền kề sai thứ tự. 3 | """ 4 | def bubble_sort(arr): 5 | for i in range(len(arr)): 6 | for j in range(0, len(arr)-i-1): 7 | if arr[j] > arr[j+1]: 8 | arr[j], arr[j+1] = arr[j+1], arr[j] 9 | 10 | 11 | arr = [64, 34, 25, 12, 22, 11, 90] 12 | bubble_sort(arr) 13 | print(arr) 14 | -------------------------------------------------------------------------------- /sort_algorithm/bucket_sort.py: -------------------------------------------------------------------------------- 1 | def insertion_sort(b): 2 | for i in range(1, len(b)): 3 | up = b[i] 4 | j = i - 1 5 | while j >= 0 and b[j] > up: 6 | b[j+1] = b[j] 7 | j -= 1 8 | 9 | b[j+1] = up 10 | 11 | return b 12 | 13 | def bucket_sort(x): 14 | arr = [] 15 | slot_num = 10 16 | 17 | for i in range(slot_num): 18 | arr.append([]) 19 | 20 | for j in x: 21 | index_b = int(slot_num*j) 22 | arr[index_b].append(j) 23 | 24 | for i in range(10): 25 | arr[i] = insertion_sort(arr[i]) 26 | 27 | k = 0 28 | for i in range(slot_num): 29 | for j in range(len(arr[i])): 30 | x[k] = arr[i][j] 31 | k += 1 32 | 33 | return x 34 | 35 | print(bucket_sort([0.897, 0.565, 0.656, 0.1234, 0.665, 0.3434])) 36 | -------------------------------------------------------------------------------- /sort_algorithm/check_sorted_array.py: -------------------------------------------------------------------------------- 1 | def array_sorted(arr): 2 | if len(arr) == 1 or len(arr) == 0: 3 | return True 4 | 5 | return arr[0] <= arr[1] and array_sorted(arr[1:]) 6 | 7 | arr = [20, 19, 23, 45, 78, 88] 8 | print(array_sorted(arr)) 9 | 10 | 11 | -------------------------------------------------------------------------------- /sort_algorithm/closest_pair.py: -------------------------------------------------------------------------------- 1 | def closest_pair(arr, x): 2 | diff = 99999 3 | res_l, res_r = 0, len(arr) - 1 4 | l, r = 0, len(arr) - 1 5 | 6 | while l < r: 7 | if abs(arr[r] + arr[l] - x) < diff: 8 | res_l = l 9 | res_r = r 10 | diff = abs(arr[r] + arr[l] - x) 11 | 12 | if abs(arr[r] + arr[l]) > x: 13 | r -=1 14 | else: 15 | l += 1 16 | 17 | return res_l, res_r 18 | 19 | arr = [10, 22, 28, 29, 30, 40] 20 | x = 54 21 | print(closest_pair(arr, x)) 22 | -------------------------------------------------------------------------------- /sort_algorithm/cocktail_sort.py: -------------------------------------------------------------------------------- 1 | def cocktail_sort(arr): 2 | n = len(arr) 3 | swapped = True 4 | start = 0 5 | end = n -1 6 | while swapped: 7 | swapped = False 8 | 9 | for i in range(start, end): 10 | if arr[i] > arr[i+1]: 11 | arr[i], arr[i+1] = arr[i+1], arr[i] 12 | swapped = True 13 | 14 | if swapped == False: 15 | break 16 | 17 | swapped = False 18 | 19 | for i in range(end - 1, start -1, -1): 20 | if arr[i] > arr[i+1]: 21 | arr[i], arr[i+1] = arr[i+1], arr[i] 22 | swapped = True 23 | 24 | start = start + 1 25 | 26 | a = [5, 1, 4, 2, 8, 0, 2] 27 | cocktail_sort(a) 28 | print(a) 29 | -------------------------------------------------------------------------------- /sort_algorithm/comb_sort.py: -------------------------------------------------------------------------------- 1 | def next_gap(gap): 2 | gap = (gap*10)//13 3 | if gap < 1: 4 | return 1 5 | return gap 6 | 7 | def comb_sort(arr): 8 | n = len(arr) 9 | 10 | gap = n 11 | swapped = True 12 | 13 | while gap != 1 or swapped: 14 | gap = next_gap(gap) 15 | 16 | swapped = False 17 | for i in range(0,n - gap): 18 | if arr[i] > arr[i + gap]: 19 | arr[i], arr[i + gap] = arr[i+gap], arr[i] 20 | swapped = True 21 | 22 | arr = [ 8, 4, 1, 3, -44, 23, -6, 28, 0] 23 | comb_sort(arr) 24 | print(arr) 25 | -------------------------------------------------------------------------------- /sort_algorithm/conditional_swapping.py: -------------------------------------------------------------------------------- 1 | """ 2 | https://www.geeksforgeeks.org/check-possible-sort-array-conditional-swapping-adjacent-allowed/ 3 | """ 4 | def possible_sort(arr, n): 5 | for i in range(n-1): 6 | if arr[i] > arr[i+1]: 7 | if arr[i] - arr[i+1] == 1: 8 | arr[i], arr[i+1] = arr[i+1], arr[i] 9 | else: 10 | return False 11 | return True 12 | 13 | arr = [1,0,3,2] 14 | print(possible_sort(arr, len(arr))) 15 | -------------------------------------------------------------------------------- /sort_algorithm/conflict_threads.py: -------------------------------------------------------------------------------- 1 | def partition(arr, low, high): 2 | pivot = arr[high] 3 | i = low - 1 4 | for j in range(low, high): 5 | if arr[j][1] == pivot[1]: 6 | if arr[j][2] < pivot[2]: 7 | i += 1 8 | arr[i], arr[j] = arr[j], arr[i] 9 | elif arr[j][1] < pivot[1]: 10 | i += 1 11 | arr[i], arr[j] = arr[j], arr[i] 12 | 13 | arr[i+1], arr[high] = arr[high], arr[i+1] 14 | 15 | return i + 1 16 | 17 | def quick_sort(arr, low, high): 18 | if low < high: 19 | p = partition(arr, low, high) 20 | 21 | quick_sort(arr, low, p -1) 22 | quick_sort(arr, p + 1, high) 23 | 24 | def conflict(arr, n): 25 | quick_sort(arr, 0, n - 1) 26 | 27 | for i in range(1, n): 28 | if arr[i][1] == arr[i -1][1]: 29 | if arr[i][2] < arr[i-1][2] + 5: 30 | j = i - 1 31 | while arr[i][1] == arr[j][1] and arr[i][2] <= arr[j][2] + 5 and j > 0: 32 | if arr[i][3]== 'W' or arr[j][3] == 'W': 33 | print(arr[i][0], arr[j][2]) 34 | 35 | j -= 1 36 | arr = [ 37 | (1, 512, 1, 'R'), 38 | (2, 432, 2, 'W'), 39 | (3, 512, 3, 'R'), 40 | (4, 932, 4, 'R'), 41 | (5, 512, 5, 'W'), 42 | (6, 932, 6, 'R'), 43 | (7, 835, 7, 'R'), 44 | (8, 432, 8, 'R') 45 | ] 46 | 47 | conflict(arr, len(arr)) 48 | -------------------------------------------------------------------------------- /sort_algorithm/consecutive_numbers.py: -------------------------------------------------------------------------------- 1 | def consecutive_number(arr, n): 2 | arr.sort() 3 | 4 | count = 1 5 | for i in range(n-1): 6 | if arr[i] +1 != arr[i+1]: 7 | count += 1 8 | 9 | return count 10 | 11 | arr = [ 100, 56, 5, 6, 102, 58, 101, 57, 7, 103, 59 ] 12 | print(consecutive_number(arr, len(arr))) 13 | 14 | -------------------------------------------------------------------------------- /sort_algorithm/count_all_pairs_difference.py: -------------------------------------------------------------------------------- 1 | def count_pairs(arr): 2 | y = {} 3 | for x in arr: 4 | if x not in y: 5 | y[x-3] = x 6 | y[x+3] = x 7 | else: 8 | yield (x, y[x]) 9 | 10 | def binary_search(arr, low, high, x): 11 | if low <= high: 12 | mid = (low + high)//2 13 | if arr[mid] == x: 14 | return mid 15 | elif arr[mid] > x: 16 | return binary_search(arr, low, mid - 1, x) 17 | else: 18 | return binary_search(arr, mid + 1, high, x) 19 | else: 20 | return -1 21 | 22 | def count_pairs(arr, k): 23 | count = 0 24 | arr.sort() 25 | 26 | for i in range(0, len(arr) -2): 27 | j = binary_search(arr, i+1, len(arr) - 1, arr[i] + k) 28 | if j != -1: 29 | count += 1 30 | print(arr[i], arr[j]) 31 | 32 | return count 33 | 34 | def count_pairs_with_sorting(arr, k): 35 | count = 0 36 | arr.sort() 37 | 38 | l, r = 0, 0 39 | while r >= l and r < len(arr): 40 | diff = arr[r] - arr[l] 41 | if diff == k: 42 | print(arr[l], arr[r]) 43 | 44 | r += 1 45 | l += 1 46 | elif diff < k: 47 | r += 1 48 | else: 49 | l += 1 50 | 51 | 52 | def binary_search(arr, x, low): 53 | high = len(arr) - 1 54 | ans = len(arr) 55 | while low <= high: 56 | mid = (low+high)//2 57 | if arr[mid] >= x: 58 | high = mid -1 59 | ans = mid 60 | else: 61 | low = mid + 1 62 | 63 | return ans 64 | 65 | 66 | def count_pairs_with_bs(arr, k): 67 | count = 0 68 | arr.sort() 69 | N = len(arr) 70 | for i in range(N): 71 | X = binary_search(arr, arr[i] + k, i + 1) 72 | if X != N: 73 | Y = binary_search(arr, arr[i] + k + 1, i +1) 74 | count += Y - X 75 | 76 | return count 77 | 78 | arr = [ 1, 3, 5, 8, 6, 4, 6 ] 79 | k = 0 80 | print(count_pairs_with_bs(arr, k)) 81 | 82 | -------------------------------------------------------------------------------- /sort_algorithm/count_distinct_occurrences_subsequence.py: -------------------------------------------------------------------------------- 1 | def distinct_occurrence(i, j, s, t): 2 | if j >= len(t): 3 | return 1 4 | if i >= len(s): 5 | return 0 6 | 7 | if s[i]==t[j]: 8 | return distinct_occurrence(i+1, j + 1, s, t) + distinct_occurrence(i+1, j, s, t) 9 | 10 | return distinct_occurrence(i+1, j, s, t) 11 | 12 | def distinct_occurrence_dp(s, t): 13 | m = len(t) 14 | n = len(s) 15 | 16 | if m > n: 17 | return 0 18 | 19 | mat = [[0 for _ in range(n + 1)] for __ in range(m + 1)] 20 | 21 | for i in range(1, m + 1): 22 | mat[i][0] = 0 23 | for j in range(n + 1): 24 | mat[0][j] = 1 25 | 26 | 27 | for i in range(1, m + 1): 28 | for j in range(1, n + 1): 29 | if T[i - 1] != S[j - 1]: 30 | mat[i][j] = mat[i][j-1] 31 | else: 32 | mat[i][j] = mat[i][j-1] + mat[i-1][j-1] 33 | 34 | return mat[m][n] 35 | 36 | 37 | S = 'geeksforgeeks' 38 | T = 'ge' 39 | 40 | print(distinct_occurrence_dp(S, T)) 41 | -------------------------------------------------------------------------------- /sort_algorithm/count_inversion.py: -------------------------------------------------------------------------------- 1 | def count_inversion(arr): 2 | count = 0 3 | for i in range(0, len(arr)): 4 | for j in range(0, i): 5 | if arr[i] < arr[j]: 6 | count += 1 7 | 8 | return count 9 | 10 | def mergesort(arr): 11 | inv_count = 0 12 | if len(arr) > 1: 13 | mid = len(arr)//2 14 | left = arr[:mid] 15 | right = arr[mid:] 16 | 17 | inv_count += mergesort(left) 18 | inv_count += mergesort(right) 19 | 20 | i, j, k = 0, 0, 0 21 | while i < len(left) and j < len(right): 22 | if left[i] < right[j]: 23 | arr[k] = left[i] 24 | i += 1 25 | else: 26 | arr[k] = right[j] 27 | inv_count += len(left) - i 28 | j += 1 29 | k += 1 30 | 31 | while i < len(left): 32 | arr[k] = left[i] 33 | i += 1 34 | k += 1 35 | 36 | while j < len(right): 37 | arr[k] = right[j] 38 | j += 1 39 | k += 1 40 | 41 | return inv_count 42 | 43 | from heapq import heappush, heappop 44 | from bisect import bisect, insort 45 | def count_inversion(arr): 46 | N = len(arr) 47 | if N <= 1: 48 | return 0 49 | 50 | sort_list = [] 51 | result = 0 52 | 53 | for i,v in enumerate(arr): 54 | heappush(sort_list, (v, i)) 55 | 56 | x = [] 57 | while sort_list: 58 | v, i = heappop(sort_list) 59 | y = bisect(x, i) 60 | print(x, i, y, i - y) 61 | 62 | result += i - y 63 | insort(x, i) 64 | return result 65 | 66 | 67 | arr = [1, 5, 3] 68 | print(count_inversion(arr)) 69 | -------------------------------------------------------------------------------- /sort_algorithm/count_sort.py: -------------------------------------------------------------------------------- 1 | def count_sort(arr): 2 | output = [0 for i in range(len(arr))] 3 | count = [0 for i in range(256)] 4 | 5 | for i in arr: 6 | count[ord(i)] += 1 7 | 8 | for i in range(256): 9 | count[i] += count[i-1] 10 | 11 | for i in range(len(arr)): 12 | output[count[ord(arr[i])]-1] = arr[i] 13 | count[ord(arr[i])] -= 1 14 | 15 | return output 16 | 17 | s = 'geeksforgeeks' 18 | print(count_sort(s)) 19 | -------------------------------------------------------------------------------- /sort_algorithm/count_surpasser.py: -------------------------------------------------------------------------------- 1 | def merge(A, aux, low, mid, high, count): 2 | k = i = low 3 | j = mid + 1 4 | c = 0 5 | 6 | while i <= mid and j <= high: 7 | if A[i] > A[j]: 8 | count[A[i]] = count.get(A[i], 0) + c 9 | aux[k] = A[i] 10 | i += 1 11 | else: 12 | aux[k] = A[j] 13 | j += 1 14 | c += 1 15 | k += 1 16 | 17 | while i <= mid: 18 | count[A[i]] = count.get(A[i], 0) + c 19 | aux[k] = A[i] 20 | k += 1 21 | i += 1 22 | 23 | for i in range(low, high + 1): 24 | A[i] = aux[i] 25 | 26 | def mergesort(A, aux, low, high, count): 27 | if high <= low: 28 | return 29 | 30 | mid = (low + high)//2 31 | 32 | mergesort(A, aux, low, mid, count) 33 | mergesort(A, aux, mid + 1, high, count) 34 | merge(A, aux, low, mid, high, count) 35 | 36 | def surpasser(A): 37 | count ={} 38 | aux = A.copy() 39 | A = A.copy() 40 | 41 | mergesort(A, aux, 0, len(A) - 1, count) 42 | 43 | return count 44 | 45 | A = [2, 7, 5, 3, 0, 8, 1] 46 | count = surpasser(A) 47 | for v in A: 48 | print(count.get(v, 0)) 49 | 50 | -------------------------------------------------------------------------------- /sort_algorithm/cycle_sort.py: -------------------------------------------------------------------------------- 1 | def cycle_sort(arr): 2 | writes = 0 3 | for cycle_start in range(0, len(arr) - 1): 4 | item = arr[cycle_start] 5 | 6 | pos = cycle_start 7 | for i in range(cycle_start + 1, len(arr)): 8 | if arr[i] < item: 9 | pos += 1 10 | 11 | if pos == cycle_start: 12 | continue 13 | 14 | while item==arr[pos]: 15 | pos += 1 16 | 17 | arr[pos], item = item, arr[pos] 18 | writes += 1 19 | print(pos, item) 20 | while pos != cycle_start: 21 | pos = cycle_start 22 | for i in range(cycle_start + 1, len(arr)): 23 | if arr[i] < item: 24 | pos += 1 25 | 26 | while item == arr[pos]: 27 | pos += 1 28 | 29 | arr[pos], item = item, arr[pos] 30 | writes += 1 31 | print(pos, item) 32 | break 33 | return writes 34 | 35 | arr = [2, 4, 5, 1, 3] 36 | cycle_sort(arr) 37 | print(arr) 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /sort_algorithm/even_odd_sort.py: -------------------------------------------------------------------------------- 1 | def even_odd_sort(arr, n): 2 | l, r = 0, n - 1 3 | 4 | i = 0 5 | while l < r: 6 | 7 | if arr[i] % 2 != 0: 8 | arr[l], arr[i] = arr[i], arr[l] 9 | l += 1 10 | else: 11 | arr[r], arr[i] = arr[i], arr[r] 12 | r -= 1 13 | i += 1 14 | 15 | odd = arr[:l] 16 | even = arr[l:] 17 | odd.sort(reverse=True) 18 | even.sort() 19 | 20 | odd.extend(even) 21 | 22 | return odd 23 | 24 | arr = [1, 3, 2, 7, 5, 4, 6] 25 | print(even_odd_sort(arr, len(arr))) 26 | print(arr) 27 | -------------------------------------------------------------------------------- /sort_algorithm/external_sort.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import shutil 3 | import os 4 | 5 | buffer_size = 10000 6 | total_size = 100000 7 | 8 | def save_array_to_file(file_name, array_to_save): 9 | np.savetxt(file_name, array_to_save, fmt='%d') 10 | 11 | def sort_and_write(file_name, array_to_sort): 12 | array_to_sort.sort() 13 | save_array_to_file(file_name, array_to_sort) 14 | 15 | def read_n_int(file_, numbers_to_read): 16 | array_ = [] 17 | 18 | if numbers_to_read <= 0: 19 | return array_ 20 | 21 | num = file_.readline() 22 | while(num): 23 | array_.append(int(num)) 24 | if len(array_) >= numbers_to_read: 25 | break 26 | num = file_.readline() 27 | 28 | return array_ 29 | 30 | def create_unsorted_file(size_, file_name_ = 'unsorted.csv'): 31 | arr = np.arange(size_, dtype='int32') 32 | np.random.shuffle(arr) 33 | save_array_to_file(file_name_, arr) 34 | arr = None 35 | 36 | import heapq 37 | 38 | def sort_slices(file_name, buffer_size): 39 | read_arr = [] 40 | chunk = 1 41 | f = open(file_name) 42 | 43 | if os.path.exists('./tmp/'): 44 | shutil.rmtree('./tmp/') 45 | os.mkdir('./tmp/') 46 | 47 | read_arr = read_n_int(f, buffer_size) 48 | while (len(read_arr) > 0): 49 | sort_and_write('./tmp/sorted_{}'.format(chunk), read_arr) 50 | read_arr = read_n_int(f, buffer_size) 51 | chunk += 1 52 | 53 | f.close() 54 | 55 | def min_heap_sort(output_file): 56 | sorted_file = open(output_file, 'w') 57 | 58 | min_heap = [] 59 | heapq.heapify(min_heap) 60 | 61 | open_files = [] 62 | 63 | for f in os.listdir('./tmp/'): 64 | if os.path.isfile('./tmp/' + f): 65 | file_ = open('./tmp/' + f) 66 | open_files.append(file_) 67 | val = file_.readline() 68 | heapq.heappush(min_heap, (int(val), file_)) 69 | 70 | while(len(min_heap) > 0): 71 | min_element = heapq.heappop(min_heap) 72 | sorted_file.write(str(min_element[0]) + '\n') 73 | next_str = min_element[1].readline() 74 | if next_str: 75 | heapq.heappush(min_heap, (int(next_str), min_element[1])) 76 | else: 77 | min_element[1].close() 78 | 79 | sorted_file.close() 80 | 81 | def external_sort(input_file, output_file, buffer_size=10000): 82 | sort_slices(input_file, buffer_size) 83 | min_heap_sort(output_file) 84 | print('sorted value are written to {}'.format(output_file)) 85 | 86 | create_unsorted_file(total_size, file_name_ = 'unsorted.csv') 87 | external_sort(input_file= 'unsorted.csv', output_file='sorted_external.csv', buffer_size = 10000) 88 | -------------------------------------------------------------------------------- /sort_algorithm/gnome_sort.py: -------------------------------------------------------------------------------- 1 | def gnome_sort(arr, n): 2 | index = 0 3 | while index < n: 4 | if index == 0: 5 | index += 1 6 | elif arr[index] >= arr[index -1]: 7 | index += 1 8 | else: 9 | arr[index], arr[index-1] = arr[index-1], arr[index] 10 | index -=1 11 | 12 | return arr 13 | 14 | arr = [ 34, 2, 10, -9] 15 | print(gnome_sort(arr, len(arr))) 16 | 17 | -------------------------------------------------------------------------------- /sort_algorithm/greatest_product.py: -------------------------------------------------------------------------------- 1 | from math import sqrt 2 | 3 | def greatest_product(arr, n): 4 | m = {} 5 | for i in arr: 6 | m[i] = m.get(i, 0) + 1 7 | 8 | arr.sort() 9 | 10 | for i in range(n-1, 0, -1): 11 | j = 0 12 | while j < i and arr[j] <= sqrt(arr[i]): 13 | if arr[i] % arr[j] == 0: 14 | result = arr[i]//arr[j] 15 | 16 | if result != arr[j]: 17 | if result in m and m[result] > 0: 18 | return arr[i] 19 | else: 20 | if result in m and m[result] > 1: 21 | return arr[i] 22 | 23 | return -1 24 | 25 | arr = [17, 2, 1, 15, 30] 26 | print(greatest_product(arr, len(arr))) 27 | -------------------------------------------------------------------------------- /sort_algorithm/heap_sort.py: -------------------------------------------------------------------------------- 1 | """ 2 | """ 3 | def heapify(arr, n ,i): 4 | largest = i 5 | l = 2*i + 1 6 | r = 2*i + 2 7 | 8 | if l < n and arr[largest] < arr[l]: 9 | largest = l 10 | 11 | if r < n and arr[largest] < arr[r]: 12 | largest = r 13 | 14 | if largest != i: 15 | arr[i], arr[largest] = arr[largest], arr[i] 16 | heapify(arr, n, largest) 17 | 18 | def heap_sort(arr): 19 | n = len(arr) 20 | 21 | for i in range(n//2 -1 , -1, -1): 22 | heapify(arr, n, i) 23 | 24 | for i in range(n-1, 0, -1): 25 | arr[i], arr[0] = arr[0], arr[i] 26 | heapify(arr, i, 0) 27 | 28 | arr = [12, 11, 13, 5, 6, 7] 29 | heap_sort(arr) 30 | 31 | print(arr) 32 | -------------------------------------------------------------------------------- /sort_algorithm/insertion_sort.py: -------------------------------------------------------------------------------- 1 | """ 2 | giống như khi sắp sếp bài tiến lên, bốc từ số và đặt vào dãy đã sắp sếp phía trước. 3 | """ 4 | 5 | def insertion_sort(arr): 6 | for i in range(1, len(arr)): 7 | key = arr[i] 8 | 9 | j = i - 1 10 | while j >= 0 and key < arr[j]: 11 | arr[j+1] = arr[j] 12 | j -= 1 13 | 14 | arr[j+1] = key 15 | 16 | arr = [12, 11, 13, 5, 6] 17 | insertion_sort(arr) 18 | print(arr) 19 | -------------------------------------------------------------------------------- /sort_algorithm/iterative_quick_sort.py: -------------------------------------------------------------------------------- 1 | """ 2 | """ 3 | def partition(arr, l, h): 4 | pivot = arr[h] 5 | i = l -1 6 | for j in range(l, h): 7 | if arr[j] < pivot: 8 | i+=1 9 | arr[i], arr[j] = arr[j], arr[i] 10 | 11 | arr[i+1], arr[h] = arr[h], arr[i+1] 12 | 13 | return i + 1 14 | 15 | def quick_sort(arr, l, h): 16 | size = h - l + 1 17 | stack = [0]*size 18 | 19 | top = -1 20 | top += 1 21 | stack[top] = l 22 | top += 1 23 | stack[top] = h 24 | 25 | while top >= 0: 26 | h = stack[top] 27 | top -= 1 28 | l = stack[top] 29 | top -= 1 30 | 31 | p = partition(arr, l, h) 32 | 33 | if p - 1 > l: 34 | top += 1 35 | stack[top] = l 36 | top += 1 37 | stack[top] = p -1 38 | 39 | if p + 1 < h: 40 | top += 1 41 | stack[top] = l 42 | top += 1 43 | stack[top] = p + 1 44 | 45 | 46 | arr = [4, 3, 5, 2, 1, 3, 2, 3] 47 | quick_sort(arr, 0, len(arr) - 1) 48 | print(arr) 49 | -------------------------------------------------------------------------------- /sort_algorithm/kth_smallest.py: -------------------------------------------------------------------------------- 1 | """ 2 | https://www.geeksforgeeks.org/k-th-smallest-element-removing-given-integers-natural-numbers-set-2/ 3 | """ 4 | 5 | def k_smallest(arr, n, k): 6 | arr.sort() 7 | for i in range(n): 8 | if arr[i] <= k: 9 | k += 1 10 | else: 11 | break 12 | 13 | return k 14 | 15 | arr = [1,2] 16 | k = 3 17 | print(k_smallest(arr, len(arr), k)) 18 | -------------------------------------------------------------------------------- /sort_algorithm/largest_3_multiple.py: -------------------------------------------------------------------------------- 1 | """ 2 | https://www.geeksforgeeks.org/find-largest-multiple-3-array-digits-set-2-time-o1-space/ 3 | """ 4 | MAX_SIZE = 10 5 | def counting_sort(arr, n): 6 | count = [0]*MAX_SIZE 7 | for i in range(n): 8 | count[arr[i]] += 1 9 | 10 | index = 0 11 | for i in range(MAX_SIZE): 12 | while count[i] > 0: 13 | arr[index] = i 14 | count[i] -= 1 15 | index += 1 16 | 17 | arr = [4, 4, 1, 1, 1, 3] 18 | counting_sort(arr, len(arr)) 19 | print(arr) 20 | -------------------------------------------------------------------------------- /sort_algorithm/length_sort.py: -------------------------------------------------------------------------------- 1 | def sort(arr, n): 2 | for i in range(1, n): 3 | key = arr[i] 4 | 5 | j = i - 1 6 | while j >= 0 and len(key) < len(arr[j]): 7 | arr[j+1] = arr[j] 8 | j -= 1 9 | 10 | arr[j+1] = key 11 | 12 | 13 | arr = ["GeeksforGeeks", "I", "from", "am"] 14 | sort(arr, len(arr)) 15 | print(arr) 16 | -------------------------------------------------------------------------------- /sort_algorithm/lomuto_partition_quick_sort.py: -------------------------------------------------------------------------------- 1 | def partition(arr, low, high): 2 | pivot = arr[high] 3 | 4 | i = low - 1 5 | for j in range(low, high): 6 | if arr[j] < pivot: 7 | i += 1 8 | arr[i], arr[j] = arr[j], arr[i] 9 | 10 | arr[i+1], arr[high] = arr[high], arr[i+1] 11 | 12 | return i+1 13 | 14 | def partition(arr, low, high): 15 | pivot = arr[low] 16 | i = low - 1 17 | j = high + 1 18 | 19 | while(True): 20 | i += 1 21 | while arr[i] < pivot: 22 | i += 1 23 | 24 | j -= 1 25 | while arr[j] > pivot: 26 | j -= 1 27 | 28 | if i >= j: 29 | return 30 | 31 | arr[i], arr[j] = arr[j], arr[i] 32 | 33 | 34 | def quick_sort(arr, low, high): 35 | if low < high: 36 | p = partition(arr, low, high) 37 | quick_sort(arr, low, p-1) 38 | quick_sort(arr, p+1, high) 39 | 40 | arr = [10, 7, 8, 9, 1, 5] 41 | quick_sort(arr, 0, len(arr) - 1) 42 | print(arr) 43 | -------------------------------------------------------------------------------- /sort_algorithm/max_diff.py: -------------------------------------------------------------------------------- 1 | def max_diff(arr, n): 2 | freq = {} 3 | for i in arr: 4 | freq[i] = freq.get(i, 0) + 1 5 | dist = list(freq) 6 | dist.sort() 7 | 8 | min_freq = n + 1 9 | ans = 0 10 | for i in dist: 11 | cur_freq = freq[i] 12 | ans = max(ans, cur_freq - min_freq) 13 | min_freq = min(min_freq, cur_freq) 14 | 15 | return ans 16 | 17 | arr = [3, 1, 3, 2, 3, 2] 18 | 19 | print(max_diff(arr, len(arr))) 20 | -------------------------------------------------------------------------------- /sort_algorithm/maximum_height_pyramid.py: -------------------------------------------------------------------------------- 1 | def maximum_height(arr, n): 2 | result = 1 3 | for i in range(1, n): 4 | y = i*(i+1)/2 5 | if y < n: 6 | result = i 7 | else: 8 | break 9 | 10 | return result 11 | 12 | arr = [40, 100, 20, 30] 13 | print(maximum_height(arr, len(arr))) 14 | -------------------------------------------------------------------------------- /sort_algorithm/maximum_interval_overlap.py: -------------------------------------------------------------------------------- 1 | def max_guest(arrl, exit, n): 2 | mini = min(arrl) 3 | maxi = max(exit) 4 | 5 | count = [0]*(maxi - mini + 1) 6 | 7 | for i in range(n): 8 | for j in range(arrl[i], exit[i]+1): 9 | count[j-mini] += 1 10 | 11 | max_ele = max(enumerate(count), key=lambda x:x[1]) 12 | max_ele = (max_ele[0]+mini, max_ele[1]) 13 | return max_ele 14 | 15 | def max_guest(arrl, exit, n): 16 | arrl.sort() 17 | exit.sort() 18 | 19 | guests_in = 1 20 | max_guests = 1 21 | time = arrl[0] 22 | 23 | i, j = 1, 0 24 | 25 | while i < n and j < n: 26 | if arrl[i] <= exit[j]: 27 | guests_in += 1 28 | if guests_in > max_guests: 29 | max_guests = guests_in 30 | time = arrl[i] 31 | i += 1 32 | else: 33 | guests_in -= 1 34 | j += 1 35 | 36 | return time, max_guests 37 | 38 | def max_guest(arrl, exit, n): 39 | maxi =max(max(arrl), max(exit)) 40 | cur = 0 41 | idx = 0 42 | x = [0]*(maxi+2) 43 | 44 | for i in range(n): 45 | x[arrl[i]] += 1 46 | x[exit[i]+1] -= 1 47 | 48 | print(x) 49 | max_gst = 0 50 | for i in range(maxi+1): 51 | cur += x[i] 52 | if cur > max_gst: 53 | max_gst = cur 54 | idx = i 55 | 56 | print(idx, max_gst) 57 | 58 | 59 | arrl = [1, 2, 10, 5, 5]; 60 | exit = [4, 5, 12, 9, 12]; 61 | 62 | print(max_guest(arrl, exit, len(arrl))) 63 | -------------------------------------------------------------------------------- /sort_algorithm/maximum_product_triplet.py: -------------------------------------------------------------------------------- 1 | def max_triplet_product(arr, n): 2 | max_a, max_b, max_c = -1000, -1000, -1000 3 | min_a, min_b = 1000, 1000 4 | 5 | for i in range(n): 6 | if arr[i] > max_a: 7 | max_c = max_b 8 | max_b = max_a 9 | max_a = arr[i] 10 | elif arr[i] > max_b: 11 | max_c = max_b 12 | max_b = arr[i] 13 | elif arr[i] > max_c: 14 | max_c = arr[i] 15 | 16 | if arr[i] < min_a: 17 | min_b = min_a 18 | min_a = arr[i] 19 | elif arr[i] < min_b: 20 | min_b = arr[i] 21 | 22 | return max(max_a*max_b*max_c, min_a*min_b*max_a) 23 | 24 | 25 | arr = [ 1, -4, 3, -6, 7, 0 ] 26 | print(max_triplet_product(arr, len(arr))) 27 | -------------------------------------------------------------------------------- /sort_algorithm/merge_sort.py: -------------------------------------------------------------------------------- 1 | """ 2 | """ 3 | 4 | def merge_sort(arr): 5 | 6 | if len(arr) == 1: return 7 | 8 | mid = len(arr)//2 9 | L = arr[:mid] 10 | R = arr[mid:] 11 | 12 | merge_sort(L) 13 | merge_sort(R) 14 | 15 | i=j=k=0 16 | while i < len(L) and j < len(R): 17 | if L[i] < R[j]: 18 | arr[k] = L[i] 19 | i+=1 20 | else: 21 | arr[k] = R[j] 22 | j+=1 23 | 24 | k += 1 25 | 26 | while i < len(L): 27 | arr[k] = L[i] 28 | i += 1 29 | k += 1 30 | 31 | while j < len(R): 32 | arr[k] = R[j] 33 | j += 1 34 | k += 1 35 | 36 | 37 | arr = [12, 11, 13, 5, 6, 7] 38 | merge_sort(arr) 39 | print(arr) 40 | -------------------------------------------------------------------------------- /sort_algorithm/merge_sort_linked_list.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.next = None 5 | 6 | class LinkedList: 7 | def __init__(self): 8 | self.head = None 9 | 10 | def append(self, new_value): 11 | new_node = Node(new_value) 12 | 13 | if self.head == None: 14 | self.head = new_node 15 | return 16 | 17 | curr_node = self.head 18 | while curr_node.next is not None: 19 | curr_node = curr_node.next 20 | 21 | curr_node.next = new_node 22 | 23 | def sorted_merge(self, a, b): 24 | result = None 25 | if a == None: 26 | return b 27 | if b == None: 28 | return a 29 | 30 | if a.data <= b.data: 31 | result = a 32 | result.next = self.sorted_merge(a.next, b) 33 | else: 34 | result = b 35 | result.next = self.sorted_merge(a, b.next) 36 | 37 | return result 38 | 39 | def merge_sort(self, head): 40 | if head == None or head.next == None: 41 | return head 42 | 43 | middle = self.get_middle(head) 44 | next_to_middle = middle.next 45 | 46 | middle.next = None 47 | 48 | left = self.merge_sort(head) 49 | right = self.merge_sort(next_to_middle) 50 | 51 | sorted_list = self.sorted_merge(left, right) 52 | 53 | return sorted_list 54 | 55 | def get_middle(self, head): 56 | if head==None: 57 | return head 58 | 59 | slow = head 60 | fast = head 61 | 62 | while fast.next is not None and fast.next.next is not None: 63 | slow = slow.next 64 | fast = fast.next.next 65 | 66 | return slow 67 | 68 | 69 | def print_list(head): 70 | curr_node = head 71 | while curr_node is not None: 72 | print(curr_node.data, end=' ') 73 | curr_node = curr_node.next 74 | 75 | print(' ') 76 | 77 | li = LinkedList() 78 | li.append(15) 79 | li.append(10) 80 | li.append(5) 81 | li.append(20) 82 | li.append(3) 83 | li.append(2) 84 | li.append(4) 85 | li.append(9) 86 | li.append(10) 87 | li.append(11) 88 | li.append(3) 89 | 90 | print_list(li.head) 91 | print_list(li.merge_sort(li.head)) 92 | -------------------------------------------------------------------------------- /sort_algorithm/minimum_difference.py: -------------------------------------------------------------------------------- 1 | def minimum_difference(arr, n, m): 2 | arr.sort() 3 | 4 | min_diff = arr[n-1] - arr[0] 5 | for i in range(n - m + 1): 6 | diff = arr[i+m-1] - arr[i] 7 | if diff < min_diff: 8 | min_diff = diff 9 | 10 | return min_diff 11 | 12 | arr = [12, 4, 7, 9, 2, 23, 25, 41, 30, 40, 28, 42, 30, 44, 48, 43, 50] 13 | m = 7 14 | n = len(arr) 15 | print(minimum_difference(arr, n, m)) 16 | -------------------------------------------------------------------------------- /sort_algorithm/minimum_sum_diff.py: -------------------------------------------------------------------------------- 1 | def min_sum(a, b, n): 2 | a.sort() 3 | b.sort() 4 | 5 | s = 0 6 | for i in range(n): 7 | s += abs(a[i] - b[i]) 8 | 9 | return s 10 | 11 | a = [4, 1, 8, 7] 12 | b = [2, 3, 6, 5] 13 | print(min_sum(a, b, len(a))) 14 | -------------------------------------------------------------------------------- /sort_algorithm/minimum_swaps.py: -------------------------------------------------------------------------------- 1 | def min_swaps(arr): 2 | n = len(arr) 3 | 4 | arrpos = [*enumerate(arr)] 5 | 6 | arrpos.sort(key=lambda it:it[1]) 7 | 8 | vis = {k: False for k in range(n)} 9 | 10 | ans = 0 11 | 12 | for i in range(n): 13 | if vis[i] or arrpos[i][0]==i: 14 | continue 15 | 16 | j = i 17 | cycle_size = 0 18 | 19 | while not vis[j]: 20 | vis[j] = True 21 | 22 | j = arrpos[j][0] 23 | cycle_size += 1 24 | 25 | ans += (cycle_size - 1) 26 | 27 | return ans 28 | 29 | def min_swaps(arr): 30 | n = len(arr) 31 | 32 | tmp = sorted(arr) 33 | 34 | ans = 0 35 | 36 | for i in range(n): 37 | if arr[i] != tmp[i]: 38 | ans += 1 39 | 40 | j = arr.index(tmp[i]) 41 | arr[i], arr[j] = arr[j], arr[i] 42 | 43 | return ans 44 | 45 | arr = [1, 20, 6, 4, 5] 46 | print(min_swaps(arr)) 47 | -------------------------------------------------------------------------------- /sort_algorithm/minimum_swaps_2_positions.py: -------------------------------------------------------------------------------- 1 | """ 2 | https://www.geeksforgeeks.org/minimum-swaps-reach-permuted-array-2-positions-left-swaps-allowed/ 3 | """ 4 | 5 | def merge(arr, tmp, left, mid, right): 6 | inv_count = 0 7 | 8 | i = left 9 | j = mid 10 | k = left 11 | 12 | while i <= mid -1 and j <= right: 13 | if arr[i] <= arr[j]: 14 | tmp[k] = arr[i] 15 | i += 1 16 | else: 17 | tmp[k] = arr[j] 18 | j += 1 19 | inv_count += (mid - i) 20 | 21 | k += 1 22 | 23 | while i <= mid - 1: 24 | tmp[i] = arr[i] 25 | i += 1 26 | k += 1 27 | 28 | while j <= right: 29 | tmp[j] = arr[j] 30 | j += 1 31 | k += 1 32 | 33 | for i in range(left, right+1): 34 | arr[i] = tmp[i] 35 | 36 | return inv_count 37 | 38 | def _merge_sort(arr, tmp, left, right): 39 | inv_count = 0 40 | 41 | if left < right: 42 | mid = (left + right)//2 43 | 44 | inv_count += _merge_sort(arr, tmp, left, mid) 45 | inv_count += _merge_sort(arr, tmp, mid+1, right) 46 | 47 | inv_count += merge(arr, tmp, left, mid+1, right) 48 | 49 | return inv_count 50 | 51 | def merge_sort(arr, n): 52 | tmp = [0]*n 53 | return _merge_sort(arr, tmp, 0, n-1) 54 | 55 | def min_swaps(arr, n): 56 | for i in range(n): 57 | if (arr[i] -1) - i > 2: 58 | return -1 59 | 60 | num_inversion = merge_sort(arr, n) 61 | 62 | return num_inversion 63 | 64 | arr = [1, 2, 5, 3, 4] 65 | print(min_swaps(arr, len(arr))) 66 | -------------------------------------------------------------------------------- /sort_algorithm/minimum_swaps_identical_array.py: -------------------------------------------------------------------------------- 1 | def minimum_swaps(a, b, n): 2 | n_swaps = 0 3 | for i in range(n): 4 | if a[i] != b[i]: 5 | n_swaps += 1 6 | 7 | j = b.index(a[i]) 8 | b[i], b[j] = b[j], b[i] 9 | 10 | return n_swaps 11 | 12 | def cycle_sort(b, n): 13 | visited = [False]*n 14 | ans = 0 15 | 16 | for i in range(n): 17 | if visited[i] or b[i][0] == i: 18 | continue 19 | 20 | j = i 21 | cycle_size = 0 22 | while not visited[j]: 23 | visited[j] = True 24 | j = b[j][0] 25 | cycle_size += 1 26 | 27 | ans += (cycle_size - 1) 28 | 29 | return ans 30 | 31 | def minimum_swaps(a, b, n): 32 | mp = {} 33 | 34 | for i in range(n): 35 | mp[b[i]] = i 36 | 37 | for i in range(n): 38 | b[i] = (mp[a[i]], a[i]) 39 | 40 | return cycle_sort(b, n) 41 | 42 | a = [3, 6, 4, 8] 43 | b = [4, 6, 8, 3] 44 | 45 | print(minimum_swaps(a, b, len(a))) 46 | -------------------------------------------------------------------------------- /sort_algorithm/minimum_unsorted_subarray.py: -------------------------------------------------------------------------------- 1 | def unsorted_subarray(arr, n): 2 | i = 0 3 | j = n - 1 4 | 5 | while arr[i + 1] >= arr[i]: 6 | i += 1 7 | 8 | while arr[j-1] <= arr[j]: 9 | j -= 1 10 | 11 | 12 | min_value = min(arr[i+1:j-1]) 13 | max_value = max(arr[i+1:j-1]) 14 | 15 | i = 0 16 | j = n - 1 17 | while min_value >= arr[i]: 18 | i += 1 19 | 20 | while max_value <= arr[j]: 21 | j -= 1 22 | 23 | print(i, j) 24 | 25 | arr = [10, 12, 20, 30, 25, 40, 32, 31, 35, 50, 60] 26 | unsorted_subarray(arr, len(arr)) 27 | -------------------------------------------------------------------------------- /sort_algorithm/nearly_sorted_array.py: -------------------------------------------------------------------------------- 1 | """insertion sort is effience for k nearly sorted array 2 | """ 3 | 4 | def insertion_sort(arr, n): 5 | for i in range(1, n): 6 | j = i 7 | key = arr[i] 8 | 9 | while arr[j -1] > key and j > 0: 10 | arr[j] = arr[j-1] 11 | j -= 1 12 | 13 | arr[j] = key 14 | 15 | from heapq import heappop, heappush, heapify 16 | 17 | def sort_k(arr, n, k): 18 | heap = arr[:k] 19 | heapify(heap) 20 | 21 | target_index = 0 22 | for i in range(k, n): 23 | arr[target_index] = heappop(heap) 24 | heappush(heap, arr[i]) 25 | target_index += 1 26 | 27 | while heap: 28 | arr[target_index] = heappop(heap) 29 | target_index += 1 30 | 31 | k = 3 32 | arr = [2, 6, 3, 12, 56, 8] 33 | n = len(arr) 34 | 35 | sort_k(arr, len(arr), k) 36 | print(arr) 37 | -------------------------------------------------------------------------------- /sort_algorithm/noble_integer.py: -------------------------------------------------------------------------------- 1 | def noble_integer(arr, n): 2 | arr.sort() 3 | 4 | for i in range(n-1): 5 | if arr[i] == arr[i+1]: 6 | continue 7 | 8 | if arr[i] == n - i - 1: 9 | return arr[i] 10 | 11 | if arr[n-1] == 0: 12 | return 0 13 | 14 | return -1 15 | 16 | def noble_integer(arr, n): 17 | count = [0]*(n+1) 18 | 19 | for i in range(n): 20 | if arr[i] < 0: 21 | continue 22 | elif arr[i]>=n: 23 | count[n] += 1 24 | else: 25 | count[arr[i]] += 1 26 | 27 | total_greater = count[n] 28 | for i in range(n-1, -1, -1): 29 | if total_greater == i and count[i] > 0: 30 | return i 31 | 32 | elif total_greater > i: 33 | return -1 34 | total_greater += count[i] 35 | 36 | return -1 37 | 38 | arr = [10, 3, 20, 40, 2] 39 | print(noble_integer(arr, len(arr))) 40 | -------------------------------------------------------------------------------- /sort_algorithm/number_pairs_xy_yx.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /sort_algorithm/odd_even_sort.py: -------------------------------------------------------------------------------- 1 | def old_even_sort(arr, n): 2 | is_sorted = 0 3 | while is_sorted == 0: 4 | is_sorted = 1 5 | for i in range(1, n -1, 2): 6 | if arr[i] > arr[i+1]: 7 | arr[i], arr[i+1] = arr[i+1], arr[i] 8 | is_sorted = 0 9 | 10 | for i in range(0, n - 1, 2): 11 | if arr[i] > arr[i+1]: 12 | arr[i], arr[i+1] = arr[i+1], arr[i] 13 | is_sorted = 0 14 | 15 | arr = [34, 2, 10, -9] 16 | old_even_sort(arr, len(arr)) 17 | print(arr) 18 | 19 | -------------------------------------------------------------------------------- /sort_algorithm/overlap_interval.py: -------------------------------------------------------------------------------- 1 | def overlap_interval(arr): 2 | max_ele = 0 3 | for start, end in arr: 4 | if max_ele < end: 5 | max_ele = end 6 | 7 | aux = [0]*(max_ele+1) 8 | for start, end in arr: 9 | aux[start] += 1 10 | aux[end] -=1 11 | 12 | for i in range(1, max_ele+1): 13 | aux[i] += aux[i-1] 14 | 15 | if aux[i] >= 1: 16 | return True 17 | 18 | 19 | arr = [[ 6, 8 ], [1, 3 ], [ 2, 4 ], [ 4, 7 ]] 20 | print(overlap_interval(arr)) 21 | -------------------------------------------------------------------------------- /sort_algorithm/pancake_sort.py: -------------------------------------------------------------------------------- 1 | def flip(arr, i): 2 | start = 0 3 | while start < i: 4 | arr[start], arr[i] = arr[i], arr[start] 5 | start += 1 6 | i -= 1 7 | 8 | def find_max(arr, n): 9 | mi = 0 10 | for i in range(0, n): 11 | if arr[i] > arr[mi]: 12 | mi = i 13 | 14 | return mi 15 | 16 | def pancake_sort(arr, n): 17 | curr_size = n 18 | while curr_size > 1: 19 | mi = find_max(arr, curr_size) 20 | if mi != curr_size -1: 21 | flip(arr, mi) 22 | flip(arr, curr_size -1) 23 | 24 | curr_size -= 1 25 | 26 | arr = [23, 10, 20, 11, 12, 6, 7] 27 | pancake_sort(arr, len(arr)) 28 | print(arr) 29 | -------------------------------------------------------------------------------- /sort_algorithm/pancake_sorting_question.py: -------------------------------------------------------------------------------- 1 | """https://www.geeksforgeeks.org/a-pancake-sorting-question/ 2 | """ 3 | 4 | def ceil_search(arr, low, high, x): 5 | print(low, high) 6 | if x <= arr[low]: 7 | return low 8 | if x > arr[high]: 9 | return -1 10 | 11 | if high - low == 1 and arr[low] <= x <= arr[high]: 12 | return high 13 | 14 | mid = (high + low)//2 15 | 16 | if arr[mid] == x: 17 | return mid 18 | 19 | if arr[mid] > x: 20 | return ceil_search(arr, low, mid, x) 21 | 22 | if arr[mid] < x: 23 | return ceil_search(arr, mid, high, x) 24 | 25 | def flip(arr, i): 26 | start = 0 27 | while i > start: 28 | arr[i], arr[start] = arr[start], arr[i] 29 | start += 1 30 | i -= 1 31 | 32 | def insertion_sort(arr): 33 | 34 | for i in range(1, len(arr)): 35 | j = ceil_search(arr, 0, i-1, arr[i]) 36 | 37 | if j != -1: 38 | flip(arr, j-1) 39 | flip(arr, i-1) 40 | flip(arr, i) 41 | flip(arr, j) 42 | 43 | 44 | arr=[18, 40, 35, 12, 30, 35, 20, 6, 90, 80] 45 | 46 | insertion_sort(arr) 47 | print(arr) 48 | -------------------------------------------------------------------------------- /sort_algorithm/pigeonhole_sort.py: -------------------------------------------------------------------------------- 1 | def pigeonhole_sort(arr): 2 | my_min = min(arr) 3 | my_max = max(arr) 4 | 5 | size = my_max - my_min + 1 6 | holes = [0]*size 7 | 8 | for x in a: 9 | holes[x - my_min] += 1 10 | 11 | 12 | i = 0 13 | for count in range(size): 14 | while holes[count] > 0: 15 | holes[count] -= 1 16 | arr[i] = count + my_min 17 | i += 1 18 | 19 | a = [8, 3, 2, 7, 4, 6, 8] 20 | pigeonhole_sort(a) 21 | print(a) 22 | -------------------------------------------------------------------------------- /sort_algorithm/possible_triangle.py: -------------------------------------------------------------------------------- 1 | def possible_triangle(arr, n): 2 | arr.sort() 3 | 4 | for i in range(n-2): 5 | if arr[i] + arr[i+1] > arr[i+1]: 6 | return True 7 | 8 | return False 9 | 10 | arr = [5, 4, 3, 1, 2] 11 | print(possible_triangle(arr, len(arr))) 12 | -------------------------------------------------------------------------------- /sort_algorithm/quick_sort.py: -------------------------------------------------------------------------------- 1 | """ 2 | """ 3 | def partition(arr, l, h): 4 | pivot = arr[h] 5 | i = l - 1 6 | for j in range(l, h): 7 | if arr[j] < pivot: 8 | i += 1 9 | arr[i], arr[j] = arr[j], arr[i] 10 | 11 | arr[i+1], arr[h] = arr[h], arr[i+1] 12 | 13 | return i+1 14 | 15 | def quick_sort(arr, l, h): 16 | if (l < h): 17 | pi = partition(arr, l, h) 18 | quick_sort(arr, l, pi-1) 19 | quick_sort(arr, pi+1, h) 20 | 21 | arr = [10, 7, 8, 9, 1, 5] 22 | quick_sort(arr, 0, len(arr)-1) 23 | print(arr) 24 | -------------------------------------------------------------------------------- /sort_algorithm/quick_sort_doubly_linked_list.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, d): 3 | self.data = d 4 | self.prev = None 5 | self.next = None 6 | 7 | def last_node(node): 8 | while node.next != None: 9 | node = node.next 10 | 11 | return node 12 | 13 | def partition(l, h): 14 | x = h.data 15 | i = l.prev 16 | 17 | j = l 18 | 19 | while j != h: 20 | if j.data < x: 21 | i = l if i == None else i.next 22 | 23 | i.data, j.data = j.data, i.data 24 | 25 | j = j.next 26 | 27 | i = l if i == None else i.next 28 | i.data, h.data = h.data, i.data 29 | 30 | return i 31 | 32 | def _quicksort(l, h): 33 | if h != None and l != h and l != h.next: 34 | tmp = partition(l, h) 35 | _quicksort(l, tmp.prev) 36 | _quicksort(tmp.next, h) 37 | 38 | def quicksort(node): 39 | head = last_node(node) 40 | _quicksort(node, head) 41 | 42 | def print_list(head): 43 | while(head != None): 44 | print(head.data, end=" "); 45 | head = head.next; 46 | 47 | head = None 48 | def push(new_data): 49 | global head 50 | new_node= Node(new_data) 51 | 52 | if head == None: 53 | head = new_node 54 | return 55 | 56 | new_node.next = head 57 | head.prev = new_node 58 | new_node.prev = None 59 | head = new_node 60 | 61 | 62 | push(5); 63 | push(20); 64 | push(4); 65 | push(3); 66 | push(30); 67 | 68 | print_list(head) 69 | print('\n') 70 | quicksort(head) 71 | print_list(head) 72 | -------------------------------------------------------------------------------- /sort_algorithm/quick_sort_reducing_worst_case.py: -------------------------------------------------------------------------------- 1 | def partition(arr, low, high): 2 | i = low - 1 3 | pivot = arr[high] 4 | 5 | for j in range(low, high): 6 | if arr[j] < pivot: 7 | i += 1 8 | arr[i], arr[j] = arr[j], arr[i] 9 | 10 | arr[i+1], arr[high] = arr[high], arr[i+1] 11 | return i + 1 12 | 13 | def quick_sort(arr, low, high): 14 | if low < high: 15 | p = partition(arr, low, high) 16 | 17 | quick_sort(arr, low, p -1) 18 | quick_sort(arr, p+1, high) 19 | 20 | def quick_sort(arr, low, high): 21 | while low < high: 22 | p = partition(arr, low, high) 23 | 24 | quick_sort(arr, low, p - 1) 25 | low = p + 1 26 | 27 | def quick_sort(arr, low, high): 28 | while low < high: 29 | p = partition(arr, low, high) 30 | 31 | if p - low < high - p: 32 | quick_sort(arr, low, p - 1) 33 | low = p + 1 34 | else: 35 | quick_sort(arr, p + 1, high) 36 | high = p - 1 37 | 38 | a = [1,4,2,7,5] 39 | quick_sort(a, 0, len(a) - 1) 40 | print(a) 41 | 42 | -------------------------------------------------------------------------------- /sort_algorithm/radix_sort.py: -------------------------------------------------------------------------------- 1 | def count_sort(arr, exp): 2 | n = len(arr) 3 | 4 | output = [0]*n 5 | count = [0]*10 6 | 7 | for i in range(n): 8 | index = arr[i] // exp 9 | count[index%10] += 1 10 | 11 | 12 | for i in range(1, 10): 13 | count[i] += count[i-1] 14 | 15 | i = n - 1 16 | while i >= 0: 17 | index = arr[i] // exp 18 | output[count[index % 10] - 1] = arr[i] 19 | count[index % 10] -= 1 20 | i -= 1 21 | 22 | i = 0 23 | for i in range(n): 24 | arr[i] = output[i] 25 | 26 | def radix_sort(arr): 27 | m = max(arr) 28 | 29 | exp = 1 30 | 31 | while m // exp >= 1: 32 | count_sort(arr, exp) 33 | exp *= 10 34 | 35 | return arr 36 | 37 | arr = [170, 45, 75, 90, 802, 24, 2, 66] 38 | print(radix_sort(arr)) 39 | -------------------------------------------------------------------------------- /sort_algorithm/rearrange_pos_neg.py: -------------------------------------------------------------------------------- 1 | def rotate(arr, l, r): 2 | tmp = arr[r] 3 | for j in range(r, l-1, -1): 4 | arr[j] = arr[j-1] 5 | arr[l] = tmp 6 | 7 | def move_negative_qsort(arr, n): 8 | i = -1 9 | for j in range(n): 10 | if arr[j] < 0: 11 | i += 1 12 | arr[i], arr[j] = arr[j], arr[i] 13 | 14 | if j - i >= 2: 15 | rotate(arr, i+1, j) 16 | 17 | def move_negative_insertion_sort(arr, n): 18 | for i in range(1, n): 19 | key = arr[i] 20 | if key >= 0: 21 | continue 22 | 23 | j = i - 1 24 | while j >= 0 and arr[j] >= 0: 25 | arr[j+1] = arr[j] 26 | j -= 1 27 | 28 | arr[j+1] = key 29 | 30 | 31 | def merge(arr, l, m, r): 32 | n1 = m - l + 1 33 | n2 = r - m 34 | 35 | L = [arr[l+i] for i in range(n1)] 36 | R = [arr[m+ 1 + i] for i in range(n2)] 37 | 38 | i = 0 39 | j = 0 40 | k = l 41 | 42 | while i < n1 and L[i] < 0: 43 | arr[k] = L[i] 44 | k += 1 45 | i += 1 46 | 47 | while j < n2 and R[j] < 0: 48 | arr[k] = R[j] 49 | k += 1 50 | j += 1 51 | 52 | while i < n1: 53 | arr[k] = L[i] 54 | k += 1 55 | i += 1 56 | 57 | while j < n2: 58 | arr[k] = R[j] 59 | k += 1 60 | j += 1 61 | 62 | def reverse(arr, l, r): 63 | if l < r: 64 | arr[l], arr[r] = arr[r], arr[l] 65 | l += 1 66 | r -= 1 67 | reverse(arr, l, r) 68 | 69 | def merge_inplace(arr, l, m, r): 70 | i = l 71 | j = m + 1 72 | 73 | while i <= m and arr[i] < 0: 74 | i += 1 75 | 76 | while j <= r and arr[j] < 0: 77 | j += 1 78 | 79 | reverse(arr, i, m) 80 | reverse(arr, m + 1, j - 1) 81 | reverse(arr, i, j - 1) 82 | 83 | 84 | def move_negative_merge_sort(arr, l, r): 85 | if l < r: 86 | mid = (l+r)//2 87 | 88 | move_negative_merge_sort(arr, l, mid) 89 | move_negative_merge_sort(arr, mid+1, r) 90 | #merge(arr, l, mid, r) 91 | merge_inplace(arr, l, mid, r) 92 | 93 | arr = [5, 5, -3, 4, -8, 0, -7, 3, -9, -3, 9, -2, 1] 94 | move_negative_merge_sort(arr, 0, len(arr)-1) 95 | print(arr) 96 | -------------------------------------------------------------------------------- /sort_algorithm/recursive_bubble_sort.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | """ 4 | 5 | def bubble_sort(arr, n): 6 | if n == 1: return 7 | 8 | for j in range(0, n - 1): 9 | if arr[j] > arr[j+1]: 10 | arr[j], arr[j+1] = arr[j+1], arr[j] 11 | 12 | bubble_sort(arr, n -1) 13 | 14 | 15 | 16 | arr = [64, 34, 25, 12, 22, 11, 90] 17 | bubble_sort(arr, len(arr)) 18 | print(arr) 19 | -------------------------------------------------------------------------------- /sort_algorithm/recursive_insertion_sort.py: -------------------------------------------------------------------------------- 1 | """ 2 | Sắp sếp cuối về trước 3 | """ 4 | def insertion_sort(arr, n): 5 | if n == 1: 6 | return 7 | 8 | insertion_sort(arr, n -1) 9 | key = arr[n -1] 10 | j = n - 2 11 | while j >= 0 and key < arr[j]: 12 | arr[j+1] = arr[j] 13 | j -= 1 14 | 15 | arr[j+1] = key 16 | 17 | 18 | arr = [12,11,13,5,6] 19 | 20 | insertion_sort(arr, len(arr)) 21 | print(arr) 22 | -------------------------------------------------------------------------------- /sort_algorithm/reversing_subarray.py: -------------------------------------------------------------------------------- 1 | def check_reverse(arr, n): 2 | tmp = sorted(arr) 3 | 4 | for front in range(n): 5 | if arr[front] != tmp[front]: 6 | break 7 | 8 | for back in range(n-1, -1, -1): 9 | if arr[back] != tmp[back]: 10 | break 11 | 12 | if front >= back: 13 | return True 14 | 15 | while front != back: 16 | front += 1 17 | if arr[front - 1] < arr[front]: 18 | return False 19 | 20 | return True 21 | 22 | def check_reverse(arr, n): 23 | if n == 1: 24 | return True 25 | 26 | i = 1 27 | for i in range(1, n): 28 | if arr[i -1] < arr[i]: 29 | if i == n: 30 | return True 31 | else: 32 | break 33 | print(i) 34 | j = i 35 | while j < n and arr[j] < arr[j-1]: 36 | if i > 1 and arr[j] < arr[i-2]: 37 | return False 38 | j+=1 39 | if j==n: 40 | return True 41 | print(i, j) 42 | k = j 43 | if arr[k] < arr[i-1]: 44 | return False 45 | 46 | while k > 1 and k < n: 47 | if arr[k] < arr[k -1]: 48 | return False 49 | k += 1 50 | 51 | return True 52 | arr = [1,2,3,4,20,9,16,17] 53 | print(check_reverse(arr, len(arr))) 54 | -------------------------------------------------------------------------------- /sort_algorithm/selection_sort.py: -------------------------------------------------------------------------------- 1 | """ 2 | Liên tục chọn phần từ nhỏ nhất và đặt ở vị trí đầu tiên 3 | """ 4 | 5 | def selection_sort(arr): 6 | for i in range(len(arr)): 7 | min_idx = i 8 | for j in range(i, len(arr)): 9 | if arr[min_idx] > arr[j]: 10 | min_idx = j 11 | 12 | arr[min_idx], arr[i] = arr[i], arr[min_idx] 13 | 14 | 15 | 16 | A = [64, 25, 12, 22, 11] 17 | selection_sort(A) 18 | print(A) 19 | -------------------------------------------------------------------------------- /sort_algorithm/sextuplets.py: -------------------------------------------------------------------------------- 1 | """ 2 | a * b + c = (f + e) * d 3 | """ 4 | 5 | def upper_bound(arr, length, value): 6 | low = 0 7 | high = length 8 | 9 | while low < high: 10 | mid = (low + high)//2 11 | if value >= arr[mid]: 12 | low = mid + 1 13 | else: 14 | high = mid 15 | 16 | return low 17 | 18 | def lower_bound(arr, length, value): 19 | low = 0 20 | high = length 21 | 22 | while low < high: 23 | mid = (low + high)//2 24 | if value > arr[mid]: 25 | low = mid + 1 26 | else: 27 | high = mid 28 | 29 | return low 30 | 31 | 32 | def find_sextuplets(arr, n): 33 | index = 0 34 | rhs = [0]*(n*n*n + 1) 35 | 36 | for i in range(n): 37 | if arr[i] != 0: 38 | for j in range(n): 39 | for k in range(n): 40 | rhs[index] = arr[i] * (arr[j] + arr[k]) 41 | index += 1 42 | 43 | rhs.sort() 44 | 45 | result = 0 46 | 47 | for i in range(n): 48 | for j in range(n): 49 | for k in range(n): 50 | val = arr[i]*arr[j] + arr[k] 51 | result += upper_bound(rhs, index, val) - lower_bound(rhs, index, val) 52 | 53 | return result 54 | 55 | arr = [2, 3] 56 | n = len(arr) 57 | 58 | print(find_sextuplets(arr, n)) 59 | -------------------------------------------------------------------------------- /sort_algorithm/shell_sort.py: -------------------------------------------------------------------------------- 1 | def shell_sort(arr): 2 | gap = len(arr)//2 3 | 4 | while gap > 0: 5 | i = 0 6 | j = gap 7 | 8 | while j < len(arr): 9 | if arr[i] > arr[j]: 10 | arr[i], arr[j] = arr[j], arr[i] 11 | 12 | i += 1 13 | j += 1 14 | 15 | print(i, j, gap) 16 | 17 | k = i 18 | while k - gap > -1: 19 | if arr[k - gap] > arr[k]: 20 | arr[k-gap], arr[k] = arr[k], arr[k-gap] 21 | 22 | k -= 1 23 | gap //= 2 24 | 25 | arr2 = [12, 34, 54, 2, 3] 26 | shell_sort(arr2) 27 | print(arr2) 28 | 29 | -------------------------------------------------------------------------------- /sort_algorithm/smallest_diff_pair.py: -------------------------------------------------------------------------------- 1 | def smallest_diff_pair(a, b): 2 | a.sort() 3 | b.sort() 4 | 5 | i=j=0 6 | 7 | result = 99999 8 | while i < len(a) and j < len(b): 9 | if abs(a[i] - b[j]) < result: 10 | result = abs(a[i] - b[j]) 11 | 12 | if a[i] < b[j]: 13 | i += 1 14 | else: 15 | j += 1 16 | 17 | return result 18 | 19 | a = [1, 2, 11, 5] 20 | b = [4, 12, 19, 23, 127, 235] 21 | 22 | print(smallest_diff_pair(a, b)) 23 | 24 | -------------------------------------------------------------------------------- /sort_algorithm/smallest_diff_triplet.py: -------------------------------------------------------------------------------- 1 | def smallest_diff_triplet(a, b, c, n): 2 | a.sort() 3 | b.sort() 4 | c.sort() 5 | 6 | res_min = 0 7 | res_max = 0 8 | res_mid = 0 9 | 10 | i=j=k=0 11 | 12 | diff = 999999999 13 | 14 | while i < n and j < n and k < n: 15 | s = a[i] + b[j] + c[k] 16 | 17 | maxe = max(a[i], b[j], c[k]) 18 | mine = min(a[i], b[j], c[k]) 19 | 20 | if mine==a[i]: 21 | i += 1 22 | elif mine == b[j]: 23 | j += 1 24 | else: 25 | k += 1 26 | 27 | if diff > maxe - mine: 28 | diff = maxe - mine 29 | res_max = maxe 30 | res_mid = s - maxe - mine 31 | res_min = mine 32 | 33 | return res_min, res_mid, res_max 34 | 35 | a = [5, 2, 8] 36 | b = [10, 7, 12] 37 | c = [9, 14, 6] 38 | 39 | print(smallest_diff_triplet(a, b, c, len(a))) 40 | -------------------------------------------------------------------------------- /sort_algorithm/sort_array_012s.py: -------------------------------------------------------------------------------- 1 | def sort(arr, n): 2 | low = 0 3 | mid = 0 4 | high = n - 1 5 | 6 | while mid <= high: 7 | if arr[mid] == 0: 8 | arr[low], arr[mid] = arr[mid], arr[low] 9 | low += 1 10 | mid += 1 11 | elif arr[mid] == 1: 12 | mid += 1 13 | else: 14 | arr[mid], arr[high] = arr[high], arr[mid] 15 | high -= 1 16 | 17 | arr = [0, 1, 1, 0, 1, 2, 1, 2, 0, 0, 0, 1] 18 | sort(arr, len(arr)) 19 | print(arr) 20 | -------------------------------------------------------------------------------- /sort_algorithm/sort_big_int.py: -------------------------------------------------------------------------------- 1 | """ 2 | https://www.geeksforgeeks.org/sorting-big-integers/ 3 | * if the lengths are different, just compare length 4 | * if the lengths are same, compare lexicon 5 | """ 6 | def sort_big_int(arr, n): 7 | arr.sort(key=lambda x: (len(x), x)) 8 | 9 | arr = ["54", "724523015759812365462", "870112101220845", "8723"] 10 | sort_big_int(arr, len(arr)) 11 | print(arr) 12 | -------------------------------------------------------------------------------- /sort_algorithm/sort_dates.py: -------------------------------------------------------------------------------- 1 | def get_max(arr, q): 2 | max_ele = 0 3 | for e in arr: 4 | max_ele = max(max_ele, e[q]) 5 | 6 | return max_ele 7 | 8 | def count_sort(arr, q, n): 9 | max_ele = get_max(arr, q) 10 | p = 1 11 | 12 | while max_ele > 0: 13 | count = [0]*10 14 | output = [[0, 0, 0] for _ in range(n)] 15 | 16 | for i in range(n): 17 | count[(arr[i][q]//p)%10] += 1 18 | 19 | for i in range(1, 10): 20 | count[i] += count[i-1] 21 | for i in range(n-1, -1, -1): 22 | output[count[(arr[i][q]//p)%10]-1] = arr[i] 23 | count[(arr[i][q]//p)%10] -= 1 24 | 25 | 26 | for i in range(n): 27 | arr[i] = output[i] 28 | 29 | p *= 10 30 | max_ele = max_ele//10 31 | 32 | def sort(arr, n): 33 | count_sort(arr, 0, n) 34 | count_sort(arr, 1, n) 35 | count_sort(arr, 2, n) 36 | 37 | #arr = [[ 20, 1, 2014 ],[ 25, 3, 2010 ],[ 3, 12, 2000 ],[ 18, 11, 2000 ],[ 19, 4, 2015 ],[ 9, 7, 2005 ]] 38 | arr = [[20, 1, 2014], [1, 4, 2015], [3, 12, 2000], [25, 3, 2010], [8, 11, 2000], [9, 7, 2005]] 39 | 40 | sort(arr, len(arr)) 41 | print(arr) 42 | -------------------------------------------------------------------------------- /sort_algorithm/sort_element_by_frequency.py: -------------------------------------------------------------------------------- 1 | class BSTNode: 2 | def __init__(self, key): 3 | self.key = key 4 | self.count = 1 5 | self.left = None 6 | self.right = None 7 | 8 | def insert(self, key): 9 | if self.key == key: 10 | self.count += 1 11 | elif key < self.key: 12 | if self.left == None: 13 | self.left = BSTNode(key) 14 | else: 15 | self.left.insert(key) 16 | else: 17 | if self.right == None: 18 | self.right = BSTNode(key) 19 | else: 20 | self.right.insert(key) 21 | 22 | def inorder(self): 23 | if self.left != None: 24 | self.left.inorder() 25 | print((self.key, self.count), end=' ') 26 | if self.right != None: 27 | self.right.inorder() 28 | 29 | class BSTree: 30 | def __init__(self): 31 | self.root = None 32 | 33 | def add(self, key): 34 | if self.root == None: 35 | self.root = BSTNode(key) 36 | else: 37 | self.root.insert(key) 38 | 39 | def inorder(self): 40 | if self.root != None: 41 | self.root.inorder() 42 | 43 | 44 | bstree = BSTree() 45 | arr = [2, 3, 2, 4, 5, 12, 2, 3, 3, 3, 12] 46 | print(arr) 47 | for i in arr: 48 | bstree.add(i) 49 | bstree.inorder() 50 | 51 | 52 | -------------------------------------------------------------------------------- /sort_algorithm/sort_n_number_n2.py: -------------------------------------------------------------------------------- 1 | def count_sort(arr, n, exp): 2 | output = [0]*n 3 | count = [0]*n 4 | 5 | for i in range(n): 6 | count[(arr[i]//exp) % n] += 1 7 | print(arr[i], (arr[i]//exp) % n) 8 | for i in range(1, n): 9 | count[i] += count[i-1] 10 | 11 | for i in range(n-1, -1, -1): 12 | output[count[(arr[i]//exp) %n] - 1] = arr[i] 13 | count[(arr[i]//exp) %n] -= 1 14 | 15 | for i in range(n): 16 | arr[i] = output[i] 17 | 18 | 19 | def sort(arr, n): 20 | count_sort(arr, n, 1) 21 | count_sort(arr, n, n) 22 | 23 | arr = [40, 12, 45, 32, 33, 1, 22] 24 | n = len(arr) 25 | sort(arr, n) 26 | 27 | print(arr) 28 | -------------------------------------------------------------------------------- /sort_algorithm/sort_one_swap.py: -------------------------------------------------------------------------------- 1 | def sort(arr, n): 2 | 3 | for i in range(1, n): 4 | 5 | if arr[i] < arr[i-1]: 6 | 7 | j = i - 1 8 | while j >= 0 and arr[i] < arr[j]: 9 | j -= 1 10 | 11 | arr[i], arr[j+1] = arr[j+1], arr[i] 12 | 13 | 14 | arr = [ 10, 30, 20, 40, 50, 60, 70 ] 15 | sort(arr, len(arr)) 16 | print(arr) 17 | -------------------------------------------------------------------------------- /sort_algorithm/sort_square_array.py: -------------------------------------------------------------------------------- 1 | def sort_square(arr, n): 2 | 3 | for k in range(n): 4 | if arr[k] >= 0: 5 | break 6 | 7 | i = k - 1 8 | j = k 9 | ind = 0 10 | 11 | tmp = [0]*n 12 | while i >= 0 and j < n: 13 | if arr[i]*arr[i] < arr[j]*arr[j]: 14 | tmp[ind] = arr[i]*arr[i] 15 | i -= 1 16 | else: 17 | tmp[ind] = arr[j]*arr[j] 18 | j += 1 19 | 20 | ind += 1 21 | 22 | while i >= 0: 23 | tmp[ind] = arr[i]*arr[i] 24 | ind += 1 25 | i -= 1 26 | 27 | while j < n: 28 | tmp[ind] = arr[j]*arr[j] 29 | ind += 1 30 | j += 1 31 | 32 | for i in range(n): 33 | arr[i] = tmp[i] 34 | 35 | def sort_square(arr, n): 36 | left = 0 37 | right = n - 1 38 | index = n - 1 39 | result = [0]*n 40 | 41 | while index >= 0: 42 | if abs(arr[left]) >= abs(arr[right]): 43 | result[index] = arr[left]*arr[left] 44 | left += 1 45 | else: 46 | result[index] = arr[right]*arr[right] 47 | right -= 1 48 | index -= 1 49 | 50 | for i in range(n): 51 | arr[i] = result[i] 52 | 53 | return arr 54 | 55 | arr = [-6, -3, -1, 2, 4, 5 ] 56 | sort_square(arr, len(arr)) 57 | print(arr) 58 | -------------------------------------------------------------------------------- /sort_algorithm/sort_using_max.py: -------------------------------------------------------------------------------- 1 | def sort(a, b, c): 2 | maxv = max(a, max(b, c)) 3 | minv = -max(-a, max(-b, -c)) 4 | midv = (a+b+c) - (maxv+minv) 5 | return minv, midv, maxv 6 | 7 | a, b, c = 4, 1, 9 8 | print(sort(a, b, c)) 9 | -------------------------------------------------------------------------------- /sort_algorithm/sort_waveform.py: -------------------------------------------------------------------------------- 1 | def sort_waveform(arr, n): 2 | for i in range(0, n, 2): 3 | if i - 1 >=0 and arr[i] < arr[i-1]: 4 | arr[i], arr[i-1] = arr[i-1], arr[i] 5 | 6 | if i + 1 < n and arr[i] < arr[i+1]: 7 | arr[i], arr[i+1] = arr[i+1], arr[i] 8 | 9 | arr = [10, 90, 49, 2, 1, 5, 23] 10 | sort_waveform(arr, len(arr)) 11 | print(arr) 12 | -------------------------------------------------------------------------------- /sort_algorithm/sort_without_copy.py: -------------------------------------------------------------------------------- 1 | def sort(arr, n): 2 | index = [0]*n 3 | for i in range(n): 4 | index[i] = i 5 | 6 | for i in range(n-1): 7 | min_index = i 8 | for j in range(i+1, n): 9 | if arr[index[min_index]] > arr[index[j]]: 10 | min_index = j 11 | 12 | index[min_index], index[i] = index[i], index[min_index] 13 | 14 | for i in range(n): 15 | print(arr[index[i]], end=" ") 16 | 17 | arr = ["geeks", "quiz", "geeks", "for"] 18 | sort(arr, len(arr)) 19 | -------------------------------------------------------------------------------- /sort_algorithm/sorted_array_given_equation.py: -------------------------------------------------------------------------------- 1 | """ 2 | https://www.geeksforgeeks.org/sort-array-applying-given-equation/ 3 | """ 4 | 5 | def sort_array(arr, n, A, B, C): 6 | for i in range(n): 7 | arr[i] = A*arr[i]*arr[i] + B*arr[i] + C 8 | 9 | index = 0 10 | maxe = arr[0] 11 | 12 | for i in range(n): 13 | if maxe < arr[i]: 14 | maxe = arr[i] 15 | index = i 16 | 17 | i = 0 18 | j = n - 1 19 | k = 0 20 | tmp = [0]*n 21 | 22 | while i <= index and j > index: 23 | if arr[i] < arr[j]: 24 | tmp[k] = arr[i] 25 | k += 1 26 | i += 1 27 | else: 28 | tmp[k] = arr[j] 29 | k += 1 30 | j -= 1 31 | 32 | while i <= index: 33 | tmp[k] = arr[i] 34 | k += 1 35 | i += 1 36 | 37 | while j > index: 38 | tmp[k] = arr[j] 39 | k += 1 40 | j -= 1 41 | 42 | 43 | for i in range(n): 44 | arr[i] = tmp[i] 45 | 46 | arr = [-21, -15, 12, 13, 14] 47 | A = -6 48 | B = -7 49 | C = 2 50 | sort_array(arr, len(arr), A, B, C) 51 | print(arr) 52 | -------------------------------------------------------------------------------- /sort_algorithm/stooge_sort.py: -------------------------------------------------------------------------------- 1 | def stooge_sort(arr, l, h): 2 | if l >= h: 3 | return 4 | 5 | if arr[l] > arr[h]: 6 | arr[l], arr[h] = arr[h], arr[l] 7 | 8 | if h - l > 1: 9 | t = (h -l + 1)//3 10 | stooge_sort(arr, l, h - t) 11 | stooge_sort(arr, l + t, h) 12 | stooge_sort(arr, l, h - t) 13 | 14 | arr = [2, 4, 5, 3, 1] 15 | stooge_sort(arr, 0, len(arr) - 1) 16 | print(arr) 17 | -------------------------------------------------------------------------------- /sort_algorithm/three_way_merge_sort.py: -------------------------------------------------------------------------------- 1 | def merge(arr, start, mid1, mid2, end): 2 | left_arr = arr[start:mid1] 3 | mid_arr = arr[mid1:mid2] 4 | right_arr = arr[mid2:end+1] 5 | 6 | left_arr.append(float('inf')) 7 | mid_arr.append(float('inf')) 8 | right_arr.append(float('inf')) 9 | 10 | ind_left, ind_mid, ind_right = 0, 0, 0 11 | for i in range(start, end+1): 12 | minimum = min(left_arr[ind_left], mid_arr[ind_mid], right_arr[ind_right]) 13 | if minimum == left_arr[ind_left]: 14 | arr[i] = minimum 15 | ind_left += 1 16 | elif minimum == mid_arr[ind_mid]: 17 | arr[i] = minimum 18 | ind_mid += 1 19 | else: 20 | arr[i] = minimum 21 | ind_right += 1 22 | 23 | def merge_sort(arr, start, end): 24 | if end - start <= 1: 25 | return 26 | mid1 = start + (end - start)//3 27 | mid2 = start + 2*(end - start)//3 28 | 29 | merge_sort(arr, start, mid1) 30 | merge_sort(arr, mid1, mid2) 31 | merge_sort(arr, mid2, end) 32 | merge(arr, start, mid1, mid2, end) 33 | 34 | return arr 35 | 36 | arr = [312,413,3,423,5,3,342,1,2,53] 37 | merge_sort(arr, 0, len(arr) -1) 38 | print(arr) 39 | -------------------------------------------------------------------------------- /sort_algorithm/three_way_quick_sort.py: -------------------------------------------------------------------------------- 1 | def partition(arr, fist, last, start, mid): 2 | pivot = arr[last] 3 | end = last 4 | 5 | while mid[0] <= end: 6 | if arr[mid[0]] < pivot: 7 | arr[mid[0]], arr[start[0]] = arr[start[0]], arr[mid[0]] 8 | 9 | mid[0] = mid[0] +1 10 | start[0] = start[0] + 1 11 | 12 | elif arr[mid[0]] > pivot: 13 | arr[mid[0]], arr[end] = arr[end], arr[mid[0]] 14 | 15 | end = end -1 16 | else: 17 | mid[0] = mid[0] + 1 18 | 19 | 20 | def quicksort(arr, first ,last): 21 | if first >= last: 22 | return 23 | 24 | if last == first + 1: 25 | if arr[first] > arr[last]: 26 | arr[first], arr[last] = arr[last], arr[first] 27 | return 28 | 29 | start = [first] 30 | mid = [first] 31 | 32 | partition(arr, first, last, start, mid) 33 | quicksort(arr, first, start[0] -1) 34 | quicksort(arr, mid[0], last) 35 | 36 | arr = [4,9,4,4,1,9,4,4,9,4,4,1,4] 37 | quicksort(arr, 0, len(arr) - 1) 38 | print(arr) 39 | 40 | -------------------------------------------------------------------------------- /sort_algorithm/tim_sort.py: -------------------------------------------------------------------------------- 1 | MIN_MERGE = 32 2 | def calc_min_run(n): 3 | r = 0 4 | while n >= MIN_MERGE: 5 | r |= n & 1 6 | n >>= 1 7 | 8 | return n + r 9 | 10 | def insertion_sort(arr, left, right): 11 | for i in range(left +1, right + 1): 12 | j = i 13 | while j > left and arr[j-1] > arr[j]: 14 | arr[j-1], arr[j] = arr[j], arr[j-1] 15 | j -= 1 16 | 17 | return arr 18 | 19 | def merge(arr, l, m , r): 20 | len1, len2 = m - l + 1, r - m 21 | left, right = [], [] 22 | for i in range(0, len1): 23 | left.append(arr[l+i]) 24 | 25 | for i in range(0, len2): 26 | right.append(arr[m+i+1]) 27 | 28 | 29 | i,j,k = 0,0,l 30 | 31 | while i < len1 and j < len2: 32 | if left[i] <= right[j]: 33 | arr[k] = left[i] 34 | i += 1 35 | else: 36 | arr[k] = right[j] 37 | j += 1 38 | 39 | k += 1 40 | 41 | while i < len1: 42 | arr[k] = left[i] 43 | k += 1 44 | i += 1 45 | 46 | while j < len2: 47 | arr[k] = right[j] 48 | k += 1 49 | j += 1 50 | 51 | 52 | def tim_sort(arr): 53 | n = len(arr) 54 | min_run = calc_min_run(n) 55 | for start in range(0, n, min_run): 56 | end = min(start + min_run - 1, n - 1) 57 | insertion_sort(arr, start, end) 58 | 59 | size = min_run 60 | while size < n: 61 | 62 | for left in range(0, n, 2*size): 63 | mid = min(n-1, left + size - 1) 64 | right = min((left +2*size -1), (n - 1)) 65 | 66 | if mid < right: 67 | merge(arr, left, mid, right) 68 | 69 | size = 2*size 70 | 71 | 72 | arr = [-2, 7, 15, -14, 0, 15, 0, 73 | 7, -7, -4, -13, 5, 8, -14, 12] 74 | 75 | tim_sort(arr) 76 | print(arr) 77 | -------------------------------------------------------------------------------- /sort_algorithm/tree_sort.py: -------------------------------------------------------------------------------- 1 | class BSTNode(): 2 | def __init__(self, key): 3 | self.key = key 4 | self.right = None 5 | self.left = None 6 | self.parent = None 7 | 8 | def insert(self, node): 9 | if self.key > node.key: 10 | if self.left == None: 11 | self.left = node 12 | node.parent = self 13 | else: 14 | self.left.insert(node) 15 | else: 16 | if self.right == None: 17 | self.right = node 18 | node.parent = self 19 | else: 20 | self.right.insert(node) 21 | 22 | def inorder(self): 23 | if self.left is not None: 24 | self.left.inorder() 25 | print(self.key, end=' ') 26 | if self.right is not None: 27 | self.right.inorder() 28 | 29 | class BSTree(): 30 | def __init__(self): 31 | self.root = None 32 | 33 | def inorder(self): 34 | if self.root is not None: 35 | self.root.inorder() 36 | 37 | def add(self, key): 38 | new_node = BSTNode(key) 39 | if self.root is None: 40 | self.root = new_node 41 | else: 42 | self.root.insert(new_node) 43 | 44 | bstree = BSTree() 45 | arr = [4, 2, 3, 4, 5, 6, 1, 7, 9, 10, 3] 46 | for i in arr: 47 | bstree.add(i) 48 | bstree.inorder() 49 | 50 | 51 | -------------------------------------------------------------------------------- /sort_algorithm/triplet_sum_zero.py: -------------------------------------------------------------------------------- 1 | def zero_sum(arr, n): 2 | for i in range(n-1): 3 | s = set() 4 | for j in range(i+1, n): 5 | x = - (arr[i] + arr[j]) 6 | if x in s: 7 | print(arr[i], arr[j], x) 8 | else: 9 | s.add(arr[j]) 10 | 11 | def zero_sum(arr, n): 12 | arr.sort() 13 | 14 | for i in range(n-1): 15 | l = i+1 16 | r = n-1 17 | x = arr[i] 18 | 19 | while l < r: 20 | if x + arr[l] + arr[r] == 0: 21 | print(x, arr[r], arr[l]) 22 | l += 1 23 | r -= 1 24 | elif x + arr[l] + arr[r] < 0: 25 | l += 1 26 | else: 27 | r -= 1 28 | 29 | 30 | arr = [0, -1, 2, -3, 1] 31 | print(zero_sum(arr, len(arr))) 32 | -------------------------------------------------------------------------------- /sort_algorithm/worst_case_mergesort.py: -------------------------------------------------------------------------------- 1 | def join(arr, left, right, l, m, r): 2 | for i in range(m-l+1): 3 | arr[i] = left[i] 4 | 5 | i+=1 6 | for j in range(r-m): 7 | arr[i+j] = right[j] 8 | 9 | def split(arr, left, right, l, m, r): 10 | for i in range(m-l+1): 11 | left[i] = arr[i*2] 12 | 13 | for i in range(r-m): 14 | right[i] = arr[i*2+1] 15 | 16 | def worst_case(arr, l, r): 17 | if l < r: 18 | m = (l+r)//2 19 | left = [0]*(m-l+1) 20 | right = [0]*(r-m) 21 | 22 | split(arr, left, right, l, m, r) 23 | worst_case(left, l, m) 24 | worst_case(right, m+1, r) 25 | 26 | join(arr, left, right, l, m, r) 27 | 28 | arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; 29 | worst_case(arr, 0, len(arr)-1) 30 | print(arr) 31 | --------------------------------------------------------------------------------