├── Z_tests ├── __init__.py ├── test_E_searching.py └── test_D_arrays.py ├── _config.yml ├── J_linked_list ├── problems │ ├── B_nth_node_from_the_end_of_linked_list.py │ ├── F_recursive_traversal_in_a_singly_linked_list.py │ ├── J_lru_cache_design.py │ ├── L_palindrome_linked_list.py │ ├── A_middle_of_linked_list.py │ ├── H_the_intersection_of_two_linked_list.py │ ├── I_pairwise_swap_nodes_of_linked_list.py │ ├── D_recursive_method_to_reverse_a_linked_list.py │ ├── O_reverse_a_doubly_linked_list.py │ ├── C_an_iterative_method_to_reverse_a_linked_list_.py │ └── E_reverse_in_group_of_size_k.py ├── C_circular_linked_list.py ├── B_doubly_linked_list.py ├── A_implementation.py └── loop_problems │ ├── A_detecting_loops.py │ └── B_detecting_loops_using_floyd_cycle_detection.py ├── T_dynamic_programming ├── problems │ ├── B_coin_change_count_combinations.py │ ├── I_maximum_sum_with_no_consecutive.py │ ├── knapsack_problem │ │ ├── B_efficient_approach.py │ │ └── A_naive_approach.py │ ├── J_subset_sum_problem.py │ ├── long_increasing_subsequence_problem │ │ ├── A_naive_approach.py │ │ └── B_efficient_approach.py │ ├── C_maximum_cuts.py │ ├── G_egg_dropping_problem.py │ ├── D_minimum_coins_to_make_a_value.py │ ├── K_matrix_chain_multiplication.py │ ├── E_minimum_jumps_to_reach_at_the_end.py │ ├── A_longest_common_subsequence.py │ ├── edit_distance_problem │ │ ├── A_naive_approach.py │ │ └── B_dp_approach.py │ └── F_optimal_strategy_for_a_game.py └── A_memoization.py ├── .gitignore ├── .github └── FUNDING.yml ├── B_bit_magic ├── D_operation_complement.py ├── A_operation_and.py ├── B_operation_or.py ├── C_operation_xor.py ├── G_brian_kerningham.py ├── E_operation_leftshit_rightshift.py ├── F_count_setbit.py ├── H_using_lookuptable.py └── Z_bit_magic.md ├── D_arrays ├── types_of_arrays │ ├── B_dynamic_size_array.py │ └── A_fixed_size_array.py ├── operation_on_arrays │ ├── B_insertion.py │ ├── C_deletion.py │ └── A_searching.py └── problems │ ├── left_rotate_the_elements_of_an_array.py │ ├── prefix_sum.py │ ├── leaders_in_an_array.py │ ├── maximum_consecutive_ones.py │ ├── max_difference_in_array.py │ ├── frequencies_in_sorted_array.py │ ├── longest_even_odd_subarray.py │ ├── sliding_window.py │ ├── maximum_subarray_sum.py │ ├── max_profit_stock.py │ ├── consecutive_flips.py │ ├── left_rotate_by_d_places.py │ ├── trapping_rain_water.py │ ├── check_if_sorted.py │ ├── majority_element.py │ └── maximum_circular_subarray_sum.py ├── C_recursion ├── A_factorial.py ├── F_checking_palindrome.py ├── K_josephus.py ├── H_rod_cutting.py ├── B_fibonnaci.py ├── D_print_1_to_n.py ├── I_subset_of_set.py ├── G_sum_of_digits.py ├── C_print_n_to_1.py ├── E_tail_recursion.py ├── J_tower_of_hanoi.py └── Z_recursion.md ├── I_string ├── G_palindrome_check.py ├── B_given_a_string_find_the_leftmost_character_that_repeats.py ├── F_given_two_strings_check_if_they_are_rotations_of_each_other_or_not.py ├── C_given_a_string_find_the_leftmost_character_that_does_not_repeat.py ├── D_given_a_string_find_the_lexicographic_rank.py ├── H_rabin_karp_algorithm.py ├── A_given_a_string_check_if_they_are_an_anagram_of_each_other.py ├── E_given_a_text_string_and_a_pattern_string_find_if_a_permutation_of_the_pattern_exists_in_the_text.py ├── I_kmp_algorithm.py └── Z_string.md ├── .travis.yml ├── G_matrix ├── B_pass_matrix_as_argument.py ├── D_transposing_a_matrix.py ├── C_printing_matrix_in_a_snake_pattern.py ├── I_matrix_multiplication.py ├── J_search_in_row-wise_and_column-wise_sorted_matrix.py ├── A_multidimensional_matrix.py ├── F_check_if_the_element_is_present_in_a_row_and_column-wise_sorted_matrix.py ├── G_boundary_traversal.py ├── E_rotating_a_matrix.py ├── H_spiral_traversal.py └── Z_matrix.md ├── A_mathematics ├── B_palindrome.py ├── E_factorial.py ├── C_gcd.py ├── G_prime_factors.py ├── Z_mathematics.md ├── H_sieve_of_erathosthenes.py ├── D_lcm.py ├── A_count_digits.py └── F_prime_number.py ├── V_segment_tree ├── Z_segment_tree.md └── A_construction.py ├── R_greedy ├── Z_greedy.md ├── A_activity_selection_problem.py ├── C_job_sequencing_problem.py └── B_fractional_knapsack.py ├── S_backtracking ├── Z_backtracking.md ├── A_rat_in_a_maze.py └── B_n_queen_problem.py ├── W_disjoint_set └── Z_disjoint_set.md ├── M_dequeue ├── Z_dequeue.md ├── problems │ └── A_maximum_of_all_subarray_of_size_k.py └── A_implementation.py ├── F_sorting ├── A_bubblesort.py ├── C_insertionsort.py ├── B_selectionsort.py ├── problems │ ├── C_count_inversions_in_arrays.py │ ├── F_sorting_arrays_with_2_and_3_types_of_elements.py │ ├── E_chocolate_distribution_problem.py │ ├── D_kth_smallest_element.py │ ├── B_union_of_2_sorted_arrays.py │ ├── G_merge_overlapping_intervals.py │ ├── H_meeting_the_maximum_guests.py │ └── A_intersection_of_2_sorted_arrays.py ├── H_countingsort.py ├── F_heapsort.py ├── D_mergesort.py ├── E_lomutoandhoare.py ├── I_radixsort.py └── G_cyclesort.py ├── H_hashing └── problems │ ├── F_subarray_with_zero-sum.py │ ├── A_count_distinct_elements.py │ ├── B_count_of_the_frequency_of_array_elements.py │ ├── C_the_intersection_of_two_arrays.py │ ├── K_longest_consecutive_subsequence.py │ ├── M_more_than_nk_occurences.py │ ├── D_union_of_two_unsorted_arrays.py │ ├── H_longest_subarray_with_a_given_sum.py │ ├── E_pair_with_given_sum_in_an_unsorted_array.py │ ├── G_subarray_with_given_sum.py │ ├── J_longest_common_span_with_the_same_sum_in_a_binary_array.py │ ├── L_count_distinct_elements_in_every_window.py │ └── I_longest_subarray_with_an_equal_number_of_0’s_and_1’s.py ├── E_searching ├── problems │ ├── C_count_of_occurrences_of_x_in_sorted_element.py │ ├── A_index_of_first_occurence_in_sorted_array.py │ ├── B_index_of_last_occurence_in_sorted_array.py │ ├── J_majority_element.py │ ├── D_count_of_1s_in_a_binary_sorted_array.py │ ├── F_peak_element.py │ ├── G_find_an_element_in_an_infinite_sized_sorted_array.py │ ├── I_median_of_two_sorted_arrays.py │ ├── H_the_square_root_of_an_integer.py │ └── E_find_an_element_in_sorted_and_rotated_array.py ├── iterative │ └── A_binary_search_iterative.py ├── recursive │ └── A_binary_search_recursive.py └── two_pointer_approach_problems │ ├── C_find_triplet_in_an_array_which_gives_sum_x.py │ ├── B_find_pair_in_a_sorted_array_which_gives_sum_x.py │ └── A_find_pair_in_an_unsorted_array_which_gives_sum_x.py ├── L_queue ├── Z_queue.md ├── A_implementation.py └── problems │ ├── B_generate_numbers_with_given_digits.py │ ├── A_reversing_a_queue.py │ └── C_circular_tour.py ├── U_trie ├── Z_trie.md ├── A_representation.py └── E_count_distinct_rows_in_a_binary_matrix.py ├── Q_graphs ├── problems │ ├── topological_sorting │ │ ├── B_dfs_based_algorithm.py │ │ └── A_kahn's_bfs_based_algorithm.py │ ├── E_bellmanford_shortest_path_algorithm.py │ └── detecting_cycle │ │ └── A_in_the_undirected_graph.py ├── A_adjacency_matrix.py └── B_adjacency_list.py ├── N_tree ├── implementation │ ├── A_inorder_traversal.py │ ├── B_preorder_traversal.py │ ├── C_postorder_traversal.py │ ├── D_level_order_traversal.py │ └── E_tree_traversal_in_spiral_form.py └── problems │ ├── A_size_of_binary_tree.py │ ├── C_height_of_binary_tree.py │ ├── B_maximum_in_binary_tree.py │ ├── E_print_left_view_of_binary_tree.py │ ├── R_iterative_preorder_traversal.py │ ├── L_the_diameter_of_a_binary_tree.py │ ├── G_check_for_balanced_binary_tree.py │ ├── Q_iterative_inorder_traversal.py │ ├── F_children_sum_property.py │ ├── O_count_nodes_in_a_complete_binary_tree.py │ ├── P_serialize_and_deserialize_a_binary_tree.py │ ├── M_lca_problem_with_an_efficient_solution.py │ ├── H_maximum_width_of_binary_tree.py │ ├── K_tree_traversal_spiral_form.py │ ├── N_burn_a_binary_tree_from_a_leaf.py │ ├── J_construct_binary_tree_from_inorder_and_preorder.py │ └── I_convert_binary_tree_to_doubly_linked_list.py ├── P_heap ├── problems │ ├── C_k_largest_elements.py │ ├── A_sort_ksorted_array.py │ ├── B_buy_maximum_items_with_given_sum.py │ └── E_median_of_a_stream.py ├── A_heap_sort.py ├── B_priority_queue.py ├── binary_heap │ └── A_insertion.py └── Z_heap.md ├── O_binary_search_tree ├── B_insertion_in_bst.py ├── problems │ ├── A_the_ceiling_of_a_key_in_bst.py │ ├── B_ceiling_on_the_left_side_in_an_array.py │ ├── D_check_for_bst.py │ ├── G_vertical_sum_in_a_binary_tree.py │ ├── I_top_view_of_binary_tree.py │ ├── H_vertical_traversal_of_binary_tree.py │ ├── C_find_kth_smallest_in_bst.py │ └── J_bottom_view_of_binary_tree.py ├── A_implementation.py └── D_floor_in_bst.py ├── K_stack ├── problems │ ├── G_largest_rectangular_area_in_a_histogram.py │ ├── D_stock_span_problem_with_variations.py │ ├── E_previous_greater_element_.py │ ├── A_balanced_parenthesis_.py │ └── B_two_stacks_in_an_array_.py ├── infix_prefix_and_postfix │ ├── D_evaluation_of_prefix.py │ └── B_evaluation_of_postfix.py └── Z_stack.md └── LICENSE /Z_tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal -------------------------------------------------------------------------------- /J_linked_list/problems/B_nth_node_from_the_end_of_linked_list.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /T_dynamic_programming/problems/B_coin_change_count_combinations.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | .pytest_cache 3 | main.py 4 | .vscode/settings.json 5 | .gitignore 6 | script.sh -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: thisisshub 4 | custom: [paypal.me/thisisshub] 5 | -------------------------------------------------------------------------------- /B_bit_magic/D_operation_complement.py: -------------------------------------------------------------------------------- 1 | def method1(n: int) -> bin: 2 | return bin(~n) 3 | 4 | 5 | if __name__ == "__main__": 6 | """ 7 | from timeit import timeit 8 | print(timeit(lambda: method1(60), number=10000)) # 0.0014995479998560768 9 | """ 10 | -------------------------------------------------------------------------------- /B_bit_magic/A_operation_and.py: -------------------------------------------------------------------------------- 1 | def method1(n: int, m: int) -> bin: 2 | return bin(n & m) 3 | 4 | 5 | if __name__ == "__main__": 6 | """ 7 | from timeit import timeit 8 | print(timeit(lambda: method1(25, 30), number=10000)) # 0.0016055950000009034 9 | """ 10 | -------------------------------------------------------------------------------- /B_bit_magic/B_operation_or.py: -------------------------------------------------------------------------------- 1 | def method1(n: int, m: int) -> bin: 2 | return bin(n | m) 3 | 4 | 5 | if __name__ == "__main__": 6 | """ 7 | from timeit import timeit 8 | print(timeit(lambda: method1(25, 30), number=10000)) # 0.0016012300000056712 9 | """ 10 | -------------------------------------------------------------------------------- /B_bit_magic/C_operation_xor.py: -------------------------------------------------------------------------------- 1 | def method1(n: int, m: int) -> bin: 2 | return bin(n ^ m) 3 | 4 | 5 | if __name__ == "__main__": 6 | """ 7 | from timeit import timeit 8 | print(timeit(lambda: method1(60, 13), number=10000)) # 0.0017356749999635213 9 | """ 10 | -------------------------------------------------------------------------------- /D_arrays/types_of_arrays/B_dynamic_size_array.py: -------------------------------------------------------------------------------- 1 | def method1(n: list): 2 | return n 3 | 4 | 5 | if __name__ == "__main__": 6 | """ 7 | from timeit import timeit 8 | print(timeit(lambda: method1([1, 2, 3, 4, 5]), number=10000)) # 0.0021682340002371348 9 | """ 10 | -------------------------------------------------------------------------------- /C_recursion/A_factorial.py: -------------------------------------------------------------------------------- 1 | def method1(n: int) -> int: 2 | return 1 if n == 0 or n == 1 else n * method1(n - 1) 3 | 4 | 5 | if __name__ == "__main__": 6 | """ 7 | from timeit import timeit 8 | print(timeit(lambda: method1(10), number=10000)) # 0.012313627999901655 9 | """ 10 | -------------------------------------------------------------------------------- /I_string/G_palindrome_check.py: -------------------------------------------------------------------------------- 1 | def method1(s: str) -> bool: 2 | return True if s == s[::-1] else False 3 | 4 | 5 | if __name__ == "__main__": 6 | """ 7 | from timeit import timeit 8 | print(timeit(lambda: method1("AABAA"), number=10000)) # 0.0018115240000042832 9 | """ 10 | -------------------------------------------------------------------------------- /C_recursion/F_checking_palindrome.py: -------------------------------------------------------------------------------- 1 | def method1(n: str) -> bool: 2 | return True if str(n) == str(n)[::-1] else False 3 | 4 | 5 | if __name__ == "__main__": 6 | """ 7 | from timeit import timeit 8 | print(timeit(lambda: method1(1111), number=10000)) # 0.004767893999087391 9 | """ 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: 2 | - python 3 | 4 | install: 5 | - pip install pytest codecov coverage 6 | 7 | script: 8 | - python3 -m pytest --color=yes --verbose Z_tests/ 9 | 10 | notifications: 11 | email: 12 | recipients: 13 | thisisshub@gmail.com 14 | on_success: never 15 | on_failure: always -------------------------------------------------------------------------------- /G_matrix/B_pass_matrix_as_argument.py: -------------------------------------------------------------------------------- 1 | matrix = [[1, 2, 3], [4, 5, 6]] 2 | 3 | 4 | def method1(matrix: list) -> list: 5 | return matrix 6 | 7 | 8 | if __name__ == "__main__": 9 | """ 10 | from timeit import timeit 11 | print(timeit(lambda: method1(matrix), number=10000)) # 0.002698033000342548 12 | """ 13 | -------------------------------------------------------------------------------- /B_bit_magic/G_brian_kerningham.py: -------------------------------------------------------------------------------- 1 | def method1(n: int) -> int: 2 | c = 0 3 | while n: 4 | n &= n - 1 5 | c += 1 6 | return c 7 | 8 | 9 | if __name__ == "__main__": 10 | """ 11 | from timeit import timeit 12 | print(timeit(lambda: method1(9), number=10000)) # 0.0021619279996230034 13 | """ 14 | -------------------------------------------------------------------------------- /A_mathematics/B_palindrome.py: -------------------------------------------------------------------------------- 1 | def method1(n: str) -> bool: 2 | '''Checks for palindrome by reversing the string''' 3 | 4 | return True if n == n[::-1] else False 5 | 6 | 7 | if __name__ == "__main__": 8 | """ 9 | from timeit import timeit 10 | print(timeit(lambda: method1('aibohphobia'), number=10000)) 11 | """ 12 | -------------------------------------------------------------------------------- /D_arrays/types_of_arrays/A_fixed_size_array.py: -------------------------------------------------------------------------------- 1 | def method1(): 2 | import array 3 | 4 | arr = array.array("i", (1, 2, 3, 4, 5)) 5 | return arr 6 | 7 | 8 | if __name__ == "__main__": 9 | """ 10 | from timeit import timeit 11 | print(timeit(lambda: method1(), number=10000)) # 0.0056163460003517685 12 | """ 13 | -------------------------------------------------------------------------------- /V_segment_tree/Z_segment_tree.md: -------------------------------------------------------------------------------- 1 | # List of Contents 2 | 3 | - [Construction](https://github.com/thisisshub/DSA/blob/main/V_segment_tree/A_construction.py) 4 | - [Range Query](https://github.com/thisisshub/DSA/blob/main/V_segment_tree/B_range_query.py) 5 | - [Update Query](https://github.com/thisisshub/DSA/blob/main/V_segment_tree/C_update_query.py) -------------------------------------------------------------------------------- /C_recursion/K_josephus.py: -------------------------------------------------------------------------------- 1 | def method1(n: int, k: int) -> int: 2 | if n == 1: 3 | return 1 4 | else: 5 | return (method1(n - 1, k) + k - 1) % n + 1 6 | 7 | 8 | if __name__ == "__main__": 9 | """ 10 | from timeit import timeit 11 | print(timeit(lambda: method1(14, 2), number=10000)) # 0.02025889400010783 12 | """ 13 | -------------------------------------------------------------------------------- /R_greedy/Z_greedy.md: -------------------------------------------------------------------------------- 1 | # List of Contents 2 | 3 | - [Activity Selection Problem](https://github.com/thisisshub/DSA/blob/main/R_greedy/A_activity_selection_problem.py) 4 | - [Fractional Knapsack](https://github.com/thisisshub/DSA/blob/main/R_greedy/B_fractional_knapsack.py) 5 | - [Job Sequencing Problem](https://github.com/thisisshub/DSA/blob/main/R_greedy/C_job_sequencing_problem.py) -------------------------------------------------------------------------------- /D_arrays/operation_on_arrays/B_insertion.py: -------------------------------------------------------------------------------- 1 | def method1(n: int, l: list) -> list: 2 | print(l.insert(4, 8)) # [0, 1, 2, 3, 15, 4, 5, 6, 7, 8, 9] 3 | 4 | 5 | if __name__ == "__main__": 6 | """ 7 | n = 15 8 | l = [i for i in range(10)] 9 | from timeit import timeit 10 | print(timeit(lambda: method1(n, l), number=10000)) # 0.011750334000680596 11 | """ 12 | -------------------------------------------------------------------------------- /S_backtracking/Z_backtracking.md: -------------------------------------------------------------------------------- 1 | # List of Contents 2 | 3 | - [Activity Selection Problem](https://github.com/thisisshub/DSA/blob/main/R_greedy/A_activity_selection_problem.py) 4 | - [Fractional Knapsack](https://github.com/thisisshub/DSA/blob/main/R_greedy/B_fractional_knapsack.py) 5 | - [Job Sequencing Problem](https://github.com/thisisshub/DSA/blob/main/R_greedy/C_job_sequencing_problem.py) -------------------------------------------------------------------------------- /W_disjoint_set/Z_disjoint_set.md: -------------------------------------------------------------------------------- 1 | # List of Contents 2 | 3 | - [Find And Union Operations](https://github.com/thisisshub/DSA/blob/main/W_disjoint_set/A_find_and_union_operations.py) 4 | - [Union By Rank And Path Compression](https://github.com/thisisshub/DSA/blob/main/W_disjoint_set/B_union_by_rank_and_path_compression.py) 5 | - [Kruskal Algorithm](https://github.com/thisisshub/DSA/blob/main/W_disjoint_set/C_kruskal_algorithm.py) -------------------------------------------------------------------------------- /M_dequeue/Z_dequeue.md: -------------------------------------------------------------------------------- 1 | # List of Contents 2 | 3 | - [Implementation](https://github.com/thisisshub/DSA/blob/main/M_dequeue/A_implementation.py) 4 | 5 | ## Problems 6 | - [Maximum Of All Subarray Of Size K](https://github.com/thisisshub/DSA/blob/main/M_dequeue/problems/A_maximum_of_all_subarray_of_size_k.py) 7 | - [Desgin A Ds That Takes Min](https://github.com/thisisshub/DSA/blob/main/M_dequeue/problems/B_desgin_a_DS_that_takes_min.py) 8 | -------------------------------------------------------------------------------- /D_arrays/problems/left_rotate_the_elements_of_an_array.py: -------------------------------------------------------------------------------- 1 | def method1(): 2 | a = [1, 2, 3, 4, 5] 3 | for _ in range(1): 4 | f = a[0] 5 | for j in range(0, len(a) - 1): 6 | a[j] = a[j + 1] 7 | a[len(a) - 1] = f 8 | return a 9 | 10 | 11 | if __name__ == "__main__": 12 | """ 13 | from timeit import timeit 14 | print(timeit(lambda: method1(), number=10000)) 0.008410404003370786 15 | """ 16 | -------------------------------------------------------------------------------- /I_string/B_given_a_string_find_the_leftmost_character_that_repeats.py: -------------------------------------------------------------------------------- 1 | def method1(string: str) -> str: 2 | h = {} 3 | for i in string: 4 | if i in h: 5 | return i 6 | else: 7 | h[i] = 0 8 | return "\0" 9 | 10 | 11 | if __name__ == "__main__": 12 | """ 13 | from timeit import timeit 14 | print(timeit(lambda: method1("thisisastring"), number=10000)) # 0.0030865349999658065 15 | """ 16 | -------------------------------------------------------------------------------- /F_sorting/A_bubblesort.py: -------------------------------------------------------------------------------- 1 | def method1(l: list) -> list: 2 | n = len(l) 3 | for i in range(n - 1): 4 | for j in range(0, n - i - 1): 5 | if l[j] > l[j + 1]: 6 | l[j], l[j + 1] = l[j + 1], l[j] 7 | return l 8 | 9 | 10 | if __name__ == "__main__": 11 | """ 12 | l = [1, 3, 4, 7, 5, 9] 13 | from timeit import timeit 14 | timeit(lambda: method1(l), number=10000) # 0.02512622900030692 15 | """ 16 | -------------------------------------------------------------------------------- /I_string/F_given_two_strings_check_if_they_are_rotations_of_each_other_or_not.py: -------------------------------------------------------------------------------- 1 | def method1(str1: str, str2: str) -> bool: 2 | if len(str1) != len(str2): 3 | return False 4 | temp = str1 + str2 5 | return True if temp.count(str2) else False 6 | 7 | 8 | if __name__ == "__main__": 9 | """ 10 | from timeit import timeit 11 | print(timeit(lambda: method1("ABCD", "DCBA"), number=10000)) # 0.0039531319998786785 12 | """ 13 | -------------------------------------------------------------------------------- /J_linked_list/C_circular_linked_list.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.next = None 5 | 6 | 7 | class CircularLinkedList: 8 | def __init__(self): 9 | self.head = None 10 | 11 | 12 | if __name__ == "__main__": 13 | """ 14 | from timeit import timeit 15 | clist = CircularLinkedList() 16 | print(timeit(lambda: clist, number=10000)) # 0.0003614770000126555 17 | """ 18 | -------------------------------------------------------------------------------- /B_bit_magic/E_operation_leftshit_rightshift.py: -------------------------------------------------------------------------------- 1 | def method_leftshift(n: int) -> bin: 2 | return bin(n << 2) 3 | 4 | 5 | def method_rightshift(n: int) -> bin: 6 | return bin(n >> 2) 7 | 8 | 9 | if __name__ == "__main__": 10 | """ 11 | from timeit import timeit 12 | print(timeit(lambda: method_leftshift(60), number=10000)) # 0.0023728119999759656 13 | print(timeit(lambda: method_rightshift(60), number=10000)) # 0.0018800369998643873 14 | """ 15 | -------------------------------------------------------------------------------- /H_hashing/problems/F_subarray_with_zero-sum.py: -------------------------------------------------------------------------------- 1 | def method1(arr,n): 2 | n_sum = 0 3 | s = set() 4 | for i in range(n): 5 | n_sum += arr[i] 6 | if n_sum == 0 or n_sum in s: 7 | return True 8 | s.add(n_sum) 9 | return False 10 | 11 | if __name__ == "__main__": 12 | """ 13 | from timeit import timeit 14 | arr = [-3, 2, 3, 1, 6] 15 | n = len(arr) 16 | print(timeit(lambda: method1(arr, n), number=10000)) # 0.01074043799599167 17 | """ -------------------------------------------------------------------------------- /F_sorting/C_insertionsort.py: -------------------------------------------------------------------------------- 1 | def method1(l: list): 2 | for i in range(1, len(l)): 3 | key = l[i] 4 | j = i - 1 5 | while j >= 0 and key < l[j]: 6 | l[j + 1] = l[j] 7 | j -= 1 8 | l[j + 1] = key 9 | return l 10 | 11 | 12 | if __name__ == "__main__": 13 | """ 14 | l = [1, 3, 4, 7, 5, 9] 15 | from timeit import timeit 16 | print(timeit(method1(l), number=10000)) # 0.013673285000550095 17 | """ 18 | -------------------------------------------------------------------------------- /J_linked_list/B_doubly_linked_list.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, next=None, prev=None, data=None): 3 | self.next = next # reference to next node in DLL 4 | self.prev = prev # reference to previous node in DLL 5 | self.data = data 6 | 7 | 8 | if __name__ == "__main__": 9 | """ 10 | from timeit import timeit 11 | DoublyLl = Node() 12 | print(timeit(lambda: DoublyLl, number=10000)) # 0.00042409200068505015 13 | """ 14 | -------------------------------------------------------------------------------- /G_matrix/D_transposing_a_matrix.py: -------------------------------------------------------------------------------- 1 | def method1(): 2 | matrix = [[1, 2, 3], [4, 5, 6], [8, 9, 0]] 3 | 4 | ans = [[0, 0, 0], [0, 0, 0], [0, 0, 0]] 5 | 6 | for i in range(len(matrix)): 7 | for j in range(3): 8 | ans[j][i] = matrix[i][j] 9 | 10 | for r in ans: 11 | print(r) 12 | 13 | 14 | if __name__ == "__main__": 15 | """ 16 | from timeit import timeit 17 | print(timeit(lambda: method1(), number=10000)) # 0.4282153890017071 18 | """ 19 | -------------------------------------------------------------------------------- /H_hashing/problems/A_count_distinct_elements.py: -------------------------------------------------------------------------------- 1 | def method1(ll: list, n: int) -> int: 2 | s = set() 3 | c = 0 4 | for i in range(n): 5 | if ll[i] not in s: 6 | s.add(ll[i]) 7 | c += 1 8 | return c 9 | 10 | 11 | if __name__ == "__main__": 12 | """ 13 | from timeit import timeit 14 | ll = [6, 10, 5, 4, 9, 120, 4, 6, 10] 15 | n = len(ll) 16 | print(timeit(lambda: method1(ll, n), number=10000)) # 0.01385382900480181 17 | """ 18 | -------------------------------------------------------------------------------- /E_searching/problems/C_count_of_occurrences_of_x_in_sorted_element.py: -------------------------------------------------------------------------------- 1 | def method1(arr: list, n: int, x: int) -> int: 2 | res = 0 3 | for i in range(n): 4 | if x == arr[i]: 5 | res += 1 6 | return res 7 | 8 | 9 | if __name__ == "__main__": 10 | """ 11 | arr = [1, 2, 2, 2, 2, 3, 4, 7 ,8 ,8] 12 | n = len(arr) 13 | x = 2 14 | from timeit import timeit 15 | print(timeit(lambda: method1(arr, n, x), number=10000)) # 0.009037977999923896 16 | """ 17 | -------------------------------------------------------------------------------- /L_queue/Z_queue.md: -------------------------------------------------------------------------------- 1 | # List of Contents 2 | 3 | - [Implementation](https://github.com/thisisshub/DSA/blob/main/L_queue/A_implementation.py) 4 | 5 | ## Problems 6 | - [Reversing A Queue](https://github.com/thisisshub/DSA/blob/main/L_queue/problems/A_reversing_a_queue.py) 7 | - [Generate Numbers With Given Digits](https://github.com/thisisshub/DSA/blob/main/L_queue/problems/B_generate_numbers_with_given_digits.py) 8 | - [Circular Tour](https://github.com/thisisshub/DSA/blob/main/L_queue/problems/C_circular_tour.py) -------------------------------------------------------------------------------- /U_trie/Z_trie.md: -------------------------------------------------------------------------------- 1 | # List of Contents 2 | 3 | - [Representation](https://github.com/thisisshub/DSA/blob/main/U_trie/A_representation.py) 4 | - [Search](https://github.com/thisisshub/DSA/blob/main/U_trie/B_search.py) 5 | - [Insert](https://github.com/thisisshub/DSA/blob/main/U_trie/C_insert.py) 6 | - [Delete](https://github.com/thisisshub/DSA/blob/main/U_trie/D_delete.py) 7 | - [Count Distinct Rows In A Binary Matrix](https://github.com/thisisshub/DSA/blob/main/U_trie/E_count_distinct_rows_in_a_binary_matrix.py) -------------------------------------------------------------------------------- /F_sorting/B_selectionsort.py: -------------------------------------------------------------------------------- 1 | def method1(l: list) -> list: 2 | import sys 3 | 4 | for i in range(len(l)): 5 | minid = i 6 | for j in range(i + 1, len(l)): 7 | if l[minid] > l[j]: 8 | minid = j 9 | l[i], l[minid] = l[minid], l[i] 10 | return l 11 | 12 | 13 | if __name__ == "__main__": 14 | """ 15 | l = [1, 3, 4, 7, 5, 9] 16 | from timeit import timeit 17 | print(timeit(method1(l), number=10000)) # 0.029101145999447908 18 | """ 19 | -------------------------------------------------------------------------------- /U_trie/A_representation.py: -------------------------------------------------------------------------------- 1 | _end = "_end_" 2 | 3 | 4 | def method1(*words): 5 | root = dict() 6 | for word in words: 7 | current_dict = root 8 | for letter in word: 9 | current_dict = current_dict.setdefault(letter, {}) 10 | current_dict[_end] = _end 11 | return root 12 | 13 | 14 | if __name__ == "__main__": 15 | """ 16 | from timeit import timeit 17 | 18 | print(timeit(lambda: method1("foo", "bar", "bob", "cat"))) # 1.2939369230007287 19 | """ 20 | -------------------------------------------------------------------------------- /D_arrays/problems/prefix_sum.py: -------------------------------------------------------------------------------- 1 | def method1(ll: list, n: int, prefixSum: int) -> int: 2 | prefixSum[0] = ll[0] 3 | for i in range(1, n): 4 | prefixSum[i] = prefixSum[i - 1] + ll[i] 5 | 6 | ll =[10, 4, 16, 20 ] 7 | n = len(ll) 8 | 9 | prefixSum = [0 for i in range(n + 1)] 10 | 11 | method1(ll, n, prefixSum) 12 | 13 | if __name__ == "__main__": 14 | """ 15 | from timeit import timeit 16 | print(timeit(lambda: method1(ll, n, prefixSum), number=10000)) # 0.005700344998331275 17 | """ -------------------------------------------------------------------------------- /F_sorting/problems/C_count_inversions_in_arrays.py: -------------------------------------------------------------------------------- 1 | def method1(ll: list) -> int: 2 | inversionCount = 0 3 | for i in range(len(ll) - 1): 4 | for j in range(i + 1, len(ll)): 5 | if ll[i] > ll[j]: 6 | inversionCount = inversionCount + 1 7 | 8 | return inversionCount 9 | 10 | 11 | if __name__ == "__main__": 12 | """ 13 | from timeit import timeit 14 | ll = [1, 9, 6, 4, 5] 15 | print(timeit(lambda: method1(ll), number=10000)) # 0.017585102999873925 16 | """ 17 | -------------------------------------------------------------------------------- /C_recursion/H_rod_cutting.py: -------------------------------------------------------------------------------- 1 | def method1(price: list, n: int) -> int: 2 | import sys 3 | 4 | if n <= 0: 5 | return 0 6 | max_val = -sys.maxsize - 1 7 | for i in range(0, n): 8 | max_val = max(max_val, price[i] + method1(price, n - i - 1)) 9 | return max_val 10 | 11 | 12 | if __name__ == "__main__": 13 | """ 14 | from timeit import timeit 15 | prices = [1, 5, 8, 9, 10, 17, 17, 20] 16 | print(timeit(lambda: method1(prices, len(prices)), number=10000)) # 1.6864704039999197 17 | """ 18 | -------------------------------------------------------------------------------- /J_linked_list/A_implementation.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.next = None 5 | 6 | 7 | class LinkedList: 8 | def __init__(self): 9 | self.head = None 10 | 11 | 12 | if __name__ == "__main__": 13 | """ 14 | from timeit import timeit 15 | Llist = LinkedList() 16 | Llist.head = Node(1) 17 | second = Node(2) 18 | third = Node(3) 19 | second.next = third 20 | print(timeit(lambda: Llist, number=10000)) # 0.00037003099987487076 21 | """ 22 | -------------------------------------------------------------------------------- /A_mathematics/E_factorial.py: -------------------------------------------------------------------------------- 1 | def method1(n: int) -> int: 2 | # Single line to find factorial by recursion. 3 | return 1 if n == 0 or n == 1 else n * method1(n - 1) 4 | 5 | 6 | def method2(n: int) -> int: 7 | '''This function returns the factorial 8 | by using In-built function.''' 9 | 10 | import math 11 | 12 | return math.factorial(n) 13 | 14 | 15 | if __name__ == "__main__": 16 | """ 17 | from timeit import timeit 18 | print(timeit(lambda: method1(10), number=10000)) # 0.012027394001052016 19 | """ 20 | -------------------------------------------------------------------------------- /B_bit_magic/F_count_setbit.py: -------------------------------------------------------------------------------- 1 | def method1(n: int) -> int: 2 | c = 0 3 | while n: 4 | c += n & 1 5 | n >>= 1 6 | return c 7 | 8 | 9 | def method2(n: int) -> int: 10 | if n == 0: 11 | return 0 12 | else: 13 | return (n & 1) + method2(n >> 1) 14 | 15 | 16 | if __name__ == "__main__": 17 | """ 18 | from timeit import timeit 19 | print(timeit(lambda: method1(9), number=10000)) # 0.0034751240000332473 20 | print(timeit(lambda: method2(9), number=10000)) # 0.006590511000013066 21 | """ 22 | -------------------------------------------------------------------------------- /R_greedy/A_activity_selection_problem.py: -------------------------------------------------------------------------------- 1 | def method1(s, f): 2 | n = len(f) 3 | print("The following activities are selected") 4 | 5 | i = 0 6 | print(i, end=" ") 7 | 8 | for j in range(n): 9 | 10 | if s[j] >= f[i]: 11 | print(j, end=" ") 12 | i = j 13 | 14 | 15 | if __name__ == "__main__": 16 | """ 17 | from timeit import timeit 18 | 19 | s = [1, 3, 0, 5, 8, 5] 20 | f = [2, 4, 6, 7, 9, 9] 21 | print(timeit(lambda: method1(s, f), number=10000)) # 0.2884501590015134 22 | """ 23 | -------------------------------------------------------------------------------- /D_arrays/problems/leaders_in_an_array.py: -------------------------------------------------------------------------------- 1 | def method1(): 2 | def method(ll: list, size: int) -> int: 3 | max_from_right = ll[size - 1] 4 | for i in range(size - 2, -1, -1): 5 | if max_from_right <= ll[i]: 6 | print(ll[i]) 7 | max_from_right = ll[i] 8 | 9 | ll = [16, 17, 4, 3, 5, 2] 10 | return method(ll, len(ll)) 11 | 12 | 13 | if __name__ == "__main__": 14 | """ 15 | from timeit import timeit 16 | print(timeit(lambda: method1(), number=10000)) # 0.08483552300003794 17 | """ 18 | -------------------------------------------------------------------------------- /M_dequeue/problems/A_maximum_of_all_subarray_of_size_k.py: -------------------------------------------------------------------------------- 1 | def method1(arr, n, k): 2 | max = 0 3 | 4 | for i in range(n - k + 1): 5 | max = arr[i] 6 | for j in range(1, k): 7 | if arr[i + j] > max: 8 | max = arr[i + j] 9 | return str(max) + " " 10 | 11 | 12 | if __name__ == "__main__": 13 | """ 14 | from timeit import timeit 15 | 16 | arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 17 | n = len(arr) 18 | k = 3 19 | print(timeit(lambda: method1(arr, n, k))) # 0.7219209800023236 20 | """ 21 | -------------------------------------------------------------------------------- /D_arrays/problems/maximum_consecutive_ones.py: -------------------------------------------------------------------------------- 1 | def method1(ll: list, n: int) -> int: 2 | count = 0 3 | result = 0 4 | for i in range(0, n): 5 | if ll[i] == 0: 6 | count = 0 7 | else: 8 | count += 1 9 | result = max(result, count) 10 | 11 | return result 12 | 13 | 14 | ll = [1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1] 15 | n = len(ll) 16 | 17 | if __name__ == "__main__": 18 | """ 19 | from timeit import timeit 20 | print(timeit(lambda: method1(ll, n), number=10000)) # 0.02980456100340234 21 | """ 22 | -------------------------------------------------------------------------------- /T_dynamic_programming/A_memoization.py: -------------------------------------------------------------------------------- 1 | def memoize_factorial(f): 2 | memory = {} 3 | 4 | def inner(num): 5 | if num not in memory: 6 | memory[num] = f(num) 7 | return memory[num] 8 | 9 | return inner 10 | 11 | 12 | @memoize_factorial 13 | def facto(num): 14 | if num == 1: 15 | return 1 16 | else: 17 | return num * facto(num - 1) 18 | 19 | 20 | if __name__ == "__main__": 21 | """ 22 | from timeit import timeit 23 | 24 | print(timeit(lambda: facto(5), number=10000)) # 0.0009072790053323843 25 | """ -------------------------------------------------------------------------------- /C_recursion/B_fibonnaci.py: -------------------------------------------------------------------------------- 1 | def method1(n: int) -> int: 2 | return int(((((1 + 5 ** 0.5) / 2) ** n) - (((1 - 5 ** 0.5) / 2) ** n)) / 5 ** 0.5) 3 | 4 | 5 | def method2(n: int) -> int: 6 | from functools import reduce 7 | 8 | c = reduce(lambda x, n: [x[1], x[0] + x[1]], range(n), [0, 1])[0] 9 | return c 10 | 11 | 12 | if __name__ == "__main__": 13 | """ 14 | from timeit import timeit 15 | print(timeit(lambda: method1(20), number=10000)) # 0.004012904999399325 16 | print(timeit(lambda: method2(20), number=10000)) # 0.04924747400036722 17 | """ 18 | -------------------------------------------------------------------------------- /B_bit_magic/H_using_lookuptable.py: -------------------------------------------------------------------------------- 1 | bitsettable = [0] * 256 2 | bitsettable[0] = 0 3 | 4 | for i in range(256): 5 | bitsettable[i] = (i & 1) + bitsettable[i // 2] 6 | 7 | 8 | def method1(n: int) -> int: 9 | return ( 10 | bitsettable[n & 0xFF] 11 | + bitsettable[(n >> 8) & 0xFF] 12 | + bitsettable[(n >> 16) & 0xFF] 13 | + bitsettable[(n >> 24 & 0xFF)] 14 | ) 15 | 16 | 17 | if __name__ == "__main__": 18 | """ 19 | from timeit import timeit 20 | print(timeit(lambda: method1(9), number=10000)) # 0.003812235000623332 21 | """ 22 | -------------------------------------------------------------------------------- /H_hashing/problems/B_count_of_the_frequency_of_array_elements.py: -------------------------------------------------------------------------------- 1 | def method1(ll: list, n: int) -> int: 2 | 3 | mp = dict() 4 | 5 | for i in range(n): 6 | if ll[i] in mp.keys(): 7 | mp[ll[i]] += 1 8 | else: 9 | mp[ll[i]] = 1 10 | 11 | for x in mp: 12 | print(x, " ", mp[x]) 13 | 14 | 15 | if __name__ == "__main__": 16 | """ 17 | from timeit import timeit 18 | ll = [10, 20, 20, 10, 10, 20, 5, 20] 19 | n = len(ll) 20 | print(timeit(lambda: method1(ll, n), number=10000)) # 0.24235440699703759 21 | """ 22 | -------------------------------------------------------------------------------- /Q_graphs/problems/topological_sorting/B_dfs_based_algorithm.py: -------------------------------------------------------------------------------- 1 | graph = {"A": ["B", "C"], "B": ["D", "E"], "C": ["F"], "D": [], "E": ["F"], "F": []} 2 | 3 | visited = set() 4 | 5 | 6 | def dfs(visited, graph, node): 7 | if node not in visited: 8 | print(node) 9 | visited.add(node) 10 | for neighbour in graph[node]: 11 | dfs(visited, graph, neighbour) 12 | 13 | 14 | if __name__ == "__main__": 15 | """ 16 | from timeit import timeit 17 | 18 | print(timeit(lambda: dfs(visited, graph, "A"), number=10000)) # 0.001466015000914922 19 | """ 20 | -------------------------------------------------------------------------------- /E_searching/problems/A_index_of_first_occurence_in_sorted_array.py: -------------------------------------------------------------------------------- 1 | def method1(arr, n, x): 2 | first = -1 3 | for i in range(0, n): 4 | if x != arr[i]: 5 | continue 6 | if first == -1: 7 | first = i 8 | 9 | if first != -1: 10 | print("First Occurrence = ", first) 11 | 12 | 13 | if __name__ == "__main__": 14 | """ 15 | arr = [1, 2, 2, 2, 2, 3, 4, 7, 8, 8 ] 16 | n = len(arr) 17 | x = 8 18 | from timeit import timeit 19 | print(timeit(lambda: method1(arr, n, x), number=10000)) # 0.11710410399996363 20 | """ 21 | -------------------------------------------------------------------------------- /H_hashing/problems/C_the_intersection_of_two_arrays.py: -------------------------------------------------------------------------------- 1 | def method1(ll1, ll2, n1, n2): 2 | hs = set() 3 | for i in range(0, n1): 4 | hs.add(ll1[i]) 5 | print("Intersection:") 6 | for i in range(0, n2): 7 | if ll2[i] in hs: 8 | print(ll2[i], end=" ") 9 | 10 | 11 | if __name__ == "__main__": 12 | """ 13 | from timeit import timeit 14 | ll1 = [7, 1, 5, 2, 3, 6] 15 | ll2 = [3, 8, 6, 20, 7] 16 | n1 = len(ll1) 17 | n2 = len(ll2) 18 | print(timeit(lambda: method1(ll1, ll2, n1, n2), number=10000)) # 0.11873356500291266 19 | """ 20 | -------------------------------------------------------------------------------- /D_arrays/problems/max_difference_in_array.py: -------------------------------------------------------------------------------- 1 | def method1(): 2 | def maxDiff(ll: list) -> int: 3 | vmin = ll[0] 4 | dmax = 0 5 | for i in range(len(ll)): 6 | if ll[i] < vmin: 7 | vmin = ll[i] 8 | elif ll[i] - vmin > dmax: 9 | dmax = ll[i] - vmin 10 | return dmax 11 | 12 | ll = [i for i in range(5)] 13 | return maxDiff(ll) 14 | 15 | 16 | if __name__ == "__main__": 17 | """ 18 | from timeit import timeit 19 | print(timeit(lambda: method1(), number=10000)) # 0.01388289500027895 20 | """ 21 | -------------------------------------------------------------------------------- /F_sorting/problems/F_sorting_arrays_with_2_and_3_types_of_elements.py: -------------------------------------------------------------------------------- 1 | def method1(arr: list, n: int) -> list: 2 | type0 = 0 3 | type1 = n - 1 4 | while type0 < type1: 5 | if arr[type0] == 1: 6 | arr[type0], arr[type1] = arr[type1], arr[type0] 7 | type1 -= 1 8 | else: 9 | type0 += 1 10 | 11 | 12 | if __name__ == "__main__": 13 | """ 14 | arr = [1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1] 15 | n = len(arr) 16 | from timeit import timeit 17 | print(timeit(lambda: method1(arr, n), number=10000)) # 0.01202381199982483 18 | """ 19 | -------------------------------------------------------------------------------- /L_queue/A_implementation.py: -------------------------------------------------------------------------------- 1 | def method1(queue: list) -> list: 2 | 3 | queue.append("a") 4 | queue.append("b") 5 | queue.append("c") 6 | 7 | print("Initial queue") 8 | print(queue) 9 | 10 | print("\nElements dequeued from queue") 11 | print(queue.pop(0)) 12 | print(queue.pop(0)) 13 | print(queue.pop(0)) 14 | 15 | print("\nQueue after removing elements") 16 | return queue 17 | 18 | 19 | if __name__ == "__main__": 20 | """ 21 | from timeit import timeit 22 | 23 | print(timeit(lambda: method1([]), number=10000)) # 0.8325513340023463 24 | """ 25 | -------------------------------------------------------------------------------- /A_mathematics/C_gcd.py: -------------------------------------------------------------------------------- 1 | def method1(n: int, m: int) -> int: 2 | '''Return gcd by Euclidean Algorithm.''' 3 | 4 | while m: 5 | n, m = m, n % m 6 | return abs(n) 7 | 8 | 9 | def method2(n: int, m: int) -> int: 10 | '''Return gcd by inbuilt gcd() method.''' 11 | 12 | from math import gcd 13 | 14 | return gcd(n, m) 15 | 16 | 17 | if __name__ == "__main__": 18 | """ 19 | from timeit import timeit 20 | print(timeit(lambda: method1(3, 9), number=10000)) # 0.0018165660003433004 21 | print(timeit(lambda: method2(3, 9), number=10000)) # 0.006539128997246735 22 | """ 23 | -------------------------------------------------------------------------------- /G_matrix/C_printing_matrix_in_a_snake_pattern.py: -------------------------------------------------------------------------------- 1 | def method1(n: int, m: int, matrix: list) -> list: 2 | for i in range(m): 3 | if i % 2 == 0: 4 | for j in range(n): 5 | print(str(matrix[i][j]), end=" ") 6 | else: 7 | for j in range(n - 1, -1, -1): 8 | print(str(matrix[i][j]), end=" ") 9 | 10 | 11 | if __name__ == "__main__": 12 | from timeit import timeit 13 | 14 | matrix = [[10, 20, 30, 40], [15, 15, 25, 55], [17, 19, 17, 18], [1, 8, 9, 2]] 15 | print(timeit(lambda: method1(4, 4, matrix), number=10000)) # 0.1679946160002146 16 | -------------------------------------------------------------------------------- /D_arrays/problems/frequencies_in_sorted_array.py: -------------------------------------------------------------------------------- 1 | def method1(ll: list) -> list: 2 | from collections import Counter 3 | 4 | return sorted(ll, key=Counter(ll).get, reverse=True) 5 | 6 | 7 | def method2(ll: list) -> list: 8 | return sorted(ll, key=ll.count, reverse=True) 9 | 10 | 11 | if __name__ == "__main__": 12 | """ 13 | from timeit import timeit 14 | ll = [1,2,3,4,3,3,3,6,7,1,1,9,3,2, 3, 2, 1, 3, 4, 5, 6, 7, 7, 7, 1] 15 | print(timeit(lambda: method1(ll), number=10000)) # 0.03473279799982265 16 | print(timeit(lambda: method2(ll), number=10000)) # 0.057430269999713346 17 | """ 18 | -------------------------------------------------------------------------------- /H_hashing/problems/K_longest_consecutive_subsequence.py: -------------------------------------------------------------------------------- 1 | def method1(ll: list, n: int) -> int: 2 | s = set() 3 | ans = 0 4 | for ele in ll: 5 | s.add(ele) 6 | for i in range(n): 7 | if (ll[i] - 1) not in s: 8 | j = ll[i] 9 | while j in s: 10 | j += 1 11 | ans = max(ans, j - ll[i]) 12 | return ans 13 | 14 | 15 | if __name__ == "__main__": 16 | """ 17 | from timeit import timeit 18 | n = 7 19 | ll = [1, 9, 3, 10, 4, 20, 2] 20 | print(timeit(lambda: method1(ll, n), number=10000)) # 0.021972083995933644 21 | """ 22 | -------------------------------------------------------------------------------- /H_hashing/problems/M_more_than_nk_occurences.py: -------------------------------------------------------------------------------- 1 | def method1(ll: list, n: int, k: int) -> int: 2 | x = n // k 3 | freq = {} 4 | for i in range(n): 5 | if ll[i] in freq: 6 | freq[ll[i]] += 1 7 | else: 8 | freq[ll[i]] = 1 9 | for i in freq: 10 | if freq[i] > x: 11 | print(i) 12 | 13 | 14 | if __name__ == "__main__": 15 | """ 16 | from timeit import timeit 17 | ll = [1, 1, 2, 2, 3, 5, 4, 2, 2, 3, 1, 1, 1] 18 | n = len(ll) 19 | k = 4 20 | print(timeit(lambda: method1(ll, n, k), number=10000)) # 0.1085869129965431 21 | """ 22 | -------------------------------------------------------------------------------- /Z_tests/test_E_searching.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | sys.path.append("../") 4 | 5 | from E_searching.iterative import A_binary_search_iterative 6 | from E_searching.recursive import A_binary_search_recursive 7 | 8 | class Test_E_searching: 9 | def test_A_binary_search_iterative(self): 10 | n = 9 11 | l = [i for i in range(10)] 12 | assert A_binary_search_iterative.method1_iterative(n, l) == 9 13 | 14 | def test_B_binary_search_recursive(self): 15 | n = 9 16 | l = [i for i in range(10)] 17 | assert A_binary_search_recursive.method1_recursive(l, 0, len(l) - 1, n) == 9 18 | -------------------------------------------------------------------------------- /G_matrix/I_matrix_multiplication.py: -------------------------------------------------------------------------------- 1 | def method1(): 2 | A = [[12, 7, 3], [4, 5, 6], [7, 8, 9]] 3 | 4 | B = [[5, 8, 1, 2], [6, 7, 3, 0], [4, 5, 9, 1]] 5 | 6 | result = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] 7 | 8 | for i in range(len(A)): 9 | for j in range(len(B[0])): 10 | for k in range(len(B)): 11 | result[i][j] += A[i][k] * B[k][j] 12 | 13 | for r in result: 14 | print(r) 15 | 16 | 17 | if __name__ == "__main__": 18 | """ 19 | from timeit import timeit 20 | print(timeit(lambda: method1(), number=10000)) # 0.2153797940000004 21 | """ 22 | -------------------------------------------------------------------------------- /E_searching/problems/B_index_of_last_occurence_in_sorted_array.py: -------------------------------------------------------------------------------- 1 | def method1(arr, n, x): 2 | first = -1 3 | last = -1 4 | for i in range(0, n): 5 | if x != arr[i]: 6 | continue 7 | if first == -1: 8 | first = i 9 | last = i 10 | 11 | if first != -1: 12 | print("Last Occurrence = ", last) 13 | 14 | 15 | if __name__ == "__main__": 16 | """ 17 | arr = [1, 2, 2, 2, 2, 3, 4, 7, 8, 8 ] 18 | n = len(arr) 19 | x = 8 20 | from timeit import timeit 21 | print(timeit(lambda: method1(arr, n, x), number=10000)) # 0.08866931500006103 22 | """ 23 | -------------------------------------------------------------------------------- /H_hashing/problems/D_union_of_two_unsorted_arrays.py: -------------------------------------------------------------------------------- 1 | def method1(arr1, arr2, n1, n2): 2 | hs = set() 3 | for i in range(0, n1): 4 | hs.add(arr1[i]) 5 | for i in range(0, n2): 6 | hs.add(arr2[i]) 7 | print("Union:") 8 | for i in hs: 9 | print(i, end=" ") 10 | print("\n") 11 | 12 | 13 | if __name__ == "__main__": 14 | """ 15 | from timeit import timeit 16 | arr1 = [7, 1, 5, 2, 3, 6] 17 | arr2 = [3, 8, 6, 20, 7] 18 | n1 = len(arr1) 19 | n2 = len(arr2) 20 | print(timeit(lambda: method1(arr1, arr2, n1, n2), number=10000)) # 0.22361706300580408 21 | """ 22 | -------------------------------------------------------------------------------- /A_mathematics/G_prime_factors.py: -------------------------------------------------------------------------------- 1 | def method1(n: int) -> int: 2 | '''Return a list of prime factors of an integer by 3 | first checking if the modulo of the value of d and number is equal to 0. 4 | Then applying the for loop inside the for loop to count a factor only once. 5 | ''' 6 | 7 | divisors = [d for d in range(2, n // 2 + 1) if n % d == 0] 8 | return [d for d in divisors if all(d % od != 0 for od in divisors if od != d)] 9 | 10 | 11 | if __name__ == "__main__": 12 | """ 13 | from timeit import timeit 14 | print(timeit(lambda: method1(20), number=10000)) # 0.028740440000547096 15 | """ 16 | -------------------------------------------------------------------------------- /C_recursion/D_print_1_to_n.py: -------------------------------------------------------------------------------- 1 | def method1(n: int) -> list: 2 | return [i for i in range(1, n + 1)] 3 | 4 | 5 | def method2(n: int) -> int: 6 | i = 1 7 | while i <= n: 8 | print(i) 9 | i += 1 10 | 11 | 12 | def method3(n: int) -> int: 13 | print(*range(1, n + 1)) 14 | 15 | 16 | if __name__ == "__main__": 17 | """ 18 | from timeit import timeit 19 | print(timeit(lambda: method1(10), number=10000)) # 0.00660862100085069 20 | print(timeit(lambda: method2(10), number=10000)) # 0.3217459139996208 21 | print(timeit(lambda: method3(10), number=10000)) # 0.3245184600000357 22 | """ 23 | -------------------------------------------------------------------------------- /L_queue/problems/B_generate_numbers_with_given_digits.py: -------------------------------------------------------------------------------- 1 | def method1(): 2 | def print_well_ordered(number, x, k): 3 | if k == 0: 4 | print(number, end=" ") 5 | return 6 | 7 | for i in range((x + 1), 10): 8 | print_well_ordered(number * 10 + i, i, k - 1) 9 | 10 | def generate_welL_ordered(k): 11 | print_well_ordered(0, 0, k) 12 | 13 | k = 3 14 | return generate_welL_ordered(k) 15 | 16 | 17 | if __name__ == "__main__": 18 | """ 19 | from timeit import timeit 20 | print(timeit(lambda: method1(), number=100000)) # 19.001043160002155 21 | """ 22 | -------------------------------------------------------------------------------- /D_arrays/problems/longest_even_odd_subarray.py: -------------------------------------------------------------------------------- 1 | def method1(arr: list, n: int) -> list: 2 | longest = 1 3 | cnt = 1 4 | for i in range(n - 1): 5 | if (arr[i] + arr[i + 1]) % 2 == 1: 6 | cnt = cnt + 1 7 | else: 8 | longest = max(longest, cnt) 9 | cnt = 1 10 | if longest == 1: 11 | return 0 12 | return max(cnt, longest) 13 | 14 | 15 | if __name__ == "__main__": 16 | """ 17 | arr = [ 1, 2, 3, 4, 5, 7, 8 ] 18 | n = len(arr) 19 | from timeit import timeit 20 | print(timeit(lambda: method1(arr, n), number=10000)) # 0.01877671800320968 21 | """ 22 | -------------------------------------------------------------------------------- /E_searching/problems/J_majority_element.py: -------------------------------------------------------------------------------- 1 | def method1(ll: list, n: int) -> int: 2 | maxCount = 0 3 | index = -1 4 | for i in range(n): 5 | count = 0 6 | for j in range(n): 7 | if ll[i] == ll[j]: 8 | count += 1 9 | if count > maxCount: 10 | maxCount = count 11 | index = i 12 | if maxCount > n // 2: 13 | print(ll[index]) 14 | 15 | 16 | if __name__ == "__main__": 17 | """ 18 | from timeit import timeit 19 | ll = [1, 1, 2, 1, 3, 5, 1] 20 | n = len(ll) 21 | print(timeit(lambda: method1(ll, n), number=10000)) # 0.09685827199973573 22 | """ 23 | -------------------------------------------------------------------------------- /D_arrays/problems/sliding_window.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | INT_MIN = -sys.maxsize - 1 4 | 5 | 6 | def method1(arr, n, k): 7 | max_sum = INT_MIN 8 | for i in range(n - k + 1): 9 | current_sum = 0 10 | for j in range(k): 11 | current_sum = current_sum + arr[i + j] 12 | max_sum = max(current_sum, max_sum) 13 | 14 | return max_sum 15 | 16 | 17 | arr = [1, 4, 2, 10, 2, 3, 1, 0, 20] 18 | k = 4 19 | n = len(arr) 20 | print(method1(arr, n, k)) 21 | 22 | if __name__ == "__main__": 23 | """ 24 | from timeit import timeit 25 | print(timeit(lambda: method1(arr, n, k), number=10000)) # 0.03456093000204419 26 | """ 27 | -------------------------------------------------------------------------------- /N_tree/implementation/A_inorder_traversal.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, key): 3 | self.left = None 4 | self.right = None 5 | self.val = key 6 | 7 | 8 | def method1(root): 9 | 10 | if root: 11 | 12 | method1(root.left) 13 | 14 | print(root.val), 15 | 16 | method1(root.right) 17 | 18 | 19 | root = Node(1) 20 | root.left = Node(2) 21 | root.right = Node(3) 22 | root.left.left = Node(4) 23 | root.left.right = Node(5) 24 | 25 | if __name__ == "__main__": 26 | """ 27 | from timeit import timeit 28 | 29 | print(timeit(lambda: method1(root), number=10000)) # 0.3417354199991678 30 | """ 31 | -------------------------------------------------------------------------------- /N_tree/problems/A_size_of_binary_tree.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.left = None 5 | self.right = None 6 | 7 | 8 | def size(node): 9 | if node is None: 10 | return 0 11 | else: 12 | return size(node.left) + 1 + size(node.right) 13 | 14 | 15 | if __name__ == "__main__": 16 | """ 17 | from timeit import timeit 18 | 19 | root = Node(1) 20 | root.left = Node(2) 21 | root.right = Node(3) 22 | root.left.left = Node(4) 23 | root.left.right = Node(5) 24 | 25 | print(timeit(lambda: size(root), number=10000)) # 0.009357142997032497 26 | """ 27 | -------------------------------------------------------------------------------- /E_searching/problems/D_count_of_1s_in_a_binary_sorted_array.py: -------------------------------------------------------------------------------- 1 | def method1(arr: list, low: int, high: int) -> int: 2 | 3 | if high >= low: 4 | mid = low + (high - low) // 2 5 | if (mid == high or arr[mid + 1] == 0) and (arr[mid] == 1): 6 | return mid + 1 7 | if arr[mid] == 1: 8 | return method1(arr, (mid + 1), high) 9 | 10 | return method1(arr, low, mid - 1) 11 | 12 | return 0 13 | 14 | 15 | if __name__ == "__main__": 16 | """ 17 | arr=[1, 1, 1, 1, 0, 0, 0] 18 | from timeit import timeit 19 | print(timeit(lambda: method1(arr, 0, len(arr)-1), number=10000)) # 0.00268922500026747 20 | """ 21 | -------------------------------------------------------------------------------- /C_recursion/I_subset_of_set.py: -------------------------------------------------------------------------------- 1 | def method1(n: list) -> list: 2 | x = len(n) 3 | masks = [1 << i for i in range(x)] 4 | for i in range(1 << x): 5 | yield [ss for mask, ss in zip(masks, n) if i & mask] 6 | 7 | 8 | def method2(n: set) -> list: 9 | from itertools import combinations 10 | 11 | return [x for i in range(len(n) + 1) for x in combinations(n, i)] 12 | 13 | 14 | if __name__ == "__main__": 15 | """ 16 | from timeit import timeit 17 | print(timeit(lambda: method1([1, 2, 3, 4, 5, 6]), number=10000)) # 0.003230058999179164 18 | print(timeit(lambda: method2({1, 2, 3, 4, 5, 6}), number=10000)) # 0.055786498000088613 19 | """ 20 | -------------------------------------------------------------------------------- /D_arrays/problems/maximum_subarray_sum.py: -------------------------------------------------------------------------------- 1 | def method1(ll, n): 2 | 3 | max_so_far = 0 4 | max_ending_here = 0 5 | 6 | for i in range(0, n): 7 | max_ending_here = max_ending_here + ll[i] 8 | if max_ending_here < 0: 9 | max_ending_here = 0 10 | elif max_so_far < max_ending_here: 11 | max_so_far = max_ending_here 12 | 13 | return max_so_far 14 | 15 | 16 | if __name__ == "__main__": 17 | """ 18 | ll = [-13, -3, -25, -20, -3, -16, -23, -12, -5, -22, -15, -4, -7] 19 | n = len(ll) 20 | from timeit import timeit 21 | print(timeit(lambda: method1(ll, n), number=10000)) # 0.024287710002681706 22 | """ 23 | -------------------------------------------------------------------------------- /E_searching/iterative/A_binary_search_iterative.py: -------------------------------------------------------------------------------- 1 | def method1_iterative(n: int, l: list) -> int: 2 | low = 0 3 | high = len(l) - 1 4 | mid = 0 5 | while low <= high: 6 | mid = (low + high) // 2 7 | if l[mid] < n: 8 | low = mid + 1 9 | elif l[mid] > n: 10 | high = mid - 1 11 | else: 12 | return mid 13 | return -1 14 | 15 | 16 | if __name__ == "__main__": 17 | """ 18 | n = 9999 19 | l = [i for i in range(10000)] # [0, 1, 3, ...., 9999] 20 | from timeit import timeit 21 | print(timeit(lambda: method1_iterative(l, 0, len(l)-1, n), number=10000)) # 0.03099031199963065 22 | """ 23 | -------------------------------------------------------------------------------- /P_heap/problems/C_k_largest_elements.py: -------------------------------------------------------------------------------- 1 | import heapq 2 | 3 | 4 | class Solution(object): 5 | def find_Kth_Largest(self, nums, k): 6 | 7 | h = [] 8 | for e in nums: 9 | heapq.heappush(h, (-e, e)) 10 | for i in range(k): 11 | w, e = heapq.heappop(h) 12 | w = w 13 | if i == k - 1: 14 | return e 15 | 16 | 17 | if __name__ == "__main__": 18 | """ 19 | from timeit import timeit 20 | 21 | arr_nums = [12, 14, 9, 50, 61, 41] 22 | s = Solution() 23 | result = s.find_Kth_Largest(arr_nums, 3) 24 | print(timeit(lambda: result, number=10000)) # 0.0005090839986223727 25 | """ 26 | -------------------------------------------------------------------------------- /N_tree/implementation/B_preorder_traversal.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, key): 3 | self.left = None 4 | self.right = None 5 | self.val = key 6 | 7 | 8 | def method1(root): 9 | 10 | if root: 11 | 12 | print(root.val), 13 | 14 | method1(root.left) 15 | 16 | method1(root.right) 17 | 18 | 19 | if __name__ == "__main__": 20 | """ 21 | from timeit import timeit 22 | 23 | root = Node(1) 24 | root.left = Node(2) 25 | root.right = Node(3) 26 | root.left.left = Node(4) 27 | root.left.right = Node(5) 28 | 29 | print(timeit(lambda: method1(root), number=10000)) # 0.2481299540013424 30 | """ 31 | -------------------------------------------------------------------------------- /N_tree/implementation/C_postorder_traversal.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, key): 3 | self.left = None 4 | self.right = None 5 | self.val = key 6 | 7 | 8 | def method1(root): 9 | 10 | if root: 11 | 12 | method1(root.left) 13 | 14 | method1(root.right) 15 | 16 | print(root.val), 17 | 18 | 19 | if __name__ == "__main__": 20 | """ 21 | from timeit import timeit 22 | 23 | root = Node(1) 24 | root.left = Node(2) 25 | root.right = Node(3) 26 | root.left.left = Node(4) 27 | root.left.right = Node(5) 28 | 29 | print(timeit(lambda: method1(root), number=10000)) # 0.23595180499978596 30 | """ 31 | -------------------------------------------------------------------------------- /T_dynamic_programming/problems/I_maximum_sum_with_no_consecutive.py: -------------------------------------------------------------------------------- 1 | def method1(arr): 2 | incl = 0 3 | excl = 0 4 | 5 | for i in arr: 6 | 7 | # Current max excluding i (No ternary in 8 | # Python) 9 | new_excl = excl if excl > incl else incl 10 | 11 | # Current max including i 12 | incl = excl + i 13 | excl = new_excl 14 | 15 | # return max of incl and excl 16 | return excl if excl > incl else incl 17 | 18 | 19 | if __name__ == "__main__": 20 | """ 21 | from timeit import timeit 22 | 23 | arr = [5, 5, 10, 100, 10, 5] 24 | print(timeit(lambda: method1(arr), number=10000)) # 0.003943671996239573 25 | """ -------------------------------------------------------------------------------- /C_recursion/G_sum_of_digits.py: -------------------------------------------------------------------------------- 1 | def method1(n: int) -> int: 2 | r = 0 3 | while n: 4 | r, n = r + n % 10, n // 10 5 | return r 6 | 7 | 8 | def method2(n: int) -> int: 9 | c = 0 10 | for i in str(n): 11 | c += int(i) 12 | return c 13 | 14 | 15 | def method3(n: int) -> int: 16 | return sum(map(int, (str(n)))) 17 | 18 | 19 | if __name__ == "__main__": 20 | """ 21 | from timeit import timeit 22 | print(timeit(lambda: method1(1234), number=10000)) # 0.005289119000735809 23 | print(timeit(lambda: method2(1234), number=10000)) # 0.006883707001179573 24 | print(timeit(lambda: method3(1234), number=10000)) # 0.00851047400101379 25 | """ 26 | -------------------------------------------------------------------------------- /H_hashing/problems/H_longest_subarray_with_a_given_sum.py: -------------------------------------------------------------------------------- 1 | def method1(ll: list, n: int, k: int): 2 | mydict = dict() 3 | sum = 0 4 | maxLen = 0 5 | for i in range(n): 6 | sum += ll[i] 7 | if sum == k: 8 | maxLen = i + 1 9 | elif (sum - k) in mydict: 10 | maxLen = max(maxLen, i - mydict[sum - k]) 11 | if sum not in mydict: 12 | mydict[sum] = i 13 | return maxLen 14 | 15 | 16 | if __name__ == "__main__": 17 | """ 18 | from timeit import timeit 19 | ll = [10, 5, 2, 7, 1, 9] 20 | n = len(ll) 21 | k = 15 22 | print(timeit(lambda: method1(ll, n, k), number=10000)) # 0.01679191100265598 23 | """ 24 | -------------------------------------------------------------------------------- /D_arrays/problems/max_profit_stock.py: -------------------------------------------------------------------------------- 1 | def method1(): 2 | def maxProfit(prices): 3 | 4 | n = len(prices) 5 | cost = 0 6 | maxcost = 0 7 | 8 | if n == 0: 9 | return 0 10 | min_price = prices[0] 11 | for i in range(n): 12 | min_price = min(min_price, prices[i]) 13 | cost = prices[i] - min_price 14 | maxcost = max(maxcost, cost) 15 | return maxcost 16 | 17 | prices = [7, 1, 5, 3, 6, 4] 18 | return maxProfit(prices) 19 | 20 | 21 | if __name__ == "__main__": 22 | """ 23 | from timeit import timeit 24 | print(timeit(lambda: method1(), number=10000)) # 0.020394561999637517 25 | """ 26 | -------------------------------------------------------------------------------- /D_arrays/problems/consecutive_flips.py: -------------------------------------------------------------------------------- 1 | def method1(s, n, k): 2 | cnt = 0 3 | prev = -1 4 | for i in range(0, k): 5 | if s[i] == "1": 6 | prev = i 7 | if prev == -1: 8 | cnt += 1 9 | prev = k - 1 10 | 11 | for i in range(k, n): 12 | if s[i] != "1": 13 | if prev <= (i - k): 14 | prev = i 15 | cnt += 1 16 | else: 17 | prev = i 18 | 19 | return cnt 20 | 21 | 22 | s = "10000001" 23 | n = len(s) 24 | k = 2 25 | 26 | if __name__ == "__main__": 27 | """ 28 | from timeit import timeit 29 | print(timeit(lambda: method1(s, n, k), number=10000)) # 0.011129570000775857 30 | """ 31 | -------------------------------------------------------------------------------- /F_sorting/problems/E_chocolate_distribution_problem.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | def method1(arr, n, m): 5 | if m == 0 or n == 0: 6 | return 0 7 | arr.sort() 8 | if n < m: 9 | return -1 10 | min_diff = sys.maxsize 11 | i = 0 12 | while i + m - 1 < n: 13 | diff = arr[i + m - 1] - arr[i] 14 | if diff < min_diff: 15 | min_diff = diff 16 | i += 1 17 | return min_diff 18 | 19 | 20 | if __name__ == "__main__": 21 | """ 22 | from timeit import timeit 23 | arr = [12, 4, 7, 9, 2, 23, 25, 41, 30, 40, 28, 42, 30, 44, 48, 43, 50] 24 | print(timeit(lambda: method1(arr, len(arr), 7), number=10000)) # 0.01904779899996356 25 | """ 26 | -------------------------------------------------------------------------------- /G_matrix/J_search_in_row-wise_and_column-wise_sorted_matrix.py: -------------------------------------------------------------------------------- 1 | def method1(mat, n, x): 2 | i = 0 3 | j = n - 1 4 | while i < n and j >= 0: 5 | if mat[i][j] == x: 6 | print("n Found at ", i, ", ", j) 7 | return 1 8 | if mat[i][j] > x: 9 | j -= 1 10 | else: 11 | i += 1 12 | print("Element not found") 13 | return 0 14 | 15 | 16 | if __name__ == "__main__": 17 | """ 18 | from timeit import timeit 19 | mat = [ [10, 20, 30, 40], 20 | [15, 25, 35, 45], 21 | [27, 29, 37, 48], 22 | [32, 33, 39, 50] ] 23 | print(timeit(lambda: method1(mat, 4, 29), number=10000)) # 0.3365673150001385 24 | """ 25 | -------------------------------------------------------------------------------- /D_arrays/problems/left_rotate_by_d_places.py: -------------------------------------------------------------------------------- 1 | def method1(): 2 | def method_rotate(arr, n): 3 | temp = arr[0] 4 | for i in range(n - 1): 5 | arr[i] = arr[i + 1] 6 | arr[n - 1] = temp 7 | 8 | def method(arr: list, d: int, n: int) -> list: 9 | for _ in range(d): 10 | method_rotate(arr, n) 11 | 12 | def method_print(arr, n): 13 | for i in range(n): 14 | print(arr[i], end=" ") 15 | 16 | arr = [1, 2, 3, 4, 5, 6, 7] 17 | method(arr, 2, 7) 18 | return method_print(arr, 7) 19 | 20 | 21 | if __name__ == "__main__": 22 | """ 23 | from timeit import timeit 24 | print(timeit(lambda: method1(), number=10000)) # 0.08287155000016355 25 | """ -------------------------------------------------------------------------------- /M_dequeue/A_implementation.py: -------------------------------------------------------------------------------- 1 | class Deque: 2 | def __init__(self): 3 | self.items = [] 4 | 5 | def isEmpty(self): 6 | return self.items == [] 7 | 8 | def addFront(self, item): 9 | self.items.append(item) 10 | 11 | def addRear(self, item): 12 | self.items.insert(0, item) 13 | 14 | def removeFront(self): 15 | return self.items.pop() 16 | 17 | def removeRear(self): 18 | return self.items.pop(0) 19 | 20 | def size(self): 21 | return len(self.items) 22 | 23 | 24 | if __name__ == "__main__": 25 | """ 26 | from timeit import timeit 27 | 28 | obj = Deque() 29 | print(timeit(lambda: obj, number=10000)) # 0.0005975749954814091 30 | """ 31 | -------------------------------------------------------------------------------- /D_arrays/operation_on_arrays/C_deletion.py: -------------------------------------------------------------------------------- 1 | def method1(n: int, l: list) -> list: 2 | n = 2 3 | l = [i for i in range(10)] # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 4 | return l.remove(2) # [0, 1, 3, 4, 5, 6, 7, 8, 9] 5 | 6 | 7 | def method2(n: int, l: list) -> list: 8 | n = 2 9 | l = [i for i in range(10)] # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 10 | return l.pop(0) # [1, 2, 3, 4, 5, 6, 7, 8, 9] 11 | 12 | 13 | if __name__ == "__main__": 14 | """ 15 | n = 2 16 | l = [i for i in range(10)] # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 17 | from timeit import timeit 18 | print(timeit(lambda: method1(n, l), number=10000)) # 0.007390202999886242 19 | print(timeit(lambda: method2(n, l), number=10000)) # 0.0074160020012641326 20 | """ 21 | -------------------------------------------------------------------------------- /H_hashing/problems/E_pair_with_given_sum_in_an_unsorted_array.py: -------------------------------------------------------------------------------- 1 | def method1(ll: list, arr_size: int, sum: int) -> int: 2 | s = set() 3 | for i in range(0, arr_size): 4 | temp = sum - ll[i] 5 | if temp in s: 6 | print( 7 | "Pair with given sum " 8 | + str(sum) 9 | + " is (" 10 | + str(ll[i]) 11 | + ", " 12 | + str(temp) 13 | + ")" 14 | + s.add(ll[i]) 15 | ) 16 | 17 | 18 | if __name__ == "__main__": 19 | """ 20 | from timeit import timeit 21 | ll = [1, 4, 45, 6, 10, 8] 22 | n = 16 23 | print(timeit(lambda: method1(ll, len(ll), n))) # 0.6651965910059516 24 | """ 25 | -------------------------------------------------------------------------------- /G_matrix/A_multidimensional_matrix.py: -------------------------------------------------------------------------------- 1 | def method1(l: list) -> list: 2 | l = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 0]] 3 | return l 4 | 5 | 6 | def method2(l: list) -> list: 7 | l = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 0]] 8 | for i in l: 9 | return i 10 | 11 | 12 | def method3(l: list) -> list: 13 | l = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 0]] 14 | for i in l: 15 | for j in i: 16 | print(j, end=" ") 17 | 18 | 19 | if __name__ == "__main__": 20 | """ 21 | from timeit import timeit 22 | print(timeit(lambda: method1(l), number=10000)) # 0.005068514998129103 23 | print(timeit(lambda: method2(l), number=10000)) # 0.0051237920015410054 24 | print(timeit(lambda: method3(l), number=10000)) # 0.1331835500022862 25 | """ 26 | -------------------------------------------------------------------------------- /E_searching/problems/F_peak_element.py: -------------------------------------------------------------------------------- 1 | def findPeakUtil(ll: list, low: int, high: int, n: int) -> list: 2 | mid = low + (high - low) / 2 3 | mid = int(mid) 4 | if (mid == 0 or ll[mid - 1] <= ll[mid]) and ( 5 | mid == n - 1 or ll[mid + 1] <= ll[mid] 6 | ): 7 | return mid 8 | elif mid > 0 and ll[mid - 1] > ll[mid]: 9 | return findPeakUtil(ll, low, (mid - 1), n) 10 | else: 11 | return findPeakUtil(ll, (mid + 1), high, n) 12 | 13 | 14 | def method1(ll, n): 15 | return findPeakUtil(ll, 0, n - 1, n) 16 | 17 | 18 | if __name__ == "__main__": 19 | """ 20 | from timeit import timeit 21 | ll = [1, 3, 20, 4, 1, 0] 22 | n = len(ll) 23 | print(timeit(lambda: method1(ll, n))) # 0.4230448450007316 24 | """ 25 | -------------------------------------------------------------------------------- /C_recursion/C_print_n_to_1.py: -------------------------------------------------------------------------------- 1 | def method1(n: int) -> list: 2 | return [i for i in range(n, 0, -1)] 3 | 4 | 5 | def method2(n: int) -> list: 6 | return [n - x for x in range(n)] 7 | 8 | 9 | def method3(n: int) -> int: 10 | print(*range(n, 0, -1)) 11 | 12 | 13 | def method4(n: int) -> int: 14 | while n > 0: 15 | print(n) 16 | n -= 1 17 | 18 | 19 | if __name__ == "__main__": 20 | """ 21 | from timeit import timeit 22 | print(timeit(lambda: method1(10), number=10000)) # 0.005636529000184964 23 | print(timeit(lambda: method2(10), number=10000)) # 0.0071275150003202725 24 | print(timeit(lambda: method3(10), number=10000)) # 0.062233691998699214 25 | print(timeit(lambda: method4(10), number=10000)) # 0.26295897900126874 26 | """ 27 | -------------------------------------------------------------------------------- /A_mathematics/Z_mathematics.md: -------------------------------------------------------------------------------- 1 | # List of Contents 2 | 3 | - [Count Digits](https://github.com/thisisshub/DSA/blob/main/A_mathematics/A_count_digits.py) 4 | - [Prime Number](https://github.com/thisisshub/DSA/blob/main/A_mathematics/F_prime_number.py) 5 | - [Palindrome](https://github.com/thisisshub/DSA/blob/main/A_mathematics/B_palindrome.py) 6 | - [Gcd](https://github.com/thisisshub/DSA/blob/main/A_mathematics/C_gcd.py) 7 | - [Lcm](https://github.com/thisisshub/DSA/blob/main/A_mathematics/D_lcm.py) 8 | - [Sieve Of Erathosthenes](https://github.com/thisisshub/DSA/blob/main/A_mathematics/H_sieve_of_erathosthenes.py) 9 | - [Factorial](https://github.com/thisisshub/DSA/blob/main/A_mathematics/E_factorial.py) 10 | - [Prime Factors](https://github.com/thisisshub/DSA/blob/main/A_mathematics/G_prime_factors.py) -------------------------------------------------------------------------------- /F_sorting/problems/D_kth_smallest_element.py: -------------------------------------------------------------------------------- 1 | def method1(arr, n, k): 2 | arr.sort() 3 | return arr[k - 1] 4 | 5 | 6 | def method2(arr, k): 7 | import heapq 8 | 9 | smallest = [] 10 | for value in arr: 11 | if len(smallest) < k: 12 | heapq.heappush(smallest, -value) 13 | else: 14 | heapq.heappushpop(smallest, -value) 15 | if len(smallest) < k: 16 | return None 17 | return -smallest[0] 18 | 19 | 20 | if __name__ == "__main__": 21 | """ 22 | from timeit import timeit 23 | arr = [12, 3, 5, 7, 19] 24 | n = len(arr) 25 | k = 2 26 | print(timeit(lambda: method1(arr, n, k), number=10000)) # 0.0018417680003040005 27 | print(timeit(lambda: method2(arr, k), number=10000)) # 0.009863699999186792 28 | """ 29 | -------------------------------------------------------------------------------- /G_matrix/F_check_if_the_element_is_present_in_a_row_and_column-wise_sorted_matrix.py: -------------------------------------------------------------------------------- 1 | def method1(): 2 | def search(mat, n, x): 3 | i = 0 4 | j = n - 1 5 | while i < n and j >= 0: 6 | if mat[i][j] == x: 7 | print("n Found at ", i, ", ", j) 8 | return 1 9 | if mat[i][j] > x: 10 | j -= 1 11 | else: 12 | i += 1 13 | 14 | print("Element not found") 15 | return 0 16 | 17 | mat = [[10, 20, 30, 40], [15, 25, 35, 45], [27, 29, 37, 48], [32, 33, 39, 50]] 18 | 19 | return search(mat, 4, 29) 20 | 21 | 22 | if __name__ == "__main__": 23 | """ 24 | from timeit import timeit 25 | print(timeit(lambda: method1(), number=10000)) # 0.06679722199987737 26 | """ 27 | -------------------------------------------------------------------------------- /N_tree/problems/C_height_of_binary_tree.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.left = None 5 | self.right = None 6 | 7 | 8 | def method1(node): 9 | if node is None: 10 | return -1 11 | 12 | else: 13 | 14 | lDepth = method1(node.left) 15 | rDepth = method1(node.right) 16 | 17 | if lDepth > rDepth: 18 | return lDepth + 1 19 | else: 20 | return rDepth + 1 21 | 22 | 23 | if __name__ == "__main__": 24 | """ 25 | from timeit import timeit 26 | 27 | root = Node(1) 28 | root.left = Node(2) 29 | root.right = Node(3) 30 | root.left.left = Node(4) 31 | root.left.right = Node(5) 32 | 33 | print(timeit(lambda: (method1(root)), number=10000)) 34 | """ 35 | -------------------------------------------------------------------------------- /E_searching/recursive/A_binary_search_recursive.py: -------------------------------------------------------------------------------- 1 | def method1_recursive(l: list, low: int, high: int, x: int) -> int: 2 | if high >= low: 3 | mid = low + (high-low)// 2 #to avoid overflow error for large values 4 | if l[mid] == x: 5 | return mid 6 | elif l[mid] > x: 7 | return method1_recursive(l, low, mid - 1, x) 8 | else: 9 | return method1_recursive(l, mid + 1, high, x) 10 | else: 11 | return -1 12 | return method1_recursive(l, 0, len(l) - 1, x) 13 | 14 | 15 | if __name__ == "__main__": 16 | """ 17 | n = 9999 18 | l = [i for i in range(10000)] # [0, 1, 3, ...., 9999] 19 | from timeit import timeit 20 | print(timeit(lambda: method1_recursive(l, 0, len(l)-1, n), number=10000)) # 0.03099031199963065 21 | """ 22 | -------------------------------------------------------------------------------- /E_searching/two_pointer_approach_problems/C_find_triplet_in_an_array_which_gives_sum_x.py: -------------------------------------------------------------------------------- 1 | def method1(ll: list, n: int, sum: int) -> list: 2 | ll.sort() 3 | for i in range(0, n - 2): 4 | l = i + 1 5 | r = n - 1 6 | while l < r: 7 | if ll[i] + ll[l] + ll[r] == sum: 8 | print("Triplet is", ll[i], ", ", ll[l], ", ", ll[r]) 9 | return True 10 | elif ll[i] + ll[l] + ll[r] < sum: 11 | l += 1 12 | else: 13 | r -= 1 14 | return False 15 | 16 | 17 | if __name__ == "__main__": 18 | """ 19 | from timeit import timeit 20 | ll = [1, 4, 45, 6, 10, 8] 21 | sum = 22 22 | n = len(ll) 23 | print(timeit(lambda: method1(ll, n, sum), number=10000)) # 0.13895291699918744 24 | """ 25 | -------------------------------------------------------------------------------- /D_arrays/problems/trapping_rain_water.py: -------------------------------------------------------------------------------- 1 | def method1(): 2 | def findWater(arr, n): 3 | left = [0] * n 4 | right = [0] * n 5 | water = 0 6 | left[0] = arr[0] 7 | for i in range(1, n): 8 | left[i] = max(left[i - 1], arr[i]) 9 | right[n - 1] = arr[n - 1] 10 | for i in range(n - 2, -1, -1): 11 | right[i] = max(right[i + 1], arr[i]) 12 | for i in range(0, n): 13 | water += min(left[i], right[i]) - arr[i] 14 | return water 15 | 16 | arr = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1] 17 | n = len(arr) 18 | 19 | return findWater(arr, n) 20 | 21 | 22 | if __name__ == "__main__": 23 | """ 24 | from timeit import timeit 25 | print(timeit(lambda: method1(), number=10000)) # 0.13557261999812908 26 | """ 27 | -------------------------------------------------------------------------------- /G_matrix/G_boundary_traversal.py: -------------------------------------------------------------------------------- 1 | def method1(): 2 | def printBoundary(a, m, n): 3 | for i in range(m): 4 | for j in range(n): 5 | if i == 0: 6 | print(a[i][j]), 7 | elif i == m - 1: 8 | print(a[i][j]), 9 | elif j == 0: 10 | print(a[i][j]), 11 | elif j == n - 1: 12 | print(a[i][j]), 13 | else: 14 | print(" "), 15 | print() 16 | 17 | a = [[1, 2, 3, 4], [5, 6, 7, 8], [1, 2, 3, 4], [5, 6, 7, 8]] 18 | return printBoundary(a, 4, 4) 19 | 20 | 21 | if __name__ == "__main__": 22 | """ 23 | from timeit import timeit 24 | print(timeit(lambda: method1(), number=10000)) # 0.8269144149999192 25 | """ 26 | -------------------------------------------------------------------------------- /Z_tests/test_D_arrays.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | sys.path.append("../") 4 | 5 | from D_arrays.types_of_arrays import A_fixed_size_array, B_dynamic_size_array 6 | from D_arrays.operation_on_arrays import A_searching 7 | 8 | 9 | class Test_D_arrays: 10 | def test_A_fixed_array(self): 11 | assert len(A_fixed_size_array.method1()) == 5 12 | 13 | def test_B_dynamic_array(self): 14 | n = [] 15 | assert len(B_dynamic_size_array.method1(n)) == 0 16 | n = [1, 2, 3, 4, 5, 6] 17 | assert len(B_dynamic_size_array.method1(n)) == 6 18 | 19 | def test_A_searching(self): 20 | n = 9 21 | l = [i for i in range(10)] 22 | assert A_searching.method1(l, 0, len(l) - 1, n) == 9 23 | assert A_searching.method2(n, l) == True 24 | assert A_searching.method3(n, l) == True 25 | -------------------------------------------------------------------------------- /E_searching/two_pointer_approach_problems/B_find_pair_in_a_sorted_array_which_gives_sum_x.py: -------------------------------------------------------------------------------- 1 | MAX_VAL = 1000000000 2 | 3 | 4 | def method1(ll: list, n: int, x: int) -> list: 5 | res_l, res_r = 0, 0 6 | l, r, diff = 0, n - 1, MAX_VAL 7 | while r > l: 8 | if abs(ll[l] + ll[r] - x) < diff: 9 | res_l = l 10 | res_r = r 11 | diff = abs(ll[l] + ll[r] - x) 12 | 13 | if ll[l] + ll[r] > x: 14 | r -= 1 15 | else: 16 | l += 1 17 | print("The closest pair is {} and {}".format(ll[res_l], ll[res_r])) 18 | 19 | 20 | if __name__ == "__main__": 21 | """ 22 | ll = [10, 22, 28, 29, 30, 40] 23 | n = len(ll) 24 | x=54 25 | from timeit import timeit 26 | print(timeit(lambda: method1(ll, n, x), number=10000)) # 0.16023965299973497 27 | """ 28 | -------------------------------------------------------------------------------- /E_searching/problems/G_find_an_element_in_an_infinite_sized_sorted_array.py: -------------------------------------------------------------------------------- 1 | def binary_search(ll: list,l: int,r:int,x: int) -> int: 2 | if r >= l: 3 | mid = int(l+(r-l)/2) 4 | if ll[mid] == x: 5 | return mid 6 | if ll[mid] > x: 7 | return binary_search(ll,l,mid-1,x) 8 | return binary_search(ll,mid+1,r,x) 9 | return -1 10 | 11 | 12 | def method1(a, key): 13 | l, h, val = 0, 1, ll[0] 14 | while val < key: 15 | l = h 16 | h = 2*h 17 | val = ll[h] 18 | return binary_search(a, l, h, key) 19 | 20 | 21 | if __name__ == "__main__": 22 | """ 23 | from timeit import timeit 24 | ll = [3, 5, 7, 9, 10, 90, 100, 130, 140, 160, 170] 25 | print(timeit(lambda: method1(ll,10), number=10000)) # 0.007889933999649656 26 | """ -------------------------------------------------------------------------------- /F_sorting/H_countingsort.py: -------------------------------------------------------------------------------- 1 | def method1(ll: list) -> list: 2 | def countSort(ll): 3 | output = [0 for i in range(256)] 4 | count = [0 for i in range(256)] 5 | ans = ["" for _ in ll] 6 | 7 | for i in ll: 8 | count[ord(i)] += 1 9 | 10 | for i in range(256): 11 | count[i] += count[i - 1] 12 | 13 | for i in range(len(ll)): 14 | output[count[ord(ll[i])] - 1] = ll[i] 15 | count[ord(ll[i])] -= 1 16 | 17 | for i in range(len(ll)): 18 | ans[i] = output[i] 19 | return ans 20 | 21 | return countSort(ll) 22 | 23 | 24 | if __name__ == "__main__": 25 | """ 26 | l = ['1', '3', '4', '7', '5', '9'] 27 | from timeit import timeit 28 | print(timeit(lambda: method1(l), number=10000)) # 0.329147156997351 29 | """ 30 | -------------------------------------------------------------------------------- /A_mathematics/H_sieve_of_erathosthenes.py: -------------------------------------------------------------------------------- 1 | # Python program to print all primes smaller than or equal to 2 | # n using Sieve of Eratosthenes 3 | 4 | def method1(n: int) -> int: 5 | ''' 6 | Create a boolean array "sieve[0..n]" and initialize 7 | all entries it as true. A value in sieve[i] will 8 | finally be false if i is Not a prime, else true. 9 | ''' 10 | if n <= 2: 11 | return [] 12 | else: 13 | sieve = [True] * (n + 1) 14 | for x in range(3, int(n ** 0.5) + 1, 2): 15 | for y in range(3, (n // x) + 1, 2): 16 | sieve[(x * y)] = False 17 | return [2] + [i for i in range(3, n, 2) if sieve[i]] 18 | 19 | 20 | if __name__ == "__main__": 21 | """ 22 | from timeit import timeit 23 | print(timeit(lambda: method1(20), number=10000)) # 0.015664431000914192 24 | """ 25 | -------------------------------------------------------------------------------- /D_arrays/problems/check_if_sorted.py: -------------------------------------------------------------------------------- 1 | def method1(ll: list, n: int) -> bool: 2 | import sys 3 | 4 | minEle = sys.maxsize 5 | minIndex = -1 6 | for i in range(n): 7 | if ll[i] < minEle: 8 | minEle = ll[i] 9 | minIndex = i 10 | flag1 = 1 11 | for i in range(1, minIndex): 12 | if ll[i] < ll[i - 1]: 13 | flag1 = 0 14 | break 15 | flag2 = 2 16 | for i in range(minIndex + 1, n): 17 | if ll[i] < ll[i - 1]: 18 | flag2 = 0 19 | break 20 | return True if (flag1 and flag2 and ll[n - 1] < ll[0]) else False 21 | 22 | 23 | if __name__ == "__main__": 24 | """ 25 | from timeit import timeit 26 | ll = [3, 4, 5, 1, 2] 27 | n = len(ll) 28 | print(timeit(lambda: method1(ll, n), number=10000)) # 0.0164304289996835 29 | """ 30 | -------------------------------------------------------------------------------- /T_dynamic_programming/problems/knapsack_problem/B_efficient_approach.py: -------------------------------------------------------------------------------- 1 | def method1(W, wt, val, n): 2 | K = [[0 for x in range(W + 1)] for x in range(n + 1)] 3 | 4 | # Build table K[][] in bottom up manner 5 | for i in range(n + 1): 6 | for w in range(W + 1): 7 | if i == 0 or w == 0: 8 | K[i][w] = 0 9 | elif wt[i - 1] <= w: 10 | K[i][w] = max(val[i - 1] + K[i - 1][w - wt[i - 1]], K[i - 1][w]) 11 | else: 12 | K[i][w] = K[i - 1][w] 13 | 14 | return K[n][W] 15 | 16 | 17 | if __name__ == "__main__": 18 | """ 19 | from timeit import timeit 20 | 21 | val = [60, 100, 120] 22 | wt = [10, 20, 30] 23 | W = 50 24 | n = len(val) 25 | print(timeit(lambda: method1(W, wt, val, n), number=10000)) # 0.4825399399996968 26 | """ 27 | -------------------------------------------------------------------------------- /F_sorting/problems/B_union_of_2_sorted_arrays.py: -------------------------------------------------------------------------------- 1 | def method1(ll1, ll2): 2 | m = ll1[-1] 3 | n = ll2[-1] 4 | ans = 0 5 | 6 | if m > n: 7 | ans = m 8 | else: 9 | ans = n 10 | 11 | newtable = [0] * (ans + 1) 12 | print(ll1[0], end=" ") 13 | newtable[ll1[0]] += 1 14 | for i in range(1, len(ll1)): 15 | if ll1[i] != ll1[i - 1]: 16 | print(ll1[i], end=" ") 17 | newtable[ll1[i]] += 1 18 | for j in range(0, len(ll2)): 19 | if newtable[ll2[j]] == 0: 20 | print(ll2[j], end=" ") 21 | newtable[ll2[j]] += 1 22 | 23 | 24 | if __name__ == "__main__": 25 | """ 26 | from timeit import timeit 27 | ll1 = [1, 2, 2, 2, 3] 28 | ll2 = [2, 3, 4, 5] 29 | print(timeit(lambda: method1(ll1, ll2), number=10000)) # 0.05352691199914261 30 | """ 31 | -------------------------------------------------------------------------------- /I_string/C_given_a_string_find_the_leftmost_character_that_does_not_repeat.py: -------------------------------------------------------------------------------- 1 | def method1(string: str) -> str: 2 | def character_count_array(string: str) -> int: 3 | count = [0] * 256 4 | for i in string: 5 | count[ord(i)] += 1 6 | return count 7 | 8 | def first_non_repeating(string: str) -> int: 9 | count = character_count_array(string) 10 | index = -1 11 | k = 0 12 | for i in string: 13 | if count[ord(i)] == 1: 14 | index = k 15 | break 16 | k += 1 17 | return index 18 | 19 | index = first_non_repeating(string) 20 | return string[index] 21 | 22 | 23 | if __name__ == "__main__": 24 | """ 25 | from timeit import timeit 26 | print(timeit(lambda: method1("thisisisastring"), number=10000)) 27 | """ 28 | -------------------------------------------------------------------------------- /P_heap/problems/A_sort_ksorted_array.py: -------------------------------------------------------------------------------- 1 | from heapq import heappop, heappush, heapify 2 | 3 | 4 | def print_array(arr: list): 5 | for elem in arr: 6 | print(elem, end=" ") 7 | 8 | 9 | def sort_k(arr: list, n: int, k: int): 10 | heap = arr[: k + 1] 11 | 12 | heapify(heap) 13 | 14 | target_index = 0 15 | for rem_elmnts_index in range(k + 1, n): 16 | arr[target_index] = heappop(heap) 17 | heappush(heap, arr[rem_elmnts_index]) 18 | target_index += 1 19 | 20 | while heap: 21 | arr[target_index] = heappop(heap) 22 | target_index += 1 23 | 24 | 25 | if __name__ == "__main__": 26 | """ 27 | from timeit import timeit 28 | 29 | k = 3 30 | arr = [2, 6, 3, 12, 56, 8] 31 | n = len(arr) 32 | print(timeit(lambda: sort_k(arr, n, k), number=10000)) # 0.010045346996776061 33 | """ -------------------------------------------------------------------------------- /H_hashing/problems/G_subarray_with_given_sum.py: -------------------------------------------------------------------------------- 1 | def method1(ll: list, n: int, sum: int) -> int: 2 | curr_sum = ll[0] 3 | start = 0 4 | i = 1 5 | while i <= n: 6 | while curr_sum > sum and start < i - 1: 7 | curr_sum = curr_sum - ll[start] 8 | start += 1 9 | if curr_sum == sum: 10 | print("Sum found between indexes") 11 | print("% d and % d" % (start, i - 1)) 12 | return 1 13 | if i < n: 14 | curr_sum = curr_sum + ll[i] 15 | i += 1 16 | print("No subarray found") 17 | return 0 18 | 19 | 20 | if __name__ == "__main__": 21 | """ 22 | from timeit import timeit 23 | ll = [15, 2, 4, 8, 9, 5, 10, 23] 24 | n = len(ll) 25 | sum = 23 26 | print(timeit(lambda: method1(ll, n, sum), number=10000)) # 0.28271653299452737 27 | """ 28 | -------------------------------------------------------------------------------- /H_hashing/problems/J_longest_common_span_with_the_same_sum_in_a_binary_array.py: -------------------------------------------------------------------------------- 1 | def method1(ll1: list, ll2: list, n: int) -> int: 2 | maxLen = 0 3 | presum1 = presum2 = 0 4 | diff = {} 5 | for i in range(n): 6 | presum1 += ll1[i] 7 | presum2 += ll2[i] 8 | curr_diff = presum1 - presum2 9 | if curr_diff == 0: 10 | maxLen = i + 1 11 | elif curr_diff not in diff: 12 | diff[curr_diff] = i 13 | else: 14 | length = i - diff[curr_diff] 15 | maxLen = max(maxLen, length) 16 | 17 | return maxLen 18 | 19 | 20 | if __name__ == "__main__": 21 | """ 22 | from timeit import timeit 23 | ll1 = [0, 1, 0, 1, 1, 1, 1] 24 | ll2 = [1, 1, 1, 1, 1, 0, 1] 25 | print(timeit(lambda: method1(ll1, ll2, len(ll1)), number=10000)) # 0.03265197800647002 26 | """ 27 | -------------------------------------------------------------------------------- /H_hashing/problems/L_count_distinct_elements_in_every_window.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | 4 | def method1(ll: list, k: int, n: int) -> int: 5 | mp = defaultdict(lambda: 0) 6 | dist_count = 0 7 | for i in range(k): 8 | if mp[ll[i]] == 0: 9 | dist_count += 1 10 | mp[ll[i]] += 1 11 | print(dist_count) 12 | for i in range(k, n): 13 | if mp[ll[i - k]] == 1: 14 | dist_count -= 1 15 | mp[ll[i - k]] -= 1 16 | if mp[ll[i]] == 0: 17 | dist_count += 1 18 | mp[ll[i]] += 1 19 | print(dist_count) 20 | 21 | 22 | if __name__ == "__main__": 23 | """ 24 | from timeit import timeit 25 | ll = [1, 2, 1, 3, 4, 2, 3] 26 | n = len(ll) 27 | k = 4 28 | print(timeit(lambda: method1(ll, k, n), number=10000)) # 0.2502135280010407 29 | """ 30 | -------------------------------------------------------------------------------- /B_bit_magic/Z_bit_magic.md: -------------------------------------------------------------------------------- 1 | # List of Contents 2 | 3 | - [Operation And](https://github.com/thisisshub/DSA/blob/main/B_bit_magic/A_operation_and.py) 4 | - [Operation Or](https://github.com/thisisshub/DSA/blob/main/B_bit_magic/B_operation_or.py) 5 | - [Operation Xor](https://github.com/thisisshub/DSA/blob/main/B_bit_magic/C_operation_xor.py) 6 | - [Operation Complement](https://github.com/thisisshub/DSA/blob/main/B_bit_magic/D_operation_complement.py) 7 | - [Operation Leftshit Rightshift](https://github.com/thisisshub/DSA/blob/main/B_bit_magic/E_operation_leftshit_rightshift.py) 8 | - [Count Setbit](https://github.com/thisisshub/DSA/blob/main/B_bit_magic/F_count_setbit.py) 9 | - [Brian Kerningham](https://github.com/thisisshub/DSA/blob/main/B_bit_magic/G_brian_kerningham.py) 10 | - [Using Lookuptable](https://github.com/thisisshub/DSA/blob/main/B_bit_magic/H_using_lookuptable.py) -------------------------------------------------------------------------------- /T_dynamic_programming/problems/J_subset_sum_problem.py: -------------------------------------------------------------------------------- 1 | def method1(set, n, sum): 2 | 3 | if sum == 0: 4 | return True 5 | if n == 0: 6 | return False 7 | 8 | # If last element is greater than 9 | # sum, then ignore it 10 | if set[n - 1] > sum: 11 | return method1(set, n - 1, sum) 12 | 13 | # else, check if sum can be obtained 14 | # by any of the following 15 | # (a) including the last element 16 | # (b) excluding the last element 17 | return method1(set, n - 1, sum) or method1(set, n - 1, sum - set[n - 1]) 18 | 19 | 20 | if __name__ == "__main__": 21 | """ 22 | from timeit import timeit 23 | 24 | set = [3, 34, 4, 12, 5, 2] 25 | sum = 9 26 | n = len(set) 27 | print( 28 | timeit(lambda: method1(set, n, sum) == True, number=10000) 29 | ) # 0.023161377001088113 30 | """ 31 | -------------------------------------------------------------------------------- /T_dynamic_programming/problems/long_increasing_subsequence_problem/A_naive_approach.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def lengthOfLIS(self, nums): 3 | tails = [0 for i in range(len(nums))] 4 | size = 0 5 | for x in nums: 6 | i = 0 7 | j = size 8 | while i != j: 9 | mid = i + (j - i) // 2 10 | if tails[mid] < x: 11 | i = mid + 1 12 | else: 13 | j = mid 14 | tails[i] = x 15 | size = max(i + 1, size) 16 | return size 17 | 18 | 19 | if __name__ == "__main__": 20 | """ 21 | from timeit import timeit 22 | 23 | ob1 = Solution() 24 | print( 25 | timeit(lambda: ob1.lengthOfLIS([10, 9, 2, 5, 3, 7, 101, 18]), number=10000) 26 | ) # 0.006747746003384236 27 | """ -------------------------------------------------------------------------------- /A_mathematics/D_lcm.py: -------------------------------------------------------------------------------- 1 | def method1(n: int, m: int) -> int: 2 | '''This function computes LCM 3 | calculated from GCD by Euclidean Algorithm. 4 | ''' 5 | 6 | def gcd(n: int, m: int) -> int: 7 | '''This function computes GCD.''' 8 | 9 | while m: 10 | n, m = m, n % m 11 | return n 12 | 13 | return abs((n * m) // gcd(n, m)) 14 | 15 | 16 | def method2(n: int, m: int) -> int: 17 | '''This function computes LCM 18 | calculated from GCD by inbuilt gcd() method. 19 | ''' 20 | 21 | from math import gcd 22 | 23 | return abs(n * m) // gcd(n, m) 24 | 25 | 26 | if __name__ == "__main__": 27 | """ 28 | from timeit import timeit 29 | print(timeit(lambda: method1(2, 3), number=10000)) # 0.0052234140021028 30 | print(timeit(lambda: method2(2, 3), number=10000)) # 0.010972605999995722 31 | """ 32 | -------------------------------------------------------------------------------- /P_heap/A_heap_sort.py: -------------------------------------------------------------------------------- 1 | def heapify(arr, n, i): 2 | largest = i 3 | l = 2 * i + 1 4 | r = 2 * i + 2 5 | 6 | if l < n and arr[i] < arr[l]: 7 | largest = l 8 | 9 | if r < n and arr[largest] < arr[r]: 10 | largest = r 11 | 12 | if largest != i: 13 | arr[i], arr[largest] = arr[largest], arr[i] 14 | 15 | heapify(arr, n, largest) 16 | 17 | 18 | def heapSort(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 | 29 | if __name__ == "__main__": 30 | """ 31 | from timeit import timeit 32 | 33 | arr = [12, 11, 13, 5, 6, 7] 34 | n = len(arr) 35 | print(timeit(lambda: heapSort(arr), number=10000)) # 0.049621981001109816 36 | """ 37 | -------------------------------------------------------------------------------- /R_greedy/C_job_sequencing_problem.py: -------------------------------------------------------------------------------- 1 | def method1(arr, t): 2 | 3 | n = len(arr) 4 | 5 | for i in range(n): 6 | for j in range(n - 1 - i): 7 | if arr[j][2] < arr[j + 1][2]: 8 | arr[j], arr[j + 1] = arr[j + 1], arr[j] 9 | 10 | result = [False] * t 11 | 12 | job = ["-1"] * t 13 | 14 | for i in range(len(arr)): 15 | 16 | for j in range(min(t - 1, arr[i][1] - 1), -1, -1): 17 | 18 | if result[j] is False: 19 | result[j] = True 20 | job[j] = arr[i][0] 21 | break 22 | 23 | print(job) 24 | 25 | 26 | if __name__ == "__main__": 27 | """ 28 | from timeit import timeit 29 | 30 | arr = [["a", 2, 100], ["b", 1, 19], ["c", 2, 27], ["d", 1, 25], ["e", 3, 15]] 31 | 32 | print(timeit(lambda: method1(arr, 3), number=10000)) # 0.08790500099712517 33 | """ 34 | -------------------------------------------------------------------------------- /F_sorting/problems/G_merge_overlapping_intervals.py: -------------------------------------------------------------------------------- 1 | def method1(arr: list) -> list: 2 | arr.sort(key=lambda x: x[0]) 3 | m = [] 4 | s = -10000 5 | max = -100000 6 | for i in range(len(arr)): 7 | a = arr[i] 8 | if a[0] > max: 9 | if i != 0: 10 | m.append([s, max]) 11 | max = a[1] 12 | s = a[0] 13 | else: 14 | if a[1] >= max: 15 | max = a[1] 16 | 17 | if max != -100000 and [s, max] not in m: 18 | m.append([s, max]) 19 | print("The Merged Intervals are :", end=" ") 20 | for i in range(len(m)): 21 | print(m[i], end=" ") 22 | 23 | 24 | if __name__ == "__main__": 25 | """ 26 | from timeit import timeit 27 | arr = [[6, 8], [1, 9], [2, 4], [4, 7]] 28 | print(timeit(lambda: method1(arr), number=10000)) # 0.09757556899967312 29 | """ 30 | -------------------------------------------------------------------------------- /T_dynamic_programming/problems/C_maximum_cuts.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | # A utility function to get the 4 | # maximum of two integers 5 | def max(a, b): 6 | return a if (a > b) else b 7 | 8 | 9 | # Returns the best obtainable price for a rod of length n 10 | # and price[] as prices of different pieces 11 | def cutRod(price, n): 12 | if n <= 0: 13 | return 0 14 | max_val = -sys.maxsize - 1 15 | 16 | # Recursively cut the rod in different pieces 17 | # and compare different configurations 18 | for i in range(0, n): 19 | max_val = max(max_val, price[i] + cutRod(price, n - i - 1)) 20 | return max_val 21 | 22 | 23 | if __name__ == "__main__": 24 | """ 25 | from timeit import timeit 26 | 27 | arr = [1, 5, 8, 9, 10, 17, 17, 20] 28 | size = len(arr) 29 | print(timeit(lambda: cutRod(arr, size), number=10000)) # 0.7375893329954124 30 | """ 31 | -------------------------------------------------------------------------------- /E_searching/problems/I_median_of_two_sorted_arrays.py: -------------------------------------------------------------------------------- 1 | def method1(ll, ll2, n): 2 | i = j = 0 3 | m1 = m2 = -1 4 | count = 0 5 | while count < n + 1: 6 | count += 1 7 | if i == n: 8 | m1 = m2 9 | m2 = ll2[0] 10 | break 11 | elif j == n: 12 | m1 = m2 13 | m2 = ll[0] 14 | break 15 | if ll[i] <= ll2[j]: 16 | m1 = m2 17 | m2 = ll[i] 18 | i += 1 19 | else: 20 | m1 = m2 21 | m2 = ll2[j] 22 | j += 1 23 | return (m1 + m2) / 2 24 | 25 | 26 | if __name__ == "__main__": 27 | """ 28 | from timeit import timeit 29 | ll = [1, 12, 15, 26, 38] 30 | ll2 = [2, 13, 17, 30, 45] 31 | n1 = len(ll) 32 | n2 = len(ll2) 33 | print(timeit(lambda: method1(ll, ll2, n1), number=10000)) # 0.011695754000356828 34 | """ 35 | -------------------------------------------------------------------------------- /U_trie/E_count_distinct_rows_in_a_binary_matrix.py: -------------------------------------------------------------------------------- 1 | def method1(s, m, n): 2 | 3 | # Initialize variable count that 4 | # stores the count of duplicate rows. 5 | i, j, count = 0, 0, 0 6 | 7 | # Take two nested loop and 8 | # check weather rows already 9 | # get seen then increment 10 | # count by 1 then break the loop. 11 | for i in range(n): 12 | for j in range(i): 13 | if s[i] == s[j]: 14 | count += 1 15 | break 16 | 17 | # Check if count>=1 then prNo 18 | # Else prYes. 19 | if count >= 1: 20 | print("No") 21 | else: 22 | print("Yes") 23 | 24 | 25 | if __name__ == "__main__": 26 | """ 27 | from timeit import timeit 28 | 29 | m = 3 30 | n = 3 31 | s = [[1, 0, 1], [0, 0, 0], [1, 0, 0]] 32 | 33 | print(timeit(lambda: method1(s, m, n), number=10000)) # 0.04088545798731502 34 | """ 35 | -------------------------------------------------------------------------------- /O_binary_search_tree/B_insertion_in_bst.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | left = right = None 3 | 4 | def __init__(self, data): 5 | self.data = data 6 | 7 | 8 | def inorder(root): 9 | 10 | if root is None: 11 | return 12 | 13 | inorder(root.left) 14 | print(root.data, end=" ") 15 | inorder(root.right) 16 | 17 | 18 | def insert(root, key): 19 | 20 | if root is None: 21 | return Node(key) 22 | 23 | if key < root.data: 24 | root.left = insert(root.left, key) 25 | 26 | else: 27 | 28 | root.right = insert(root.right, key) 29 | 30 | return root 31 | 32 | 33 | if __name__ == "__main__": 34 | """ 35 | from timeit import timeit 36 | 37 | root = None 38 | keys = [15, 10, 20, 8, 12, 16, 25] 39 | 40 | for key in keys: 41 | root = insert(root, key) 42 | print(timeit(lambda: root, number=10000)) # 0.00042487999962759204 43 | """ 44 | -------------------------------------------------------------------------------- /F_sorting/problems/H_meeting_the_maximum_guests.py: -------------------------------------------------------------------------------- 1 | class Meeting: 2 | def __init__(self, start, end, pos): 3 | 4 | self.start = start 5 | self.end = end 6 | self.pos = pos 7 | 8 | 9 | def maxMeeting(l, n): 10 | ans = [] 11 | l.sort(key=lambda x: x.end) 12 | ans.append(l[0].pos) 13 | time_limit = l[0].end 14 | for i in range(1, n): 15 | if l[i].start > time_limit: 16 | ans.append(l[i].pos) 17 | time_limit = l[i].end 18 | 19 | for i in ans: 20 | print(i + 1, end=" ") 21 | print() 22 | 23 | 24 | if __name__ == "__main__": 25 | """ 26 | from timeit import timeit 27 | s = [ 1, 3, 0, 5, 8, 5 ] 28 | f = [ 2, 4, 6, 7, 9, 9 ] 29 | n = len(s) 30 | l = [] 31 | for i in range(n): 32 | l.append(Meeting(s[i], f[i], i)) 33 | print(timeit(lambda: maxMeeting(l, n), number=10000)) # 0.21075720799854025 34 | """ 35 | -------------------------------------------------------------------------------- /O_binary_search_tree/problems/A_the_ceiling_of_a_key_in_bst.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.key = data 4 | self.left = None 5 | self.right = None 6 | 7 | 8 | def ceil(root, inp): 9 | 10 | if root == None: 11 | return -1 12 | 13 | if root.key == inp: 14 | return root.key 15 | 16 | if root.key < inp: 17 | return ceil(root.right, inp) 18 | 19 | val = ceil(root.left, inp) 20 | return val if val >= inp else root.key 21 | 22 | 23 | if __name__ == "__main__": 24 | """ 25 | from timeit import timeit 26 | 27 | root = Node(8) 28 | 29 | root.left = Node(4) 30 | root.right = Node(12) 31 | 32 | root.left.left = Node(2) 33 | root.left.right = Node(6) 34 | 35 | root.right.left = Node(10) 36 | root.right.right = Node(14) 37 | 38 | print(timeit(lambda: ceil(root, 1), number=10000)) # 0.006074376993637998 39 | """ -------------------------------------------------------------------------------- /A_mathematics/A_count_digits.py: -------------------------------------------------------------------------------- 1 | def method1(n: int) -> int: 2 | '''Return the length of the string 3 | 4 | convert the integer to a string and get the length of the string. 5 | ''' 6 | return len(str(abs(n))) # ‘abs’ is used to handle the case even if the number is negative. 7 | 8 | 9 | def method2(n: int) -> int: 10 | '''Return th length by math.log10() function 11 | 12 | Add 1 to the result obtained by math.log() because the log of any number 13 | is 1 less than the number of digits inside that number. 14 | ''' 15 | import math 16 | 17 | return int(math.log10(n) + 1 if n > 0 else (1 if n == 0 else math.log10(-n) + 1)) 18 | 19 | 20 | if __name__ == "__main__": 21 | """ 22 | from timeit import timeit 23 | print(timeit(lambda: method1(1234567890), number=10000)) # 0.0022839140001451597 24 | print(timeit(lambda: method2(1234567890), number=10000)) # 0.004222848001518287 25 | """ 26 | -------------------------------------------------------------------------------- /A_mathematics/F_prime_number.py: -------------------------------------------------------------------------------- 1 | def method1(n: int) -> bool: 2 | '''Return a boolean value to check if 3 | there exists any factors greater than 1 4 | by using range() 5 | ''' 6 | 7 | return n > 1 and all(n % i for i in range(2, int(n ** 0.5) + 1)) 8 | 9 | 10 | def method2(n: int) -> bool: 11 | '''Return a boolean value to check if 12 | there exists any factors greater than 1 13 | by using islice() and count() methods of itertools 14 | ''' 15 | from itertools import count, islice 16 | 17 | def prime(n: int) -> bool: 18 | return n > 1 and all(n % i for i in islice(count(2), int((n) ** 0.5 - 1))) 19 | 20 | return prime(n) 21 | 22 | 23 | if __name__ == "__main__": 24 | """ 25 | from timeit import timeit 26 | print(timeit(lambda: method1(10), number=10000)) # 0.006183429999509826 27 | print(timeit(lambda: method2(10), number=10000)) # 0.015483204999327427 28 | """ 29 | -------------------------------------------------------------------------------- /C_recursion/E_tail_recursion.py: -------------------------------------------------------------------------------- 1 | """A special form of recursion where the 2 | last operation of a function is a recursive call. """ 3 | 4 | 5 | def tailrecursive(n: int, a=1) -> int: 6 | if n == 0: 7 | return a 8 | return tailrecursive(n - 1, n * a) 9 | 10 | 11 | def nontailrecursive(n: int) -> int: 12 | # The function is not tail 13 | # recursive because the value 14 | # returned by nontailrecursive(n-1) is used 15 | # in nontailrecursive(n) and call to nontailrecursive(n-1) 16 | # is not the last thing done by 17 | # nontailrecursive(n) 18 | if n == 0: 19 | return 1 20 | return n * nontailrecursive(n - 1) 21 | 22 | 23 | if __name__ == "__main__": 24 | """ 25 | from timeit import timeit 26 | print(timeit(lambda: tailrecursive(10), number=10000)) # 0.012317868999161874 27 | print(timeit(lambda: nontailrecursive(10), number=10000)) # 0.010385317998952814 28 | """ 29 | -------------------------------------------------------------------------------- /N_tree/problems/B_maximum_in_binary_tree.py: -------------------------------------------------------------------------------- 1 | class newNode: 2 | def __init__(self, data): 3 | self.data = data 4 | self.left = self.right = None 5 | 6 | 7 | def findMax(root): 8 | 9 | if root == None: 10 | return float("-inf") 11 | 12 | res = root.data 13 | lres = findMax(root.left) 14 | rres = findMax(root.right) 15 | if lres > res: 16 | res = lres 17 | if rres > res: 18 | res = rres 19 | return res 20 | 21 | 22 | if __name__ == "__main__": 23 | """ 24 | from timeit import timeit 25 | 26 | root = newNode(2) 27 | root.left = newNode(7) 28 | root.right = newNode(5) 29 | root.left.right = newNode(6) 30 | root.left.right.left = newNode(1) 31 | root.left.right.right = newNode(11) 32 | root.right.right = newNode(9) 33 | root.right.right.left = newNode(4) 34 | 35 | print(timeit(lambda: findMax(root)), number=10000) 36 | """ 37 | -------------------------------------------------------------------------------- /P_heap/problems/B_buy_maximum_items_with_given_sum.py: -------------------------------------------------------------------------------- 1 | def number(a, n, p, k): 2 | 3 | a.sort() 4 | 5 | pre = [] 6 | for i in range(n): 7 | pre.append(0) 8 | 9 | ans = 0 10 | i = 0 11 | 12 | pre[0] = a[0] 13 | 14 | if pre[0] <= p: 15 | ans = 1 16 | 17 | for i in range(1, k - 1): 18 | pre[i] = pre[i - 1] + a[i] 19 | 20 | if pre[i] <= p: 21 | ans = i + 1 22 | 23 | pre[k - 1] = a[k - 1] 24 | 25 | for i in range(k - 1, n): 26 | if i >= k: 27 | pre[i] += pre[i - k] + a[i] 28 | 29 | if pre[i] <= p: 30 | ans = i + 1 31 | 32 | return ans 33 | 34 | 35 | if __name__ == "__main__": 36 | """ 37 | from timeit import timeit 38 | 39 | n = 5 40 | arr = [2, 4, 3, 5, 7] 41 | p = 11 42 | k = 2 43 | 44 | print(timeit(lambda: number(arr, n, p, k), number=10000)) # 0.01322143599827541 45 | """ 46 | -------------------------------------------------------------------------------- /O_binary_search_tree/problems/B_ceiling_on_the_left_side_in_an_array.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.key = data 4 | self.left = None 5 | self.right = None 6 | 7 | 8 | def ceil(root, inp): 9 | 10 | if root == None: 11 | return -1 12 | 13 | if root.key == inp: 14 | return root.key 15 | 16 | if root.key < inp: 17 | return ceil(root.right, inp) 18 | 19 | val = ceil(root.left, inp) 20 | return val if val >= inp else root.key 21 | 22 | 23 | if __name__ == "__main__": 24 | """ 25 | from timeit import timeit 26 | root = Node(8) 27 | 28 | root.left = Node(4) 29 | root.right = Node(12) 30 | 31 | root.left.left = Node(2) 32 | root.left.right = Node(6) 33 | 34 | root.right.left = Node(10) 35 | root.right.right = Node(14) 36 | 37 | print(timeit(lambda: ceil(root, 9), number=10000)) # 0.005088308003905695 38 | """ 39 | -------------------------------------------------------------------------------- /T_dynamic_programming/problems/knapsack_problem/A_naive_approach.py: -------------------------------------------------------------------------------- 1 | def method1(W, wt, val, n): 2 | 3 | # Base Case 4 | if n == 0 or W == 0: 5 | return 0 6 | 7 | # If weight of the nth item is more than Knapsack of capacity 8 | # W, then this item cannot be included in the optimal solution 9 | if wt[n - 1] > W: 10 | return method1(W, wt, val, n - 1) 11 | 12 | # return the maximum of two cases: 13 | # (1) nth item included 14 | # (2) not included 15 | else: 16 | return max( 17 | val[n - 1] + method1(W - wt[n - 1], wt, val, n - 1), 18 | method1(W, wt, val, n - 1), 19 | ) 20 | 21 | 22 | if __name__ == "__main__": 23 | """ 24 | from timeit import timeit 25 | 26 | val = [60, 100, 120] 27 | wt = [10, 20, 30] 28 | W = 50 29 | n = len(val) 30 | print(timeit(lambda: method1(W, wt, val, n), number=10000)) # 0.0221543079969706 31 | """ -------------------------------------------------------------------------------- /T_dynamic_programming/problems/G_egg_dropping_problem.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | def eggDrop(n, k): 5 | 6 | # If there are no floors, then no trials 7 | # needed. OR if there is one floor, one 8 | # trial needed. 9 | if k == 1 or k == 0: 10 | return k 11 | 12 | # We need k trials for one egg 13 | # and k floors 14 | if n == 1: 15 | return k 16 | 17 | min = sys.maxsize 18 | 19 | # Consider all droppings from 1st 20 | # floor to kth floor and return 21 | # the minimum of these values plus 1. 22 | for x in range(1, k + 1): 23 | 24 | res = max(eggDrop(n - 1, x - 1), eggDrop(n, k - x)) 25 | if res < min: 26 | min = res 27 | 28 | return min + 1 29 | 30 | 31 | if __name__ == "__main__": 32 | """ 33 | from timeit import timeit 34 | 35 | n = 2 36 | k = 10 37 | print(timeit(lambda: eggDrop(n, k), number=10000)) # 2.694228070002282 38 | """ 39 | -------------------------------------------------------------------------------- /E_searching/problems/H_the_square_root_of_an_integer.py: -------------------------------------------------------------------------------- 1 | def method1(x: int) -> int: 2 | if x == 0 or x == 1: 3 | return x 4 | i = 1 5 | result = 1 6 | while result <= x: 7 | i += 1 8 | result = i * i 9 | return i - 1 10 | 11 | 12 | def method2(x: int) -> int: 13 | if x == 0 or x == 1: 14 | return x 15 | start = 1 16 | end = x 17 | while start <= end: 18 | mid = (start + end) // 2 19 | if mid * mid == x: 20 | return mid 21 | if mid * mid < x: 22 | start = mid + 1 23 | ans = mid 24 | 25 | else: 26 | end = mid - 1 27 | 28 | return ans 29 | 30 | 31 | if __name__ == "__main__": 32 | """ 33 | from timeit import timeit 34 | x = 11 35 | print(timeit(lambda: method1(x), number=10000)) # 0.0029743499999312917 36 | print(timeit(lambda: method2(x), number=10000)) # 0.006317070000477543 37 | """ 38 | -------------------------------------------------------------------------------- /F_sorting/F_heapsort.py: -------------------------------------------------------------------------------- 1 | def method1(ll: list) -> list: 2 | def swap(i, j): 3 | ll[i], ll[j] = ll[j], ll[i] 4 | 5 | def heapify(end, i): 6 | l = 2 * i + 1 7 | r = 2 * (i + 1) 8 | max = i 9 | if l < end and ll[i] < ll[l]: 10 | max = l 11 | if r < end and ll[max] < ll[r]: 12 | max = r 13 | if max != i: 14 | swap(i, max) 15 | heapify(end, max) 16 | 17 | def heap_sort(): 18 | end = len(ll) 19 | start = end // 2 - 1 20 | for i in range(start, -1, -1): 21 | heapify(end, i) 22 | for i in range(end - 1, 0, -1): 23 | swap(i, 0) 24 | heapify(i, 0) 25 | 26 | return heap_sort() 27 | 28 | 29 | if __name__ == "__main__": 30 | """ 31 | l = [1, 3, 4, 7, 5, 9] 32 | from timeit import timeit 33 | print(timeit(lambda: method1(l), number=10000)) # 0.06693621500016889 34 | """ 35 | -------------------------------------------------------------------------------- /F_sorting/problems/A_intersection_of_2_sorted_arrays.py: -------------------------------------------------------------------------------- 1 | def method1(ll1: list, ll2: list) -> list: 2 | ll = [] 3 | for i in set(ll1): 4 | for j in set(ll2): 5 | if i == j: 6 | ll.append(i) 7 | return ll 8 | 9 | 10 | def method2(ll1: list, ll2: list, m: int, n: int) -> int: 11 | i = j = 0 12 | while i < m and j < n: 13 | if ll1[i] < ll2[j]: 14 | i += 1 15 | elif ll2[j] < ll1[i]: 16 | j += 1 17 | else: 18 | print(ll2[j]) 19 | j += 1 20 | i += 1 21 | 22 | 23 | if __name__ == "__main__": 24 | """ 25 | from timeit import timeit 26 | ll1 = [1, 2, 4, 5, 6] 27 | ll2 = [2, 3, 5, 7] 28 | m = len(ll1) 29 | n = len(ll2) 30 | print(timeit(lambda: method1(ll1, ll2), number=10000)) # 0.02140125900041312 31 | print(timeit(lambda: method2(ll1, ll2, m, n), number=10000)) # 0.06446200500067789 32 | """ 33 | -------------------------------------------------------------------------------- /F_sorting/D_mergesort.py: -------------------------------------------------------------------------------- 1 | def method1(ll: list) -> list: 2 | def merge(left: list, right: list) -> list: 3 | result = [] 4 | i, j = 0, 0 5 | while i < len(left) and j < len(right): 6 | if left[i] <= right[j]: 7 | result.append(left[i]) 8 | i += 1 9 | else: 10 | result.append(right[j]) 11 | j += 1 12 | result += left[i:] 13 | result += right[j:] 14 | return result 15 | 16 | def mergesort(list): 17 | if len(list) < 2: 18 | return list 19 | middle = len(list) / 2 20 | left = mergesort(list[:middle]) 21 | right = mergesort(list[middle:]) 22 | return merge(left, right) 23 | 24 | 25 | if __name__ == "__main__": 26 | """ 27 | l = [1, 3, 4, 7, 5, 9] 28 | from timeit import timeit 29 | print(timeit(lambda: method1(l), number=10000)) # 0.009614205999241676 30 | """ 31 | -------------------------------------------------------------------------------- /N_tree/problems/E_print_left_view_of_binary_tree.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.left = None 5 | self.right = None 6 | 7 | 8 | def leftViewUtil(root, level, max_level): 9 | 10 | if root is None: 11 | return 12 | 13 | if max_level[0] < level: 14 | print("% d\t" % (root.data)) 15 | max_level[0] = level 16 | 17 | leftViewUtil(root.left, level + 1, max_level) 18 | leftViewUtil(root.right, level + 1, max_level) 19 | 20 | 21 | def leftView(root): 22 | max_level = [0] 23 | leftViewUtil(root, 1, max_level) 24 | 25 | 26 | if __name__ == "__main__": 27 | """ 28 | from timeit import timeit 29 | 30 | root = Node(12) 31 | root.left = Node(10) 32 | root.right = Node(20) 33 | root.right.left = Node(25) 34 | root.right.right = Node(40) 35 | 36 | print(timeit(lambda: leftView(root), number=10000)) # 0.2834473659968353 37 | """ -------------------------------------------------------------------------------- /T_dynamic_programming/problems/D_minimum_coins_to_make_a_value.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | # m is size of coins array (number of different coins) 4 | def method1(coins, m, V): 5 | 6 | # base case 7 | if V == 0: 8 | return 0 9 | 10 | # Initialize result 11 | res = sys.maxsize 12 | 13 | # Try every coin that has smaller value than V 14 | for i in range(0, m): 15 | if coins[i] <= V: 16 | sub_res = method1(coins, m, V - coins[i]) 17 | 18 | # Check for INT_MAX to avoid overflow and see if 19 | # result can minimized 20 | if sub_res != sys.maxsize and sub_res + 1 < res: 21 | res = sub_res + 1 22 | 23 | return res 24 | 25 | 26 | if __name__ == "__main__": 27 | """ 28 | from timeit import timeit 29 | 30 | coins = [9, 6, 5, 1] 31 | m = len(coins) 32 | V = 11 33 | print(timeit(lambda: method1(coins, m, V), number=10000)) # 0.2552786570013268 34 | """ -------------------------------------------------------------------------------- /T_dynamic_programming/problems/K_matrix_chain_multiplication.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | def method1(p, i, j): 5 | 6 | if i == j: 7 | return 0 8 | 9 | _min = sys.maxsize 10 | 11 | # place parenthesis at different places 12 | # between first and last matrix, 13 | # recursively calculate count of 14 | # multiplications for each parenthesis 15 | # placement and return the minimum count 16 | for k in range(i, j): 17 | 18 | count = ( 19 | method1(p, i, k) 20 | + method1(p, k + 1, j) 21 | + p[i - 1] * p[k] * p[j] 22 | ) 23 | 24 | if count < _min: 25 | _min = count 26 | 27 | return _min 28 | 29 | 30 | if __name__ == "__main__": 31 | """ 32 | from timeit import timeit 33 | 34 | arr = [1, 2, 3, 4, 3] 35 | n = len(arr) 36 | 37 | print( 38 | timeit(lambda: method1(arr, 1, n - 1), number=10000) 39 | ) # 0.04756156700022984 40 | """ -------------------------------------------------------------------------------- /O_binary_search_tree/problems/D_check_for_bst.py: -------------------------------------------------------------------------------- 1 | INT_MAX = 4294967296 2 | INT_MIN = -4294967296 3 | 4 | 5 | class Node: 6 | def __init__(self, data): 7 | self.data = data 8 | self.left = None 9 | self.right = None 10 | 11 | 12 | def isBST(node): 13 | return isBSTUtil(node, INT_MIN, INT_MAX) 14 | 15 | 16 | def isBSTUtil(node, mini, maxi): 17 | 18 | if node is None: 19 | return True 20 | 21 | if node.data < mini or node.data > maxi: 22 | return False 23 | 24 | return isBSTUtil(node.left, mini, node.data - 1) and isBSTUtil( 25 | node.right, node.data + 1, maxi 26 | ) 27 | 28 | 29 | if __name__ == "__main__": 30 | """ 31 | from timeit import timeit 32 | 33 | root = Node(4) 34 | root.left = Node(2) 35 | root.right = Node(5) 36 | root.left.left = Node(1) 37 | root.left.right = Node(3) 38 | 39 | print(timeit(lambda: isBST(root), number=10000)) # 0.01445196800341364 40 | """ 41 | -------------------------------------------------------------------------------- /L_queue/problems/A_reversing_a_queue.py: -------------------------------------------------------------------------------- 1 | from queue import Queue 2 | 3 | 4 | def method1(): 5 | def Print(queue): 6 | while not queue.empty(): 7 | print(queue.queue[0], end=", ") 8 | queue.get() 9 | 10 | def reversequeue(queue): 11 | Stack = [] 12 | while not queue.empty(): 13 | Stack.append(queue.queue[0]) 14 | queue.get() 15 | while len(Stack) != 0: 16 | queue.put(Stack[-1]) 17 | Stack.pop() 18 | 19 | queue = Queue() 20 | reversequeue(queue) 21 | return Print 22 | 23 | 24 | if __name__ == "__main__": 25 | """ 26 | from timeit import timeit 27 | 28 | queue = Queue() 29 | queue.put(1) 30 | queue.put(2) 31 | queue.put(3) 32 | queue.put(4) 33 | queue.put(5) 34 | queue.put(6) 35 | queue.put(7) 36 | queue.put(8) 37 | queue.put(9) 38 | queue.put(10) 39 | print(timeit(lambda: method1(), number=10000)) 40 | """ 41 | -------------------------------------------------------------------------------- /F_sorting/E_lomutoandhoare.py: -------------------------------------------------------------------------------- 1 | def method1(l: list) -> list: 2 | def partition(arr, low, high): 3 | pivot = arr[high] 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 | arr[i + 1], arr[high] = arr[high], arr[i + 1] 10 | return i + 1 11 | 12 | def quickSort(arr, low, high): 13 | if low < high: 14 | pi = partition(arr, low, high) 15 | quickSort(arr, low, pi - 1) 16 | quickSort(arr, pi + 1, high) 17 | 18 | def printArray(arr, size): 19 | for i in range(size): 20 | print(arr[i], end=" ") 21 | print() 22 | 23 | n = len(l) 24 | return printArray(l, n) 25 | 26 | 27 | if __name__ == "__main__": 28 | """ 29 | l = [1, 3, 4, 7, 5, 9] 30 | from timeit import timeit 31 | print(timeit(method1(l), number=10000)) # 0.013673285000550095 32 | """ 33 | -------------------------------------------------------------------------------- /N_tree/problems/R_iterative_preorder_traversal.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.left = None 5 | self.right = None 6 | 7 | 8 | def iterativePreorder(root): 9 | 10 | if root is None: 11 | return 12 | 13 | nodeStack = [] 14 | nodeStack.append(root) 15 | 16 | while len(nodeStack) > 0: 17 | 18 | node = nodeStack.pop() 19 | print(node.data) 20 | 21 | if node.right is not None: 22 | nodeStack.append(node.right) 23 | if node.left is not None: 24 | nodeStack.append(node.left) 25 | 26 | 27 | if __name__ == "__main__": 28 | """ 29 | from timeit import timeit 30 | 31 | root = Node(10) 32 | root.left = Node(8) 33 | root.right = Node(2) 34 | root.left.left = Node(3) 35 | root.left.right = Node(5) 36 | root.right.left = Node(2) 37 | print(timeit(lambda: iterativePreorder(root), number=10000)) # 0.2520280839999032 38 | """ 39 | -------------------------------------------------------------------------------- /N_tree/problems/L_the_diameter_of_a_binary_tree.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.left = None 5 | self.right = None 6 | 7 | 8 | def height(node): 9 | 10 | if node is None: 11 | return 0 12 | 13 | return 1 + max(height(node.left), height(node.right)) 14 | 15 | 16 | def method1(root): 17 | 18 | if root is None: 19 | return 0 20 | 21 | lheight = height(root.left) 22 | rheight = height(root.right) 23 | 24 | ldiameter = method1(root.left) 25 | rdiameter = method1(root.right) 26 | 27 | return max(lheight + rheight + 1, max(ldiameter, rdiameter)) 28 | 29 | 30 | if __name__ == "__main__": 31 | """ 32 | from timeit import timeit 33 | 34 | root = Node(1) 35 | root.left = Node(2) 36 | root.right = Node(3) 37 | root.left.left = Node(4) 38 | root.left.right = Node(5) 39 | 40 | print(timeit(lambda: method1(root), number=10000)) # 0.037249127999530174 41 | """ 42 | -------------------------------------------------------------------------------- /K_stack/problems/G_largest_rectangular_area_in_a_histogram.py: -------------------------------------------------------------------------------- 1 | def method1(histogram): 2 | stack = list() 3 | max_area = 0 4 | index = 0 5 | 6 | while index < len(histogram): 7 | if (not stack) or (histogram[stack[-1]] <= histogram[index]): 8 | stack.append(index) 9 | index += 1 10 | 11 | else: 12 | top_of_stack = stack.pop() 13 | area = histogram[top_of_stack] * ( 14 | (index - stack[-1] - 1) if stack else index 15 | ) 16 | max_area = max(max_area, area) 17 | 18 | while stack: 19 | top_of_stack = stack.pop() 20 | area = histogram[top_of_stack] * ((index - stack[-1] - 1) if stack else index) 21 | max_area = max(max_area, area) 22 | 23 | return max_area 24 | 25 | 26 | if __name__ == "__main__": 27 | """ 28 | from timeit import timeit 29 | 30 | hist = [1, 2, 5, 4, 5, 1, 6] 31 | print(timeit(lambda: method1(hist), number=10000)) # 0.027237262998824008 32 | """ 33 | -------------------------------------------------------------------------------- /O_binary_search_tree/A_implementation.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, key): 3 | self.left = None 4 | self.right = None 5 | self.val = key 6 | 7 | 8 | def insert(root, key): 9 | if root is None: 10 | return Node(key) 11 | else: 12 | if root.val == key: 13 | return root 14 | elif root.val < key: 15 | root.right = insert(root.right, key) 16 | else: 17 | root.left = insert(root.left, key) 18 | return root 19 | 20 | 21 | def inorder(root): 22 | if root: 23 | inorder(root.left) 24 | print(root.val) 25 | inorder(root.right) 26 | 27 | 28 | if __name__ == "__main__": 29 | """ 30 | from timeit import timeit 31 | 32 | r = Node(50) 33 | r = insert(r, 30) 34 | r = insert(r, 20) 35 | r = insert(r, 40) 36 | r = insert(r, 70) 37 | r = insert(r, 60) 38 | r = insert(r, 80) 39 | 40 | print(timeit(lambda: inorder(r), number=10000)) # 0.4426064440012851 41 | """ 42 | 43 | -------------------------------------------------------------------------------- /G_matrix/E_rotating_a_matrix.py: -------------------------------------------------------------------------------- 1 | def method1(): 2 | N = 4 3 | 4 | # mat = [[0 for x in range(N)] for y in range(N)] 5 | mat = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]] 6 | 7 | def rotateMatrix(mat): 8 | for x in range(0, int(N / 2)): 9 | for y in range(x, N - x - 1): 10 | temp = mat[x][y] 11 | mat[x][y] = mat[y][N - 1 - x] 12 | mat[y][N - 1 - x] = mat[N - 1 - x][N - 1 - y] 13 | mat[N - 1 - x][N - 1 - y] = mat[N - 1 - y][x] 14 | mat[N - 1 - y][x] = temp 15 | 16 | def displayMatrix(mat): 17 | for i in range(0, N): 18 | for j in range(0, N): 19 | print(mat[i][j], end=" ") 20 | print("") 21 | return rotateMatrix(mat) 22 | 23 | return (rotateMatrix(mat), displayMatrix(mat)) 24 | 25 | 26 | if __name__ == "__main__": 27 | """ 28 | from timeit import timeit 29 | print(timeit(lambda: method1(), number=10000)) # 0.2696803380001711 30 | """ 31 | -------------------------------------------------------------------------------- /J_linked_list/problems/F_recursive_traversal_in_a_singly_linked_list.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.next = None 5 | 6 | 7 | def newNode(data): 8 | new_node = Node(data) 9 | new_node.data = data 10 | new_node.next = None 11 | return new_node 12 | 13 | 14 | def insertEnd(head, data): 15 | 16 | if head == None: 17 | return newNode(data) 18 | 19 | else: 20 | head.next = insertEnd(head.next, data) 21 | return head 22 | 23 | 24 | def traverse(head): 25 | if head == None: 26 | return 27 | 28 | print(head.data, end=" ") 29 | traverse(head.next) 30 | 31 | 32 | if __name__ == "__main__": 33 | """ 34 | from timeit import timeit 35 | head = None 36 | head = insertEnd(head, 6) 37 | head = insertEnd(head, 8) 38 | head = insertEnd(head, 10) 39 | head = insertEnd(head, 12) 40 | head = insertEnd(head, 14) 41 | print(timeit(lambda: traverse(head), number=10000)) # 0.04721847000109847 42 | """ 43 | -------------------------------------------------------------------------------- /I_string/D_given_a_string_find_the_lexicographic_rank.py: -------------------------------------------------------------------------------- 1 | def method1(string: str) -> int: 2 | def fact(n: int) -> int: 3 | return 1 if n == 1 or n == 0 else n * fact(n - 1) 4 | 5 | def find_smaller_in_right(st, low, high): 6 | count_right = 0 7 | i = low + 1 8 | while i <= high: 9 | if st[i] < st[low]: 10 | count_right = count_right + 1 11 | i += 1 12 | return count_right 13 | 14 | def find_rank(st): 15 | mul = fact(len(st)) 16 | rank = 1 17 | i = 0 18 | while i < len(st): 19 | mul = mul / (len(st) - i) 20 | count_right = find_smaller_in_right(st, i, len(st) - 1) 21 | rank += count_right * mul 22 | i += 1 23 | return rank 24 | 25 | st = "thisisastring" 26 | return find_rank(st) 27 | 28 | 29 | if __name__ == "__main__": 30 | """ 31 | from timeit import timeit 32 | print(timeit(lambda: method1("thisisastring"), number=10000)) # 0.10805942400020285 33 | """ 34 | -------------------------------------------------------------------------------- /I_string/H_rabin_karp_algorithm.py: -------------------------------------------------------------------------------- 1 | def method1(pat: str, txt: str, g: int) -> int: 2 | d = 256 3 | m = len(pat) 4 | n = len(txt) 5 | i = 0 6 | j = 0 7 | p = 0 # hash value for pattern 8 | t = 0 # hash value for txt 9 | h = 1 10 | 11 | for i in range(m - 1): 12 | h = (h * d) % g 13 | for i in range(n - m + 1): 14 | if p == t: 15 | for j in range(m): 16 | if txt[i + j] != pat[j]: 17 | break 18 | else: 19 | j += 1 20 | if j == m: 21 | return "Pattern Found at index: " + str(i) 22 | 23 | if i < n - m: 24 | t = (d * (t - ord(txt[i]) * h) + ord(txt[i + m])) % g 25 | if t < 0: 26 | t += g 27 | 28 | 29 | if __name__ == "__main__": 30 | """ 31 | from timeit import timeit 32 | txt = "this is a string" 33 | pat = "this" 34 | g = 101 35 | print(timeit(lambda: method1(txt, pat, g), number=10000)) # 0.009983864998503122 36 | """ 37 | -------------------------------------------------------------------------------- /K_stack/problems/D_stock_span_problem_with_variations.py: -------------------------------------------------------------------------------- 1 | def method1(price, n, S): 2 | """ 3 | An algorithm that collects daily price quotes for some stock and returns the span of that stock's price for the current day. 4 | The span of the stock's price today is defined as the maximum number of consecutive days (starting from today and going backward) for which the stock price was less than or equal to today's price. 5 | For example, if the price of a stock over the next 7 days were [100,80,60,70,60,75,85], then the stock spans would be [1,1,1,2,1,4,6]. 6 | """ 7 | S[0] = 1 8 | for i in range(1, n, 1): 9 | S[i] = 1 10 | j = i - 1 11 | while (j >= 0) and (price[i] >= price[j]): 12 | S[i] += 1 13 | j -= 1 14 | 15 | 16 | if __name__ == "__main__": 17 | """ 18 | from timeit import timeit 19 | 20 | price = [10, 4, 5, 90, 120, 80] 21 | n = len(price) 22 | S = [None] * n 23 | print(timeit(lambda: method1(price, n, S), number=10000)) # 0.014990185001806822 24 | """ 25 | -------------------------------------------------------------------------------- /I_string/A_given_a_string_check_if_they_are_an_anagram_of_each_other.py: -------------------------------------------------------------------------------- 1 | def method1(s1: str, s2: str) -> bool: 2 | if len(s1) != len(s2): 3 | return False 4 | 5 | str1 = sorted(s1) 6 | str2 = sorted(s2) 7 | 8 | for i in range(len(s1)): 9 | if str1[i] != str2[i]: 10 | return False 11 | return True 12 | 13 | 14 | def method2(s1: str, s2: str) -> bool: 15 | count1 = [0] * 256 16 | count2 = [0] * 256 17 | for i in s1: 18 | count1[ord(i)] += 1 19 | for i in s2: 20 | count2[ord(i)] += 1 21 | 22 | if len(s1) != len(s2): 23 | return False 24 | for i in range(256): 25 | if count1[i] != count2[i]: 26 | return False 27 | return True 28 | 29 | 30 | if __name__ == "__main__": 31 | """ 32 | from timeit import timeit 33 | print(timeit(lambda: method1("thisisastring", "stringthisisa"), number=10000)) # 0.015203513999949791 34 | print(timeit(lambda: method2("thisisastring", "stringthisisa"), number=10000)) # 0.12443715199970029 35 | """ 36 | -------------------------------------------------------------------------------- /J_linked_list/problems/J_lru_cache_design.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | 3 | 4 | class LRUCache: 5 | def __init__(self, capacity: int): 6 | self.cache = OrderedDict() 7 | self.capacity = capacity 8 | 9 | def get(self, key: int) -> int: 10 | if key not in self.cache: 11 | return -1 12 | else: 13 | self.cache.move_to_end(key) 14 | return self.cache[key] 15 | 16 | def put(self, key: int, value: int) -> None: 17 | self.cache[key] = value 18 | self.cache.move_to_end(key) 19 | if len(self.cache) > self.capacity: 20 | self.cache.popitem(last=False) 21 | 22 | 23 | if __name__ == "__main__": 24 | from timeit import timeit 25 | 26 | cache = LRUCache(2) 27 | cache.put(1, 1) 28 | cache.put(2, 2) 29 | cache.get(1) 30 | cache.put(3, 3) 31 | cache.get(2) 32 | cache.put(4, 4) 33 | cache.get(1) 34 | cache.get(3) 35 | cache.get(4) 36 | print(timeit(lambda: cache.cache, number=10000)) # 0.0005562089991144603 37 | -------------------------------------------------------------------------------- /P_heap/B_priority_queue.py: -------------------------------------------------------------------------------- 1 | class PriorityQueue(object): 2 | def __init__(self): 3 | self.queue = [] 4 | 5 | def __str__(self): 6 | return " ".join([str(i) for i in self.queue]) 7 | 8 | def isEmpty(self): 9 | return len(self.queue) == 0 10 | 11 | def insert(self, data): 12 | self.queue.append(data) 13 | 14 | def delete(self): 15 | try: 16 | max = 0 17 | for i in range(len(self.queue)): 18 | if self.queue[i] > self.queue[max]: 19 | max = i 20 | item = self.queue[max] 21 | del self.queue[max] 22 | return item 23 | except IndexError: 24 | print() 25 | exit() 26 | 27 | 28 | if __name__ == "__main__": 29 | """ 30 | from timeit import timeit 31 | 32 | myQueue = PriorityQueue() 33 | myQueue.insert(12) 34 | myQueue.insert(1) 35 | myQueue.insert(14) 36 | myQueue.insert(7) 37 | print(timeit(lambda: myQueue, number=10000)) # 0.0003760149993468076 38 | """ 39 | -------------------------------------------------------------------------------- /T_dynamic_programming/problems/E_minimum_jumps_to_reach_at_the_end.py: -------------------------------------------------------------------------------- 1 | def method1(arr, l, h): 2 | 3 | # Base case: when source and 4 | # destination are same 5 | if h == l: 6 | return 0 7 | 8 | # when nothing is reachable 9 | # from the given source 10 | if arr[l] == 0: 11 | return float("inf") 12 | 13 | # Traverse through all the points 14 | # reachable from arr[l]. Recursively 15 | # get the minimum number of jumps 16 | # needed to reach arr[h] from 17 | # these reachable points. 18 | min = float("inf") 19 | for i in range(l + 1, h + 1): 20 | if i < l + arr[l] + 1: 21 | jumps = method1(arr, i, h) 22 | if jumps != float("inf") and jumps + 1 < min: 23 | min = jumps + 1 24 | 25 | return min 26 | 27 | 28 | if __name__ == "__main__": 29 | """ 30 | from timeit import timeit 31 | 32 | arr = [1, 3, 6, 3, 2, 3, 6, 8, 9, 5] 33 | n = len(arr) 34 | print(timeit(lambda: method1(arr, 0, n - 1), number=10000)) # 0.7700862489946303 35 | """ -------------------------------------------------------------------------------- /T_dynamic_programming/problems/long_increasing_subsequence_problem/B_efficient_approach.py: -------------------------------------------------------------------------------- 1 | # method1 returns length of the longest increasing subsequence 2 | # in arr of size n 3 | def method1(arr): 4 | n = len(arr) 5 | 6 | # Declare the list (array) for LIS and initialize LIS 7 | # values for all indexes 8 | method1 = [1] * n 9 | 10 | # Compute optimized LIS values in bottom up manner 11 | for i in range(1, n): 12 | for j in range(0, i): 13 | if arr[i] > arr[j] and method1[i] < method1[j] + 1: 14 | method1[i] = method1[j] + 1 15 | 16 | # Initialize maximum to 0 to get the maximum of all 17 | # LIS 18 | maximum = 0 19 | 20 | # Pick maximum of all LIS values 21 | for i in range(n): 22 | maximum = max(maximum, method1[i]) 23 | 24 | return maximum 25 | 26 | 27 | 28 | if __name__ == "__main__": 29 | """ 30 | from timeit import timeit 31 | 32 | arr = [10, 22, 9, 33, 21, 50, 41, 60] 33 | print(timeit(lambda: method1(arr), number=10000)) # 0.0482044410018716 34 | """ -------------------------------------------------------------------------------- /K_stack/infix_prefix_and_postfix/D_evaluation_of_prefix.py: -------------------------------------------------------------------------------- 1 | def method1(): 2 | def is_operand(c): 3 | return c.isdigit() 4 | 5 | def evaluate(expression): 6 | 7 | stack = [] 8 | 9 | for c in expression[::-1]: 10 | 11 | if is_operand(c): 12 | stack.append(int(c)) 13 | 14 | else: 15 | o1 = stack.pop() 16 | o2 = stack.pop() 17 | 18 | if c == "+": 19 | stack.append(o1 + o2) 20 | 21 | elif c == "-": 22 | stack.append(o1 - o2) 23 | 24 | elif c == "*": 25 | stack.append(o1 * o2) 26 | 27 | elif c == "/": 28 | stack.append(o1 / o2) 29 | 30 | return stack.pop() 31 | 32 | test_expression = "+9*26" 33 | return evaluate(test_expression) 34 | 35 | 36 | if __name__ == "__main__": 37 | """ 38 | from timeit import timeit 39 | 40 | print(timeit(lambda: method1(), number=10000)) # 0.015567280002869666 41 | """ 42 | -------------------------------------------------------------------------------- /C_recursion/J_tower_of_hanoi.py: -------------------------------------------------------------------------------- 1 | def method1(n: int, source: str, destination: str, auxiliary: str) -> str: 2 | """ 3 | >>> method1(3, 'a', 'b', 'c') 4 | Move disk 1 from source a to destination b 5 | Move disk 2 from source a to destination c 6 | Move disk 1 from source b to destination c 7 | Move disk 3 from source a to destination b 8 | Move disk 1 from source c to destination a 9 | Move disk 2 from source c to destination b 10 | Move disk 1 from source a to destination b 11 | """ 12 | if n == 1: 13 | print("Move disk 1 from source", source, "to destination", destination) 14 | return 15 | method1(n - 1, source, auxiliary, destination) 16 | print("Move disk", n, "from source", source, "to destination", destination) 17 | method1(n - 1, auxiliary, destination, source) 18 | 19 | 20 | if __name__ == "__main__": 21 | """ 22 | from timeit import timeit 23 | print(timeit(lambda: method1(3, 'a', 'b', 'c'), number=10000)) # 1.687103215001116 24 | """ 25 | import doctest 26 | 27 | doctest.testmod() 28 | -------------------------------------------------------------------------------- /D_arrays/operation_on_arrays/A_searching.py: -------------------------------------------------------------------------------- 1 | def method1(l: list, low: int, high: int, x: int) -> int: 2 | if high >= low: 3 | mid = (high + low) // 2 4 | if l[mid] == x: 5 | return mid 6 | elif l[mid] > x: 7 | return method1(l, low, mid - 1, x) 8 | else: 9 | return method1(l, mid + 1, high, x) 10 | else: 11 | return -1 12 | return method1(l, 0, len(l) - 1, x) 13 | 14 | 15 | def method2(n: int, l: list) -> bool: 16 | return True if l.index(n) <= len(l) else False 17 | 18 | 19 | def method3(n: int, l: list) -> bool: 20 | return True if n in l else False 21 | 22 | 23 | if __name__ == "__main__": 24 | """ 25 | n = 9999 26 | l = [i for i in range(10000)] # [0, 1, 3, ...., 9999] 27 | from timeit import timeit 28 | print(timeit(lambda: method1(l, 0, len(l)-1, n), number=10000)) # 0.03099031199963065 29 | print(timeit(lambda: method2(n, l), number=10000)) # 0.9109301280004729 30 | print(timeit(lambda: method3(n, l), number=10000)) # 0.8249549619995378 31 | """ 32 | -------------------------------------------------------------------------------- /N_tree/problems/G_check_for_balanced_binary_tree.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.left = None 5 | self.right = None 6 | 7 | 8 | def height(root): 9 | 10 | if root is None: 11 | return 0 12 | return max(height(root.left), height(root.right)) + 1 13 | 14 | 15 | def isBalanced(root): 16 | 17 | if root is None: 18 | return True 19 | 20 | lh = height(root.left) 21 | rh = height(root.right) 22 | 23 | if ( 24 | (abs(lh - rh) <= 1) 25 | and isBalanced(root.left) is True 26 | and isBalanced(root.right) is True 27 | ): 28 | return True 29 | 30 | return False 31 | 32 | 33 | if __name__ == "__main__": 34 | """ 35 | from timeit import timeit 36 | 37 | root = Node(1) 38 | root.left = Node(2) 39 | root.right = Node(3) 40 | root.left.left = Node(4) 41 | root.left.right = Node(5) 42 | root.left.left.left = Node(8) 43 | print(timeit(lambda: isBalanced(root), number=10000)) # 0.01500733800639864 44 | """ 45 | -------------------------------------------------------------------------------- /C_recursion/Z_recursion.md: -------------------------------------------------------------------------------- 1 | # List of Contents 2 | 3 | - [Factorial](https://github.com/thisisshub/DSA/blob/main/C_recursion/A_factorial.py) 4 | - [Fibonnaci](https://github.com/thisisshub/DSA/blob/main/C_recursion/B_fibonnaci.py) 5 | - [Print N To 1](https://github.com/thisisshub/DSA/blob/main/C_recursion/C_print_n_to_1.py) 6 | - [Print 1 To N](https://github.com/thisisshub/DSA/blob/main/C_recursion/D_print_1_to_n.py) 7 | - [Tail Recursion](https://github.com/thisisshub/DSA/blob/main/C_recursion/E_tail_recursion.py) 8 | - [Checking Palindrome](https://github.com/thisisshub/DSA/blob/main/C_recursion/F_checking_palindrome.py) 9 | - [Sum Of Digits](https://github.com/thisisshub/DSA/blob/main/C_recursion/G_sum_of_digits.py) 10 | - [Rod Cutting](https://github.com/thisisshub/DSA/blob/main/C_recursion/H_rod_cutting.py) 11 | - [Subset Of Set](https://github.com/thisisshub/DSA/blob/main/C_recursion/I_subset_of_set.py) 12 | - [Tower Of Hanoi](https://github.com/thisisshub/DSA/blob/main/C_recursion/J_tower_of_hanoi.py) 13 | - [Josephus](https://github.com/thisisshub/DSA/blob/main/C_recursion/K_josephus.py) -------------------------------------------------------------------------------- /P_heap/binary_heap/A_insertion.py: -------------------------------------------------------------------------------- 1 | from heapq import heappush, heappop, heapify 2 | 3 | 4 | class MinHeap: 5 | def __init__(self): 6 | self.heap = [] 7 | 8 | def parent(self, i): 9 | return (i - 1) / 2 10 | 11 | def insertKey(self, k): 12 | heappush(self.heap, k) 13 | 14 | def decreaseKey(self, i, new_val): 15 | self.heap[i] = new_val 16 | while i != 0 and self.heap[self.parent(i)] > self.heap[i]: 17 | 18 | self.heap[i], self.heap[self.parent(i)] = ( 19 | self.heap[self.parent(i)], 20 | self.heap[i], 21 | ) 22 | 23 | def extractMin(self): 24 | return heappop(self.heap) 25 | 26 | def deleteKey(self, i): 27 | self.decreaseKey(i, float("-inf")) 28 | self.extractMin() 29 | 30 | def getMin(self): 31 | return self.heap[0] 32 | 33 | 34 | if __name__ == "__main__": 35 | """ 36 | from timeit import timeit 37 | 38 | heapObj = MinHeap() 39 | print(timeit(lambda: heapObj.insertKey(1), number=10000)) # 0.0013612549955723807 40 | """ 41 | -------------------------------------------------------------------------------- /D_arrays/problems/majority_element.py: -------------------------------------------------------------------------------- 1 | def method1(): 2 | def findCandidate(A): 3 | maj_index = 0 4 | count = 1 5 | for i in range(len(A)): 6 | if A[maj_index] == A[i]: 7 | count += 1 8 | else: 9 | count -= 1 10 | if count == 0: 11 | maj_index = i 12 | count = 1 13 | return A[maj_index] 14 | 15 | def isMajority(A, cand): 16 | count = 0 17 | for i in range(len(A)): 18 | if A[i] == cand: 19 | count += 1 20 | if count > len(A) / 2: 21 | return True 22 | else: 23 | return False 24 | 25 | def printMajority(A): 26 | cand = findCandidate(A) 27 | if isMajority(A, cand) == True: 28 | print(cand) 29 | else: 30 | print("No Majority Element") 31 | 32 | A = [1, 3, 3, 1, 2] 33 | return printMajority(A) 34 | 35 | 36 | if __name__ == "__main__": 37 | """ 38 | from timeit import timeit 39 | print(timeit(lambda: method1(), number=10000)) # 0.12490123600218794 40 | """ 41 | -------------------------------------------------------------------------------- /N_tree/problems/Q_iterative_inorder_traversal.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.left = None 5 | self.right = None 6 | 7 | 8 | def inOrder(root): 9 | 10 | current = root 11 | stack = [] 12 | 13 | while True: 14 | 15 | if current is not None: 16 | 17 | stack.append(current) 18 | 19 | current = current.left 20 | 21 | elif stack: 22 | current = stack.pop() 23 | print(current.data, end=" ") 24 | 25 | current = current.right 26 | 27 | else: 28 | break 29 | 30 | print() 31 | 32 | 33 | root = Node(1) 34 | root.left = Node(2) 35 | root.right = Node(3) 36 | root.left.left = Node(4) 37 | root.left.right = Node(5) 38 | 39 | inOrder(root) 40 | 41 | 42 | if __name__ == "__main__": 43 | """ 44 | from timeit import timeit 45 | 46 | root = Node(1) 47 | root.left = Node(2) 48 | root.right = Node(3) 49 | root.left.left = Node(4) 50 | root.left.right = Node(5) 51 | print(timeit(lambda: inOrder(root), number=10000)) # 0.15916127999980745 52 | """ -------------------------------------------------------------------------------- /T_dynamic_programming/problems/A_longest_common_subsequence.py: -------------------------------------------------------------------------------- 1 | def method1(X, Y): 2 | 3 | m = len(X) 4 | n = len(Y) 5 | 6 | L = [[None] * (n + 1) for i in range(m + 1)] 7 | 8 | for i in range(m + 1): 9 | for j in range(n + 1): 10 | if i == 0 or j == 0: 11 | L[i][j] = 0 12 | elif X[i - 1] == Y[j - 1]: 13 | L[i][j] = L[i - 1][j - 1] + 1 14 | else: 15 | L[i][j] = max(L[i - 1][j], L[i][j - 1]) 16 | 17 | return L[m][n] 18 | 19 | 20 | def method2(X, Y, m, n): 21 | 22 | if m == 0 or n == 0: 23 | return 0 24 | elif X[m - 1] == Y[n - 1]: 25 | return 1 + method2(X, Y, m - 1, n - 1) 26 | else: 27 | return max(method2(X, Y, m, n - 1), method2(X, Y, m - 1, n)) 28 | 29 | 30 | if __name__ == "__main__": 31 | """ 32 | from timeit import timeit 33 | 34 | X = "AGGTAB" 35 | Y = "GXTXAYB" 36 | print(timeit(lambda: method1(X, Y), number=10000)) # 0.14817858800233807 37 | print( 38 | timeit(lambda: method2(X, Y, len(X), len(Y)), number=10000) 39 | ) # 0.5299446069984697 40 | """ -------------------------------------------------------------------------------- /F_sorting/I_radixsort.py: -------------------------------------------------------------------------------- 1 | def method1(ll: list) -> list: 2 | def countingSort(arr, exp1): 3 | n = len(arr) 4 | output = [0] * (n) 5 | count = [0] * (10) 6 | 7 | for i in range(0, n): 8 | index = arr[i] / exp1 9 | count[int((index) % 10)] += 1 10 | 11 | for i in range(1, 10): 12 | count[i] += count[i - 1] 13 | 14 | i = n - 1 15 | while i >= 0: 16 | index = arr[i] / exp1 17 | output[count[int((index) % 10)] - 1] = arr[i] 18 | count[int((index) % 10)] -= 1 19 | i -= 1 20 | 21 | i = 0 22 | for i in range(0, len(arr)): 23 | arr[i] = output[i] 24 | 25 | def radixSort(arr): 26 | max1 = max(arr) 27 | exp = 1 28 | while max1 / exp > 0: 29 | countingSort(arr, exp) 30 | exp *= 10 31 | 32 | return radixSort(ll) 33 | 34 | 35 | if __name__ == "__main__": 36 | """ 37 | l = ['1', '3', '4', '7', '5', '9'] 38 | from timeit import timeit 39 | print(timeit(lambda: method1(l), number=10000)) # 0.002465166999172652 40 | """ 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Shubhashish Dixit 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /O_binary_search_tree/problems/G_vertical_sum_in_a_binary_tree.py: -------------------------------------------------------------------------------- 1 | class newNode: 2 | def __init__(self, data): 3 | 4 | self.left = None 5 | self.right = None 6 | self.data = data 7 | 8 | 9 | def verticalSumUtil(root, hd, Map): 10 | 11 | if root == None: 12 | return 13 | 14 | verticalSumUtil(root.left, hd - 1, Map) 15 | 16 | if hd in Map.keys(): 17 | Map[hd] = Map[hd] + root.data 18 | else: 19 | Map[hd] = root.data 20 | 21 | verticalSumUtil(root.right, hd + 1, Map) 22 | 23 | 24 | def verticalSum(root): 25 | 26 | Map = {} 27 | 28 | verticalSumUtil(root, 0, Map) 29 | 30 | for i, j in Map.items(): 31 | print(i, "=", j, end=", ") 32 | 33 | 34 | if __name__ == "__main__": 35 | """ 36 | from timeit import timeit 37 | 38 | root = newNode(1) 39 | root.left = newNode(2) 40 | root.right = newNode(3) 41 | root.left.left = newNode(4) 42 | root.left.right = newNode(5) 43 | root.right.left = newNode(6) 44 | root.right.right = newNode(7) 45 | 46 | print(timeit(lambda: verticalSum(root), number=10000)) # 0.1557436530056293 47 | """ 48 | -------------------------------------------------------------------------------- /J_linked_list/problems/L_palindrome_linked_list.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.ptr = None 5 | 6 | 7 | def ispalindrome(head): 8 | slow = head 9 | stack = [] 10 | ispalin = True 11 | 12 | while slow != None: 13 | stack.append(slow.data) 14 | slow = slow.ptr 15 | 16 | while head != None: 17 | i = stack.pop() 18 | if head.data == i: 19 | ispalin = True 20 | else: 21 | ispalin = False 22 | break 23 | 24 | head = head.ptr 25 | 26 | return ispalin 27 | 28 | 29 | if __name__ == "__main__": 30 | """ 31 | from timeit import timeit 32 | 33 | one = Node(1) 34 | two = Node(2) 35 | three = Node(3) 36 | four = Node(4) 37 | five = Node(3) 38 | six = Node(2) 39 | seven = Node(1) 40 | 41 | one.ptr = two 42 | two.ptr = three 43 | three.ptr = four 44 | four.ptr = five 45 | five.ptr = six 46 | six.ptr = seven 47 | seven.ptr = None 48 | 49 | result = ispalindrome(one) 50 | print(timeit(lambda: result, number=10000)) # 0.00036691099921881687 51 | """ 52 | -------------------------------------------------------------------------------- /N_tree/problems/F_children_sum_property.py: -------------------------------------------------------------------------------- 1 | class newNode: 2 | def __init__(self, data): 3 | self.data = data 4 | self.left = None 5 | self.right = None 6 | 7 | 8 | def method1(node): 9 | 10 | left_data = 0 11 | right_data = 0 12 | 13 | if node == None or (node.left == None and node.right == None): 14 | return 1 15 | else: 16 | 17 | if node.left != None: 18 | left_data = node.left.data 19 | 20 | if node.right != None: 21 | right_data = node.right.data 22 | 23 | if ( 24 | (node.data == left_data + right_data) 25 | and method1(node.left) 26 | and method1(node.right) 27 | ): 28 | return 1 29 | else: 30 | return 0 31 | 32 | 33 | if __name__ == "__main__": 34 | """ 35 | from timeit import timeit 36 | 37 | root = newNode(10) 38 | root.left = newNode(8) 39 | root.right = newNode(2) 40 | root.left.left = newNode(3) 41 | root.left.right = newNode(5) 42 | root.right.right = newNode(2) 43 | print(timeit(lambda: method1(root), number=10000)) # 0.014636427004006691 44 | """ 45 | -------------------------------------------------------------------------------- /N_tree/problems/O_count_nodes_in_a_complete_binary_tree.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, key): 3 | self.data = key 4 | self.left = None 5 | self.right = None 6 | 7 | 8 | def getfullCount(root): 9 | 10 | if root is None: 11 | return 0 12 | 13 | queue = [] 14 | 15 | queue.append(root) 16 | 17 | count = 0 18 | while len(queue) > 0: 19 | node = queue.pop(0) 20 | 21 | if node.left is not None and node.right is not None: 22 | count = count + 1 23 | 24 | if node.left is not None: 25 | queue.append(node.left) 26 | 27 | if node.right is not None: 28 | queue.append(node.right) 29 | 30 | return count 31 | 32 | 33 | if __name__ == "__main__": 34 | """ 35 | from timeit import timeit 36 | 37 | root = Node(2) 38 | root.left = Node(7) 39 | root.right = Node(5) 40 | root.left.right = Node(6) 41 | root.left.right.left = Node(1) 42 | root.left.right.right = Node(11) 43 | root.right.right = Node(9) 44 | root.right.right.left = Node(4) 45 | 46 | print(timeit(lambda: (getfullCount(root)), number=10000)) 47 | """ 48 | -------------------------------------------------------------------------------- /G_matrix/H_spiral_traversal.py: -------------------------------------------------------------------------------- 1 | def method1(): 2 | def spiralPrint(m, n, a): 3 | k = 0 4 | l = 0 5 | """ k - starting row index 6 | m - ending row index 7 | l - starting column index 8 | n - ending column index 9 | i - iterator """ 10 | while k < m and l < n: 11 | for i in range(l, n): 12 | print(a[k][i], end=" ") 13 | 14 | k += 1 15 | for i in range(k, m): 16 | print(a[i][n - 1], end=" ") 17 | 18 | n -= 1 19 | if k < m: 20 | 21 | for i in range(n - 1, (l - 1), -1): 22 | print(a[m - 1][i], end=" ") 23 | 24 | m -= 1 25 | if l < n: 26 | for i in range(m - 1, k - 1, -1): 27 | print(a[i][l], end=" ") 28 | 29 | l += 1 30 | 31 | a = [[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18]] 32 | 33 | return spiralPrint(3, 6, a) 34 | 35 | 36 | if __name__ == "__main__": 37 | """ 38 | from timeit import timeit 39 | print(timeit(lambda: method1(), number=10000)) # 0.17249211399985143 40 | """ 41 | -------------------------------------------------------------------------------- /K_stack/problems/E_previous_greater_element_.py: -------------------------------------------------------------------------------- 1 | def method1(arr, n): 2 | import math as mt 3 | 4 | s = list() 5 | s.append(arr[0]) 6 | 7 | print("-1, ", end="") 8 | 9 | for i in range(1, n): 10 | 11 | while len(s) > 0 and s[-1] < arr[i]: 12 | s.pop() 13 | 14 | if len(s) == 0: 15 | print("-1, ", end="") 16 | else: 17 | print(s[-1], ", ", end="") 18 | 19 | s.append(arr[i]) 20 | 21 | 22 | def method2(arr, n): 23 | 24 | print("-1", end=", ") 25 | 26 | for i in range(1, n): 27 | flag = 0 28 | 29 | for j in range(i - 1, -1, -1): 30 | if arr[i] < arr[j]: 31 | print(arr[j], end=", ") 32 | flag = 1 33 | break 34 | 35 | if j == 0 and flag == 0: 36 | print("-1", end=", ") 37 | 38 | 39 | if __name__ == "__main__": 40 | """ 41 | from timeit import timeit 42 | 43 | arr = [10, 4, 2, 20, 40, 12, 30] 44 | n = len(arr) 45 | print(timeit(lambda: method1(arr, n), number=10000)) # 0.14209358299922314 46 | print(timeit(lambda: method2(arr, n), number=10000)) # 0.38604877599937026 47 | """ 48 | -------------------------------------------------------------------------------- /P_heap/Z_heap.md: -------------------------------------------------------------------------------- 1 | # List of Contents 2 | 3 | - [Heap Sort](https://github.com/thisisshub/DSA/blob/main/P_heap/A_heap_sort.py) 4 | - [Priority Queue](https://github.com/thisisshub/DSA/blob/main/P_heap/B_priority_queue.py) 5 | 6 | # Binary Heap 7 | - [Insertion](https://github.com/thisisshub/DSA/blob/main/P_heap/binary_heap/A_insertion.py) 8 | - [Heapify And Extract](https://github.com/thisisshub/DSA/blob/main/P_heap/binary_heap/B_heapify_and_extract.py) 9 | - [Decrease Key Delete And Build Heap](https://github.com/thisisshub/DSA/blob/main/P_heap/binary_heap/C_decrease_key_delete_and_build_heap.py) 10 | 11 | # Problems 12 | - [Sort Ksorted Array](https://github.com/thisisshub/DSA/blob/main/P_heap/problems/A_sort_ksorted_array.py) 13 | - [Buy Maximum Items With Given Sum](https://github.com/thisisshub/DSA/blob/main/P_heap/problems/B_buy_maximum_items_with_given_sum.py) 14 | - [K Largest Elements](https://github.com/thisisshub/DSA/blob/main/P_heap/problems/C_k_largest_elements.py) 15 | - [Merge K Sorted Arrays](https://github.com/thisisshub/DSA/blob/main/P_heap/problems/D_merge_k_sorted_arrays.py) 16 | - [Median Of A Stream](https://github.com/thisisshub/DSA/blob/main/P_heap/problems/E_median_of_a_stream.py) -------------------------------------------------------------------------------- /O_binary_search_tree/D_floor_in_bst.py: -------------------------------------------------------------------------------- 1 | INT_MAX = 2147483647 2 | 3 | 4 | class newNode: 5 | def __init__(self, data): 6 | self.data = data 7 | self.left = None 8 | self.right = None 9 | 10 | 11 | def insert(root, key): 12 | 13 | if not root: 14 | return newNode(key) 15 | if key < root.data: 16 | root.left = insert(root.left, key) 17 | else: 18 | root.right = insert(root.right, key) 19 | return root 20 | 21 | 22 | def floor(root, key): 23 | 24 | if not root: 25 | return INT_MAX 26 | 27 | if root.data == key: 28 | return root.data 29 | 30 | if root.data > key: 31 | return floor(root.left, key) 32 | 33 | floorValue = floor(root.right, key) 34 | return floorValue if (floorValue <= key) else root.data 35 | 36 | 37 | if __name__ == "__main__": 38 | """ 39 | from timeit import timeit 40 | 41 | root = None 42 | root = insert(root, 7) 43 | insert(root, 10) 44 | insert(root, 5) 45 | insert(root, 3) 46 | insert(root, 6) 47 | insert(root, 8) 48 | insert(root, 12) 49 | print(timeit(lambda: floor(root, 9), number=10000)) # 0.01083161299902713 50 | """ -------------------------------------------------------------------------------- /J_linked_list/problems/A_middle_of_linked_list.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.next = None 5 | 6 | 7 | class LinkedList: 8 | def __init__(self): 9 | self.head = None 10 | 11 | def push(self, new_data): 12 | new_node = Node(new_data) 13 | new_node.next = self.head 14 | self.head = new_node 15 | 16 | def printList(self): 17 | node = self.head 18 | while node: 19 | print(str(node.data) + "->", end="") 20 | node = node.next 21 | print("NULL") 22 | 23 | def printMiddle(self): 24 | 25 | slow = self.head 26 | fast = self.head 27 | 28 | while fast and fast.next: 29 | slow = slow.next 30 | fast = fast.next.next 31 | 32 | print("The middle element is ", slow.data) 33 | 34 | 35 | llist = LinkedList() 36 | 37 | for i in range(5, 0, -1): 38 | llist.push(i) 39 | llist.printList() 40 | llist.printMiddle() 41 | 42 | if __name__ == "__main__": 43 | """ 44 | from timeit import timeit 45 | print(timeit(lambda: llist.printMiddle(), number=10000)) # 0.15231092200065177 46 | """ 47 | -------------------------------------------------------------------------------- /P_heap/problems/E_median_of_a_stream.py: -------------------------------------------------------------------------------- 1 | import heapq 2 | 3 | maxh = [] 4 | minh = [] 5 | vals = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 6 | for val in vals: 7 | 8 | if not maxh and not minh: 9 | heapq.heappush(maxh, -val) 10 | print(float(val)) 11 | elif maxh: 12 | 13 | if val >= -maxh[0]: 14 | heapq.heappush(minh, val) 15 | else: 16 | heapq.heappush(maxh, -val) 17 | 18 | if len(maxh) == len(minh): 19 | print(float(-maxh[0] + minh[0]) / 2) 20 | elif len(maxh) == len(minh) + 1: 21 | print(float(-maxh[0])) 22 | elif len(minh) == len(maxh) + 1: 23 | print(float(minh[0])) 24 | 25 | elif len(minh) == len(maxh) + 2: 26 | heapq.heappush(maxh, -heapq.heappop(minh)) 27 | print(float(-maxh[0] + minh[0]) / 2) 28 | elif len(maxh) == len(minh) + 2: 29 | heapq.heappush(minh, -heapq.heappop(maxh)) 30 | print(float(-maxh[0] + minh[0]) / 2) 31 | 32 | if __name__ == "__main__": 33 | """ 34 | from timeit import timeit 35 | 36 | print(timeit((lambda: float(-maxh[0] + minh[0]) / 2), number=10000)) # 0.0013756349981122185 37 | """ 38 | -------------------------------------------------------------------------------- /L_queue/problems/C_circular_tour.py: -------------------------------------------------------------------------------- 1 | def method1(): 2 | class PetrolPump: 3 | def __init__(self, petrol, distance): 4 | self.petrol = petrol 5 | self.distance = distance 6 | 7 | def printTour(arr): 8 | 9 | n = len(arr) 10 | 11 | start = 0 12 | end = 1 13 | 14 | curr_petrol = arr[start].petrol - arr[start].distance 15 | 16 | while end != start or curr_petrol < 0: 17 | 18 | while curr_petrol < 0 and start != end: 19 | 20 | curr_petrol -= arr[start].petrol - arr[start].distance 21 | start = (start + 1) % n 22 | 23 | if start == 0: 24 | return -1 25 | 26 | curr_petrol += arr[end].petrol - arr[end].distance 27 | 28 | end = (end + 1) % n 29 | 30 | return start 31 | 32 | arr = [PetrolPump(6, 4), PetrolPump(3, 6), PetrolPump(7, 3)] 33 | start = printTour(arr) 34 | 35 | return ("No solution" if start == -1 else "start =", start) 36 | 37 | 38 | if __name__ == "__main__": 39 | """ 40 | from timeit import timeit 41 | print(timeit(lambda: method1(), number=10000)) # 0.07590579400130082 42 | """ 43 | -------------------------------------------------------------------------------- /O_binary_search_tree/problems/I_top_view_of_binary_tree.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, key): 3 | self.data = key 4 | self.left = None 5 | self.right = None 6 | self.hd = 0 7 | 8 | 9 | def topview(root): 10 | 11 | if root == None: 12 | return 13 | q = [] 14 | m = dict() 15 | hd = 0 16 | root.hd = hd 17 | 18 | q.append(root) 19 | 20 | while len(q): 21 | root = q[0] 22 | hd = root.hd 23 | 24 | if hd not in m: 25 | m[hd] = root.data 26 | if root.left: 27 | root.left.hd = hd - 1 28 | q.append(root.left) 29 | 30 | if root.right: 31 | root.right.hd = hd + 1 32 | q.append(root.right) 33 | 34 | q.pop(0) 35 | for i in sorted(m): 36 | print(m[i], end="") 37 | 38 | 39 | if __name__ == "__main__": 40 | """ 41 | from timeit import timeit 42 | 43 | root = Node(1) 44 | root.left = Node(2) 45 | root.right = Node(3) 46 | root.left.right = Node(4) 47 | root.left.right.right = Node(5) 48 | root.left.right.right.right = Node(6) 49 | print(timeit(lambda: topview(root), number=10000)) # 0.043794581994006876 50 | """ 51 | -------------------------------------------------------------------------------- /J_linked_list/loop_problems/A_detecting_loops.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.next = None 5 | 6 | 7 | class LinkedList: 8 | def __init__(self): 9 | self.head = None 10 | 11 | def push(self, new_data): 12 | new_node = Node(new_data) 13 | new_node.next = self.head 14 | self.head = new_node 15 | 16 | def printList(self): 17 | temp = self.head 18 | while temp: 19 | print(temp.data, end=" ") 20 | temp = temp.next 21 | 22 | def detectLoop(self): 23 | s = set() 24 | temp = self.head 25 | while temp: 26 | if temp in s: 27 | return True 28 | s.add(temp) 29 | temp = temp.next 30 | return False 31 | 32 | 33 | llist = LinkedList() 34 | llist.push(1) 35 | llist.push(2) 36 | llist.push(3) 37 | llist.push(4) 38 | 39 | if __name__ == "__main__": 40 | """ 41 | from timeit import timeit 42 | llist.head.next.next.next.next = llist.head 43 | if llist.detectLoop(): 44 | print(timeit(lambda: llist.detectLoop(), number=10000)) # 0.005041514000140523 45 | else: 46 | print('No loop') 47 | """ 48 | -------------------------------------------------------------------------------- /K_stack/infix_prefix_and_postfix/B_evaluation_of_postfix.py: -------------------------------------------------------------------------------- 1 | class Evaluate: 2 | def __init__(self, capacity): 3 | self.top = -1 4 | self.capacity = capacity 5 | 6 | self.array = [] 7 | 8 | def isEmpty(self): 9 | return True if self.top == -1 else False 10 | 11 | def peek(self): 12 | return self.array[-1] 13 | 14 | def pop(self): 15 | if not self.isEmpty(): 16 | self.top -= 1 17 | return self.array.pop() 18 | else: 19 | return "$" 20 | 21 | def push(self, op): 22 | self.top += 1 23 | self.array.append(op) 24 | 25 | def evaluatePostfix(self, exp): 26 | 27 | for i in exp: 28 | 29 | if i.isdigit(): 30 | self.push(i) 31 | 32 | else: 33 | val1 = self.pop() 34 | val2 = self.pop() 35 | self.push(str(eval(val2 + i + val1))) 36 | 37 | return int(self.pop()) 38 | 39 | 40 | if __name__ == "__main__": 41 | """ 42 | from timeit import timeit 43 | 44 | exp = "231*+9-" 45 | obj = Evaluate(len(exp)) 46 | print(timeit(lambda: obj.evaluatePostfix(exp), number=10000)) # 0.15434936900419416 47 | """ 48 | -------------------------------------------------------------------------------- /F_sorting/G_cyclesort.py: -------------------------------------------------------------------------------- 1 | def method1(ll: list) -> list: 2 | def cycleSort(ll): 3 | writes = 0 4 | 5 | for cycleStart in range(0, len(ll) - 1): 6 | item = ll[cycleStart] 7 | pos = cycleStart 8 | 9 | for i in range(cycleStart + 1, len(ll)): 10 | if ll[i] < item: 11 | pos += 1 12 | 13 | if pos == cycleStart: 14 | continue 15 | 16 | while item == ll[pos]: 17 | pos += 1 18 | ll[pos], item = item, ll[pos] 19 | writes += 1 20 | 21 | while pos != cycleStart: 22 | pos = cycleStart 23 | 24 | for i in range(cycleStart + 1, len(ll)): 25 | if ll[i] < item: 26 | pos += 1 27 | 28 | while item == ll[pos]: 29 | pos += 1 30 | ll[pos], item = item, ll[pos] 31 | writes += 1 32 | 33 | return writes 34 | 35 | return cycleSort(ll) 36 | 37 | 38 | if __name__ == "__main__": 39 | """ 40 | l = [1, 3, 4] 41 | from timeit import timeit 42 | print(timeit(lambda: method1(l), number=10000)) # 0.012405524001223966 43 | """ 44 | -------------------------------------------------------------------------------- /N_tree/problems/P_serialize_and_deserialize_a_binary_tree.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, val, left=None, right=None): 3 | self.val = val 4 | self.left = left 5 | self.right = right 6 | 7 | 8 | node = Node("root", Node("left", Node("left.left")), Node("right")) 9 | s = "" 10 | 11 | 12 | def serialize(node, s=""): 13 | if not node: 14 | s += "# " 15 | return s 16 | s += str(node.val) + " " 17 | s = serialize(node.left, s=s) 18 | s = serialize(node.right, s=s) 19 | return s 20 | 21 | 22 | i = 0 23 | 24 | 25 | def deserialize(s): 26 | global i 27 | if s[i] == "#": 28 | if i < len(s) - 2: 29 | i += 2 30 | return None 31 | else: 32 | space = s[i:].find(" ") 33 | sp = space + i 34 | node = Node(s[i:sp]) 35 | i = sp + 1 36 | node.left = deserialize(s) 37 | node.right = deserialize(s) 38 | return node 39 | 40 | 41 | if __name__ == "__main__": 42 | """ 43 | from timeit import timeit 44 | 45 | print(timeit(lambda: serialize(node), number=10000)) # 0.017630080999879283 46 | print(timeit(lambda: deserialize(serialize(node)), number=10000)) # 0.020570166999732464 47 | """ 48 | -------------------------------------------------------------------------------- /H_hashing/problems/I_longest_subarray_with_an_equal_number_of_0’s_and_1’s.py: -------------------------------------------------------------------------------- 1 | def method1(arr, n): 2 | hash_map = {} 3 | curr_sum = 0 4 | max_len = 0 5 | ending_index = -1 6 | 7 | for i in range(0, n): 8 | if arr[i] == 0: 9 | arr[i] = -1 10 | else: 11 | arr[i] = 1 12 | 13 | for i in range(0, n): 14 | curr_sum = curr_sum + arr[i] 15 | if curr_sum == 0: 16 | max_len = i + 1 17 | ending_index = i 18 | if curr_sum in hash_map: 19 | if max_len < i - hash_map[curr_sum]: 20 | max_len = i - hash_map[curr_sum] 21 | ending_index = i 22 | else: 23 | hash_map[curr_sum] = i 24 | 25 | for i in range(0, n): 26 | if arr[i] == -1: 27 | arr[i] = 0 28 | else: 29 | arr[i] = 1 30 | 31 | print(ending_index - max_len + 1, end=" ") 32 | print("to", end=" ") 33 | print(ending_index) 34 | 35 | return max_len 36 | 37 | 38 | if __name__ == "__main__": 39 | """ 40 | from timeit import timeit 41 | arr = [1, 0, 0, 1, 0, 1, 1] 42 | n = len(arr) 43 | print(timeit(lambda: method1(arr, n), number=10000)) # 0.15342295799928252 44 | """ 45 | -------------------------------------------------------------------------------- /N_tree/implementation/D_level_order_traversal.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, key): 3 | self.data = key 4 | self.left = None 5 | self.right = None 6 | 7 | 8 | def printLevelOrder(root): 9 | h = height(root) 10 | for i in range(1, h + 1): 11 | printGivenLevel(root, i) 12 | 13 | 14 | def printGivenLevel(root, level): 15 | if root is None: 16 | return 17 | if level == 1: 18 | print(root.data, end=" ") 19 | elif level > 1: 20 | printGivenLevel(root.left, level - 1) 21 | printGivenLevel(root.right, level - 1) 22 | 23 | 24 | def height(node): 25 | if node is None: 26 | return 0 27 | else: 28 | 29 | lheight = height(node.left) 30 | rheight = height(node.right) 31 | 32 | if lheight > rheight: 33 | return lheight + 1 34 | else: 35 | return rheight + 1 36 | 37 | 38 | if __name__ == "__main__": 39 | """ 40 | from timeit import timeit 41 | 42 | root = Node(1) 43 | root.left = Node(2) 44 | root.right = Node(3) 45 | root.left.left = Node(4) 46 | root.left.right = Node(5) 47 | 48 | print(timeit(lambda: printLevelOrder(root), number=10000)) # 0.054091101002995856 49 | """ 50 | -------------------------------------------------------------------------------- /O_binary_search_tree/problems/H_vertical_traversal_of_binary_tree.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, key): 3 | self.key = key 4 | self.left = None 5 | self.right = None 6 | 7 | 8 | def getVerticalOrder(root, hd, m): 9 | 10 | if root is None: 11 | return 12 | 13 | try: 14 | m[hd].append(root.key) 15 | except: 16 | m[hd] = [root.key] 17 | 18 | getVerticalOrder(root.left, hd - 1, m) 19 | 20 | getVerticalOrder(root.right, hd + 1, m) 21 | 22 | 23 | def printVerticalOrder(root): 24 | 25 | m = dict() 26 | hd = 0 27 | getVerticalOrder(root, hd, m) 28 | 29 | for index, value in enumerate(sorted(m)): 30 | print(index) 31 | for i in m[value]: 32 | print(i) 33 | 34 | 35 | if __name__ == "__main__": 36 | """ 37 | from timeit import timeit 38 | 39 | root = Node(1) 40 | root.left = Node(2) 41 | root.right = Node(3) 42 | root.left.left = Node(4) 43 | root.left.right = Node(5) 44 | root.right.left = Node(6) 45 | root.right.right = Node(7) 46 | root.right.left.right = Node(8) 47 | root.right.right.right = Node(9) 48 | print(timeit(lambda: printVerticalOrder(root), number=10000)) # 0.37157143000513315 49 | """ 50 | -------------------------------------------------------------------------------- /J_linked_list/problems/H_the_intersection_of_two_linked_list.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self): 3 | self.data = 0 4 | self.next = None 5 | 6 | 7 | def getIntersectionNode(head1, head2): 8 | 9 | curr1 = head1 10 | curr2 = head2 11 | 12 | while curr1 != curr2: 13 | if curr1 == None: 14 | curr1 = head2 15 | else: 16 | curr1 = curr1.next 17 | if curr2 == None: 18 | curr2 = head1 19 | else: 20 | curr2 = curr2.next 21 | return curr1.data 22 | 23 | 24 | if __name__ == "__main__": 25 | """ 26 | from timeit import timeit 27 | newNode = None 28 | head1 = Node() 29 | head1.data = 10 30 | head2 = Node() 31 | head2.data = 3 32 | newNode = Node() 33 | newNode.data = 6 34 | head2.next = newNode 35 | newNode = Node() 36 | newNode.data = 9 37 | head2.next.next = newNode 38 | newNode = Node() 39 | newNode.data = 15 40 | head1.next = newNode 41 | head2.next.next.next = newNode 42 | newNode = Node() 43 | newNode.data = 30 44 | head1.next.next = newNode 45 | head1.next.next.next = None 46 | print(timeit(lambda: getIntersectionNode(head1, head2), number=10000)) # 0.0124431709991768 47 | """ 48 | -------------------------------------------------------------------------------- /I_string/E_given_a_text_string_and_a_pattern_string_find_if_a_permutation_of_the_pattern_exists_in_the_text.py: -------------------------------------------------------------------------------- 1 | def method1(str1: str, str2: str) -> int: 2 | def compare(str1, str2): 3 | for i in range(256): 4 | if str1[i] != str2[i]: 5 | return False 6 | return True 7 | 8 | def search(pat, txt): 9 | m = len(pat) 10 | n = len(txt) 11 | 12 | count_p = [0] * 256 13 | count_t = [0] * 256 14 | 15 | for i in range(m): 16 | count_p[ord(pat[i])] += 1 17 | count_t[ord(txt[i])] += 1 18 | 19 | for i in range(m, n): 20 | if compare(count_p, count_t): 21 | return ("Found at ", i - m) 22 | 23 | count_t[ord(txt[i])] += 1 24 | count_t[ord(txt[i-m])] -= 1 25 | 26 | if compare(count_p, count_t): 27 | return ("Found at ", n - m) 28 | 29 | txt = "thisisastringtocompare" 30 | pat = "thisisiastring" 31 | 32 | search(pat, txt) 33 | 34 | 35 | if __name__ == "__main__": 36 | """ 37 | from timeit import timeit 38 | txt = "thisisastringtocompare" 39 | pat = "thisisiastring" 40 | print(timeit(lambda: method1(pat, txt), number=10000)) # 0.4546106020006846 41 | """ 42 | -------------------------------------------------------------------------------- /K_stack/problems/A_balanced_parenthesis_.py: -------------------------------------------------------------------------------- 1 | def method1(myStr: str) -> bool: 2 | """ 3 | Declare a character stack S. 4 | Now traverse the expression string. 5 | If the current character is a starting bracket (‘(‘ or ‘{‘ or ‘[‘) then push it to stack. 6 | If the current character is a closing bracket (‘)’ or ‘}’ or ‘]’) then pop from stack and if the popped character is the matching starting bracket then fine else brackets are not balanced. 7 | After complete traversal, if there is some starting bracket left in stack then “not balanced” 8 | """ 9 | 10 | open_list = ["[", "{", "("] 11 | close_list = ["]", "}", ")"] 12 | stack = [] 13 | for i in myStr: 14 | if i in open_list: 15 | stack.append(i) 16 | elif i in close_list: 17 | pos = close_list.index(i) 18 | if (len(stack) > 0) and (open_list[pos] == stack[len(stack) - 1]): 19 | stack.pop() 20 | else: 21 | return False 22 | if len(stack) == 0: 23 | return True 24 | else: 25 | return False 26 | 27 | 28 | if __name__ == "__main__": 29 | """ 30 | from timeit import timeit 31 | print(timeit(lambda: method1("{[]{()}}"), number=10000)) # 0.013378982999711297 32 | """ 33 | -------------------------------------------------------------------------------- /D_arrays/problems/maximum_circular_subarray_sum.py: -------------------------------------------------------------------------------- 1 | def method1(): 2 | 3 | from sys import maxsize 4 | 5 | def maxsubarraysum(a, size): 6 | max_so_far = -maxsize - 1 7 | max_ending_here = 0 8 | 9 | for i in range(0, size): 10 | max_ending_here = max_ending_here + a[i] 11 | if max_so_far < max_ending_here: 12 | max_so_far = max_ending_here 13 | if max_ending_here < 0: 14 | max_ending_here = 0 15 | 16 | return max_so_far 17 | 18 | def maxCircularSum(a): 19 | 20 | n = len(a) 21 | max_kadane = maxsubarraysum(a, size) 22 | max_wrap = 0 23 | for i in range(0, n): 24 | max_wrap += a[i] 25 | a[i] = -a[i] 26 | max_wrap = max_wrap + maxsubarraysum(a, size) 27 | 28 | if max_wrap > max_kadane: 29 | return max_wrap 30 | else: 31 | return max_kadane 32 | return maxsubarraysum(a, size) 33 | 34 | a = [11, 10, -20, 5, -3, -5, 8, -13, 10] 35 | size = len(a) 36 | 37 | return maxCircularSum(a) 38 | 39 | 40 | if __name__ == "__main__": 41 | """ 42 | from timeit import timeit 43 | print(timeit(lambda: method1(), number=10000)) # 0.04304332999890903 44 | """ 45 | -------------------------------------------------------------------------------- /G_matrix/Z_matrix.md: -------------------------------------------------------------------------------- 1 | # List of Contents 2 | 3 | - [Multidimensional Matrix](https://github.com/thisisshub/DSA/blob/main/G_matrix/A_multidimensional_matrix.py) 4 | - [Pass Matrix As Argument](https://github.com/thisisshub/DSA/blob/main/G_matrix/B_pass_matrix_as_argument.py) 5 | - [Printing Matrix In A Snake Pattern](https://github.com/thisisshub/DSA/blob/main/G_matrix/C_printing_matrix_in_a_snake_pattern.py) 6 | - [Transposing A Matrix](https://github.com/thisisshub/DSA/blob/main/G_matrix/D_transposing_a_matrix.py) 7 | - [Rotating A Matrix](https://github.com/thisisshub/DSA/blob/main/G_matrix/E_rotating_a_matrix.py) 8 | - [Check If The Element Is Present In A Row And Column-Wise Sorted Matrix](https://github.com/thisisshub/DSA/blob/main/G_matrix/F_check_if_the_element_is_present_in_a_row_and_column-wise_sorted_matrix.py) 9 | - [Boundary Traversal](https://github.com/thisisshub/DSA/blob/main/G_matrix/G_boundary_traversal.py) 10 | - [Spiral Traversal](https://github.com/thisisshub/DSA/blob/main/G_matrix/H_spiral_traversal.py) 11 | - [Matrix Multiplication](https://github.com/thisisshub/DSA/blob/main/G_matrix/I_matrix_multiplication.py) 12 | - [Search In Row-Wise And Column-Wise Sorted Matrix](https://github.com/thisisshub/DSA/blob/main/G_matrix/J_search_in_row-wise_and_column-wise_sorted_matrix.py) -------------------------------------------------------------------------------- /J_linked_list/loop_problems/B_detecting_loops_using_floyd_cycle_detection.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.next = None 5 | 6 | 7 | class LinkedList: 8 | def __init__(self): 9 | self.head = None 10 | 11 | def push(self, new_data): 12 | new_node = Node(new_data) 13 | new_node.next = self.head 14 | self.head = new_node 15 | 16 | def printList(self): 17 | temp = self.head 18 | while temp: 19 | print(temp.data) 20 | temp = temp.next 21 | 22 | def detectLoop(self): 23 | slow_p = self.head 24 | fast_p = self.head 25 | while slow_p and fast_p and fast_p.next: 26 | slow_p = slow_p.next 27 | fast_p = fast_p.next.next 28 | if slow_p == fast_p: 29 | return True 30 | 31 | 32 | llist = LinkedList() 33 | llist.push(1) 34 | llist.push(2) 35 | llist.push(3) 36 | llist.push(4) 37 | 38 | 39 | if __name__ == "__main__": 40 | """ 41 | from timeit import timeit 42 | llist.head.next.next.next.next = llist.head 43 | if llist.detectLoop(): 44 | print(timeit(lambda: llist.detectLoop(), number=10000)) # 0.005036081999605813 45 | else: 46 | print("No loop") 47 | """ 48 | -------------------------------------------------------------------------------- /K_stack/problems/B_two_stacks_in_an_array_.py: -------------------------------------------------------------------------------- 1 | class TwoStacks: 2 | 3 | def __init__(self, n): 4 | self.size = n 5 | self.arr = [None] * n 6 | self.top1 = -1 7 | self.top2 = self.size 8 | 9 | 10 | def push1(self, x): 11 | if self.top1 < self.top2 - 1 : 12 | self.top1 = self.top1 + 1 13 | self.arr[self.top1] = x 14 | else: 15 | print("Stack Overflow ") 16 | exit(1) 17 | 18 | 19 | def push2(self, x): 20 | if self.top1 < self.top2 - 1: 21 | self.top2 = self.top2 - 1 22 | self.arr[self.top2] = x 23 | else: 24 | print("Stack Overflow ") 25 | exit(1) 26 | 27 | 28 | def pop1(self): 29 | if self.top1 >= 0: 30 | x = self.arr[self.top1] 31 | self.top1 = self.top1 -1 32 | return x 33 | else: 34 | print("Stack Underflow ") 35 | exit(1) 36 | 37 | 38 | def pop2(self): 39 | if self.top2 < self.size: 40 | x = self.arr[self.top2] 41 | self.top2 = self.top2 + 1 42 | return x 43 | else: 44 | print("Stack Underflow ") 45 | exit() 46 | 47 | 48 | if __name__ == "__main__":\ 49 | """ 50 | from timeit import timeit 51 | ts = TwoStacks(5) 52 | ts.push1(1) 53 | ts.push2(2) 54 | ts.push2(3) 55 | ts.push1(4) 56 | ts.push2(5) 57 | print(timeit(lambda: ts, number=10000)) # 0.0004057340011058841 58 | """ 59 | -------------------------------------------------------------------------------- /Q_graphs/A_adjacency_matrix.py: -------------------------------------------------------------------------------- 1 | class Graph(object): 2 | def __init__(self, size): 3 | self.adjMatrix = [] 4 | for _ in range(size): 5 | self.adjMatrix.append([0 for i in range(size)]) 6 | self.size = size 7 | 8 | def add_edge(self, v1, v2): 9 | if v1 == v2: 10 | print("Same vertex %d and %d" % (v1, v2)) 11 | self.adjMatrix[v1][v2] = 1 12 | self.adjMatrix[v2][v1] = 1 13 | 14 | def remove_edge(self, v1, v2): 15 | if self.adjMatrix[v1][v2] == 0: 16 | print("No edge between %d and %d" % (v1, v2)) 17 | return 18 | self.adjMatrix[v1][v2] = 0 19 | self.adjMatrix[v2][v1] = 0 20 | 21 | def __len__(self): 22 | return self.size 23 | 24 | def print_matrix(self): 25 | for row in self.adjMatrix: 26 | for val in row: 27 | print("{:4}".format(val)), 28 | print 29 | 30 | 31 | def main(): 32 | g = Graph(5) 33 | g.add_edge(0, 1) 34 | g.add_edge(0, 2) 35 | g.add_edge(1, 2) 36 | g.add_edge(2, 0) 37 | g.add_edge(2, 3) 38 | 39 | g.print_matrix() 40 | 41 | 42 | if __name__ == "__main__": 43 | """ 44 | from timeit import timeit 45 | 46 | print(timeit(lambda: main(), number=10000)) # 1.204392577001272 47 | """ 48 | -------------------------------------------------------------------------------- /J_linked_list/problems/I_pairwise_swap_nodes_of_linked_list.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.next = None 5 | 6 | 7 | class LinkedList: 8 | def __init__(self): 9 | self.head = None 10 | 11 | def pairwiseSwap(self): 12 | temp = self.head 13 | 14 | if temp is None: 15 | return 16 | 17 | while temp is not None and temp.next is not None: 18 | if temp.data == temp.next.data: 19 | temp = temp.next.next 20 | else: 21 | temp.data, temp.next.data = temp.next.data, temp.data 22 | temp = temp.next.next 23 | 24 | def push(self, new_data): 25 | new_node = Node(new_data) 26 | new_node.next = self.head 27 | self.head = new_node 28 | 29 | def printList(self): 30 | temp = self.head 31 | while temp: 32 | print(temp.data) 33 | temp = temp.next 34 | 35 | 36 | if __name__ == "__main__": 37 | """ 38 | from timeit import timeit 39 | llist = LinkedList() 40 | llist.push(5) 41 | llist.push(4) 42 | llist.push(3) 43 | llist.push(2) 44 | llist.push(1) 45 | llist.pairwiseSwap() 46 | print(timeit(lambda: llist.printList(), number=10000)) # 0.27164168400122435 47 | """ 48 | -------------------------------------------------------------------------------- /O_binary_search_tree/problems/C_find_kth_smallest_in_bst.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, key): 3 | 4 | self.data = key 5 | self.left = None 6 | self.right = None 7 | 8 | 9 | def insert(root, x): 10 | 11 | if root == None: 12 | return Node(x) 13 | if x < root.data: 14 | root.left = insert(root.left, x) 15 | elif x > root.data: 16 | root.right = insert(root.right, x) 17 | return root 18 | 19 | 20 | def kthSmallest(root, k): 21 | 22 | if root == None: 23 | return None 24 | 25 | left = kthSmallest(root.left, k) 26 | 27 | if left != None: 28 | return left 29 | 30 | k -= 1 31 | if k == 0: 32 | return root 33 | 34 | return kthSmallest(root.right, k) 35 | 36 | 37 | def printKthSmallest(root): 38 | 39 | res = kthSmallest(root, k) 40 | 41 | if res == None: 42 | print("There are less than k nodes in the BST") 43 | else: 44 | print("K-th Smallest Element is ", res.data) 45 | 46 | 47 | if __name__ == "__main__": 48 | from timeit import timeit 49 | 50 | root = None 51 | keys = [20, 8, 22, 4, 12, 10, 14] 52 | 53 | for x in keys: 54 | root = insert(root, x) 55 | 56 | k = 3 57 | 58 | print(timeit(lambda: printKthSmallest(root), number=10000)) # 0.21984126699680928 59 | -------------------------------------------------------------------------------- /Q_graphs/B_adjacency_list.py: -------------------------------------------------------------------------------- 1 | class AdjNode: 2 | def __init__(self, data): 3 | self.vertex = data 4 | self.next = None 5 | 6 | 7 | class Graph: 8 | def __init__(self, vertices): 9 | self.V = vertices 10 | self.graph = [None] * self.V 11 | 12 | def add_edge(self, src, dest): 13 | 14 | node = AdjNode(dest) 15 | node.next = self.graph[src] 16 | self.graph[src] = node 17 | 18 | node = AdjNode(src) 19 | node.next = self.graph[dest] 20 | self.graph[dest] = node 21 | 22 | def print_graph(self): 23 | for i in range(self.V): 24 | print("Adjacency list of vertex {}\n head".format(i), end="") 25 | temp = self.graph[i] 26 | while temp: 27 | print(" -> {}".format(temp.vertex), end="") 28 | temp = temp.next 29 | print(" \n") 30 | 31 | 32 | if __name__ == "__main__": 33 | """ 34 | from timeit import timeit 35 | 36 | V = 5 37 | graph = Graph(V) 38 | graph.add_edge(0, 1) 39 | graph.add_edge(0, 4) 40 | graph.add_edge(1, 2) 41 | graph.add_edge(1, 3) 42 | graph.add_edge(1, 4) 43 | graph.add_edge(2, 3) 44 | graph.add_edge(3, 4) 45 | 46 | print(timeit(lambda: graph.print_graph(), number=10000)) # 1.7298283870004525 47 | """ 48 | -------------------------------------------------------------------------------- /E_searching/two_pointer_approach_problems/A_find_pair_in_an_unsorted_array_which_gives_sum_x.py: -------------------------------------------------------------------------------- 1 | def method1(arr, arr_size, sum): 2 | s = set() 3 | for i in range(0, arr_size): 4 | temp = sum - arr[i] 5 | if temp in s: 6 | print(s.add(arr[i])) 7 | 8 | def quickSort(A, si, ei): 9 | if si < ei: 10 | pi = partition(A, si, ei) 11 | quickSort(A, si, pi - 1) 12 | quickSort(A, pi + 1, ei) 13 | 14 | 15 | def partition(A, si, ei): 16 | x = A[ei] 17 | i = si - 1 18 | for j in range(si, ei): 19 | if A[j] <= x: 20 | i += 1 21 | A[i], A[j] = A[j], A[i] 22 | A[i + 1], A[ei] = A[ei], A[i + 1] 23 | return i + 1 24 | 25 | def method2(A, arr_size, sum): 26 | quickSort(A, 0, arr_size - 1) 27 | l = 0 28 | r = arr_size - 1 29 | while l < r: 30 | if A[l] + A[r] == sum: 31 | return 1 32 | elif A[l] + A[r] < sum: 33 | l += 1 34 | else: 35 | r -= 1 36 | return 0 37 | 38 | 39 | if __name__ == "__main__": 40 | """ 41 | A = [1, 4, 45, 6, 10, 8] 42 | n = 16 43 | from timeit import timeit 44 | print(timeit(lambda: method1(A, len(A), n), number=10000)) # 0.007289881999895442 45 | print(timeit(lambda: method2(A, len(A), n), number=10000)) # 0.046296988999529276 46 | """ 47 | -------------------------------------------------------------------------------- /J_linked_list/problems/D_recursive_method_to_reverse_a_linked_list.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.next = None 5 | 6 | 7 | class LinkedList: 8 | def __init__(self): 9 | self.head = None 10 | 11 | def reverse(self, head): 12 | 13 | if head is None or head.next is None: 14 | return head 15 | 16 | rest = self.reverse(head.next) 17 | 18 | head.next.next = head 19 | head.next = None 20 | 21 | return rest 22 | 23 | def __str__(self): 24 | linkedListStr = "" 25 | temp = self.head 26 | while temp: 27 | linkedListStr = linkedListStr + str(temp.data) + " " 28 | temp = temp.next 29 | return linkedListStr 30 | 31 | def push(self, data): 32 | temp = Node(data) 33 | temp.next = self.head 34 | self.head = temp 35 | 36 | 37 | if __name__ == "__main__": 38 | """ 39 | from timeit import timeit 40 | linkedList = LinkedList() 41 | linkedList.push(1) 42 | linkedList.push(2) 43 | linkedList.push(3) 44 | linkedList.push(4) 45 | print(timeit(lambda: linkedList, number=10000)) # 0.00046981800005596597 46 | linkedList.head = linkedList.reverse(linkedList.head) 47 | print(timeit(lambda: linkedList, number=10000)) # 0.0004048120008519618 48 | """ 49 | -------------------------------------------------------------------------------- /N_tree/problems/M_lca_problem_with_an_efficient_solution.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, key): 3 | self.key = key 4 | self.left = None 5 | self.right = None 6 | 7 | 8 | def findPath(root, path, k): 9 | 10 | if root is None: 11 | return False 12 | 13 | path.append(root.key) 14 | 15 | if root.key == k: 16 | return True 17 | 18 | if (root.left != None and findPath(root.left, path, k)) or ( 19 | root.right != None and findPath(root.right, path, k) 20 | ): 21 | return True 22 | 23 | path.pop() 24 | return False 25 | 26 | 27 | def method1(root, n1, n2): 28 | 29 | path1 = [] 30 | path2 = [] 31 | 32 | if not findPath(root, path1, n1) or not findPath(root, path2, n2): 33 | return -1 34 | 35 | i = 0 36 | while i < len(path1) and i < len(path2): 37 | if path1[i] != path2[i]: 38 | break 39 | i += 1 40 | return path1[i - 1] 41 | 42 | 43 | if __name__ == "__main__": 44 | """ 45 | from timeit import timeit 46 | 47 | root = Node(1) 48 | root.left = Node(2) 49 | root.right = Node(3) 50 | root.left.left = Node(4) 51 | root.left.right = Node(5) 52 | root.right.left = Node(6) 53 | root.right.right = Node(7) 54 | 55 | print(timeit(lambda: method1(root, 4, 5), number=10000)) # 0.01732934000028763 56 | """ 57 | -------------------------------------------------------------------------------- /R_greedy/B_fractional_knapsack.py: -------------------------------------------------------------------------------- 1 | class ItemValue: 2 | def __init__(self, wt, val, ind): 3 | self.wt = wt 4 | self.val = val 5 | self.ind = ind 6 | self.cost = val // wt 7 | 8 | def __lt__(self, other): 9 | return self.cost < other.cost 10 | 11 | 12 | class FractionalKnapSack: 13 | @staticmethod 14 | def getMaxValue(wt, val, capacity): 15 | iVal = [] 16 | for i in range(len(wt)): 17 | iVal.append(ItemValue(wt[i], val[i], i)) 18 | 19 | iVal.sort(reverse=True) 20 | 21 | totalValue = 0 22 | for i in iVal: 23 | curWt = int(i.wt) 24 | curVal = int(i.val) 25 | if capacity - curWt >= 0: 26 | capacity -= curWt 27 | totalValue += curVal 28 | else: 29 | fraction = capacity / curWt 30 | totalValue += curVal * fraction 31 | capacity = int(capacity - (curWt * fraction)) 32 | break 33 | return totalValue 34 | 35 | 36 | if __name__ == "__main__": 37 | """ 38 | from timeit import timeit 39 | 40 | wt = [10, 40, 20, 30] 41 | val = [60, 40, 100, 120] 42 | capacity = 50 43 | 44 | maxValue = FractionalKnapSack.getMaxValue(wt, val, capacity) 45 | print(timeit(lambda: maxValue, number=10000)) # 0.00045536499965237454 46 | """ 47 | -------------------------------------------------------------------------------- /S_backtracking/A_rat_in_a_maze.py: -------------------------------------------------------------------------------- 1 | N = 4 2 | 3 | 4 | def printSolution(sol): 5 | 6 | for i in sol: 7 | for j in i: 8 | print(str(j) + " ", end="") 9 | print("") 10 | 11 | 12 | def isSafe(maze, x, y): 13 | 14 | if x >= 0 and x < N and y >= 0 and y < N and maze[x][y] == 1: 15 | return True 16 | 17 | return False 18 | 19 | 20 | def solveMaze(maze): 21 | 22 | sol = [[0 for j in range(4)] for i in range(4)] 23 | 24 | if solveMazeUtil(maze, 0, 0, sol) == False: 25 | print("Solution doesn't exist") 26 | return False 27 | 28 | printSolution(sol) 29 | return True 30 | 31 | 32 | def solveMazeUtil(maze, x, y, sol): 33 | 34 | if x == N - 1 and y == N - 1 and maze[x][y] == 1: 35 | sol[x][y] = 1 36 | return True 37 | 38 | if isSafe(maze, x, y) == True: 39 | 40 | sol[x][y] = 1 41 | 42 | if solveMazeUtil(maze, x + 1, y, sol) == True: 43 | return True 44 | 45 | if solveMazeUtil(maze, x, y + 1, sol) == True: 46 | return True 47 | 48 | sol[x][y] = 0 49 | return False 50 | 51 | 52 | if __name__ == "__main__": 53 | """ 54 | from timeit import timeit 55 | 56 | maze = [[1, 0, 0, 0], [1, 1, 0, 1], [0, 1, 0, 0], [1, 1, 1, 1]] 57 | 58 | print(timeit(lambda: solveMaze(maze), number=10000)) # 0.26687077400129056 59 | """ 60 | -------------------------------------------------------------------------------- /I_string/I_kmp_algorithm.py: -------------------------------------------------------------------------------- 1 | def method1(pat: str, txt: str) -> int: 2 | def kmp_search(pat, txt): 3 | m = len(pat) 4 | n = len(txt) 5 | 6 | lps = [0] * m 7 | j = 0 8 | 9 | compute_lps_array(pat, m, lps) 10 | i = 0 11 | while i < n: 12 | if pat[j] == txt[i]: 13 | i += 1 14 | j += 1 15 | if j == m: 16 | return "Found pattern at: " + str(i - j) 17 | j = lps[j - 1] 18 | 19 | elif i < n and pat[j] != txt[i]: 20 | if j != 0: 21 | j = lps[j - 1] 22 | else: 23 | i += 1 24 | 25 | def compute_lps_array(pat, m, lps): 26 | len = 0 27 | lps[0] 28 | i = 1 29 | 30 | while i < m: 31 | if pat[i] == pat[len]: 32 | len += 1 33 | lps[i] = len 34 | i += 1 35 | else: 36 | if len != 0: 37 | len = lps[len - 1] 38 | else: 39 | lps[i] = 0 40 | i += 1 41 | 42 | 43 | if __name__ == "__main__": 44 | """ 45 | from timeit import timeit 46 | txt = "ABABDABACDABABCABAB" 47 | pat = "ABABCABAB" 48 | print(timeit(lambda: method1(pat, txt), number=10000)) # 0.001750715999150998 49 | """ 50 | -------------------------------------------------------------------------------- /J_linked_list/problems/O_reverse_a_doubly_linked_list.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.next = None 5 | self.prev = None 6 | 7 | 8 | class DoublyLinkedList: 9 | def __init__(self): 10 | self.head = None 11 | 12 | def reverse(self): 13 | temp = None 14 | current = self.head 15 | 16 | while current is not None: 17 | temp = current.prev 18 | current.prev = current.next 19 | current.next = temp 20 | current = current.prev 21 | 22 | if temp is not None: 23 | self.head = temp.prev 24 | 25 | def push(self, new_data): 26 | 27 | new_node = Node(new_data) 28 | 29 | new_node.next = self.head 30 | 31 | if self.head is not None: 32 | self.head.prev = new_node 33 | 34 | self.head = new_node 35 | 36 | def printList(self, node): 37 | while node is not None: 38 | print(node.data) 39 | node = node.next 40 | 41 | 42 | if __name__ == "__main__": 43 | """ 44 | from timeit import timeit 45 | 46 | dll = DoublyLinkedList() 47 | dll.push(2) 48 | dll.push(4) 49 | dll.push(8) 50 | dll.push(10) 51 | 52 | dll.printList(dll.head) 53 | 54 | print(timeit(lambda: dll.reverse(), number=10000)) # 0.008048882000366575 55 | """ 56 | -------------------------------------------------------------------------------- /O_binary_search_tree/problems/J_bottom_view_of_binary_tree.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, key): 3 | 4 | self.data = key 5 | self.hd = 1000000 6 | self.left = None 7 | self.right = None 8 | 9 | 10 | def bottomView(root): 11 | 12 | if root == None: 13 | return 14 | 15 | hd = 0 16 | 17 | m = dict() 18 | 19 | q = [] 20 | 21 | root.hd = hd 22 | 23 | q.append(root) 24 | 25 | while len(q) != 0: 26 | temp = q[0] 27 | 28 | q.pop(0) 29 | 30 | hd = temp.hd 31 | 32 | m[hd] = temp.data 33 | 34 | if temp.left != None: 35 | temp.left.hd = hd - 1 36 | q.append(temp.left) 37 | 38 | if temp.right != None: 39 | temp.right.hd = hd + 1 40 | q.append(temp.right) 41 | 42 | for i in sorted(m.keys()): 43 | print(m[i], end=" ") 44 | 45 | 46 | if __name__ == "__main__": 47 | """ 48 | from timeit import timeit 49 | 50 | root = Node(20) 51 | root.left = Node(8) 52 | root.right = Node(22) 53 | root.left.left = Node(5) 54 | root.left.right = Node(3) 55 | root.right.left = Node(4) 56 | root.right.right = Node(25) 57 | root.left.right.left = Node(10) 58 | root.left.right.right = Node(14) 59 | 60 | print(timeit(lambda: bottomView(root), number=10000)) # 0.08178278699779185 61 | """ 62 | -------------------------------------------------------------------------------- /N_tree/problems/H_maximum_width_of_binary_tree.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.left = None 5 | self.right = None 6 | 7 | 8 | def getMaxWidth(root): 9 | maxWidth = 0 10 | h = height(root) 11 | 12 | for i in range(1, h + 1): 13 | width = getWidth(root, i) 14 | if width > maxWidth: 15 | maxWidth = width 16 | return maxWidth 17 | 18 | 19 | def getWidth(root, level): 20 | if root is None: 21 | return 0 22 | if level == 1: 23 | return 1 24 | elif level > 1: 25 | return getWidth(root.left, level - 1) + getWidth(root.right, level - 1) 26 | 27 | 28 | def height(node): 29 | if node is None: 30 | return 0 31 | else: 32 | 33 | lHeight = height(node.left) 34 | rHeight = height(node.right) 35 | 36 | return (lHeight + 1) if (lHeight > rHeight) else (rHeight + 1) 37 | 38 | 39 | if __name__ == "__main__": 40 | """ 41 | from timeit import timeit 42 | 43 | root = Node(1) 44 | root.left = Node(2) 45 | root.right = Node(3) 46 | root.left.left = Node(4) 47 | root.left.right = Node(5) 48 | root.right.right = Node(8) 49 | root.right.right.left = Node(6) 50 | root.right.right.right = Node(7) 51 | 52 | print(timeit(lambda: getMaxWidth(root), number=10000)) # 0.039740855994750746 53 | """ 54 | -------------------------------------------------------------------------------- /T_dynamic_programming/problems/edit_distance_problem/A_naive_approach.py: -------------------------------------------------------------------------------- 1 | def method1(str1, str2, m, n): 2 | 3 | # If first string is empty, the only option is to 4 | # insert all characters of second string into first 5 | if m == 0: 6 | return n 7 | 8 | # If second string is empty, the only option is to 9 | # remove all characters of first string 10 | if n == 0: 11 | return m 12 | 13 | # If last characters of two strings are same, nothing 14 | # much to do. Ignore last characters and get count for 15 | # remaining strings. 16 | if str1[m - 1] == str2[n - 1]: 17 | return method1(str1, str2, m - 1, n - 1) 18 | 19 | # If last characters are not same, consider all three 20 | # operations on last character of first string, recursively 21 | # compute minimum cost for all three operations and take 22 | # minimum of three values. 23 | return 1 + min( 24 | method1(str1, str2, m, n - 1), # Insert 25 | method1(str1, str2, m - 1, n), # Remove 26 | method1(str1, str2, m - 1, n - 1), # Replace 27 | ) 28 | 29 | 30 | if __name__ == "__main__": 31 | """ 32 | from timeit import timeit 33 | 34 | # Driver code 35 | str1 = "sunday" 36 | str2 = "saturday" 37 | print( 38 | timeit(lambda: method1(str1, str2, len(str1), len(str2)), number=10000) 39 | ) # 0.2074630530041759 40 | """ -------------------------------------------------------------------------------- /E_searching/problems/E_find_an_element_in_sorted_and_rotated_array.py: -------------------------------------------------------------------------------- 1 | def method1(l: list, n: int, key: int) -> int: 2 | pivot = findPivot(l, 0, n - 1) 3 | if pivot == -1: 4 | return binarySearch(l, 0, n - 1, key) 5 | if l[pivot] == key: 6 | return pivot 7 | if l[0] <= key: 8 | return binarySearch(l, 0, pivot - 1, key) 9 | return binarySearch(l, pivot + 1, n - 1, key) 10 | 11 | 12 | def findPivot(l, low, high): 13 | if high < low: 14 | return -1 15 | if high == low: 16 | return low 17 | mid = int((low + high) / 2) 18 | if mid < high and l[mid] > l[mid + 1]: 19 | return mid 20 | if mid > low and l[mid] < l[mid - 1]: 21 | return mid - 1 22 | if l[low] >= l[mid]: 23 | return findPivot(l, low, mid - 1) 24 | return findPivot(l, mid + 1, high) 25 | 26 | 27 | def binarySearch(l, low, high, key): 28 | if high < low: 29 | return -1 30 | mid = int((low + high) / 2) 31 | if key == l[mid]: 32 | return mid 33 | if key > l[mid]: 34 | return binarySearch(l, (mid + 1), high, key) 35 | return binarySearch(l, low, (mid - 1), key) 36 | 37 | 38 | if __name__ == "__main__": 39 | """ 40 | from timeit import timeit 41 | ll = [5, 6, 7, 8, 9, 10, 1, 2, 3] 42 | n = len(ll) 43 | key = 3 44 | print(timeit(lambda: method1(ll, n, key))) # 1.2764019470005223 45 | """ 46 | -------------------------------------------------------------------------------- /N_tree/problems/K_tree_traversal_spiral_form.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, val): 3 | self.data = val 4 | self.left = None 5 | self.right = None 6 | 7 | 8 | def method1(root): 9 | 10 | d = [] 11 | 12 | d.append(root) 13 | 14 | direct = 0 15 | while len(d) != 0: 16 | size = len(d) 17 | 18 | while size: 19 | size -= 1 20 | 21 | if direct == 0: 22 | temp = d.pop() 23 | 24 | if temp.right: 25 | d.insert(0, temp.right) 26 | 27 | if temp.left: 28 | d.insert(0, temp.left) 29 | 30 | print(temp.data, end=" ") 31 | 32 | else: 33 | temp = d[0] 34 | d.pop(0) 35 | 36 | if temp.left: 37 | d.append(temp.left) 38 | 39 | if temp.right: 40 | d.append(temp.right) 41 | 42 | print(temp.data, end=" ") 43 | 44 | print() 45 | 46 | direct = 1 - direct 47 | 48 | 49 | if __name__ == "__main__": 50 | """ 51 | from timeit import timeit 52 | 53 | root = Node(10) 54 | root.left = Node(20) 55 | root.right = Node(30) 56 | root.left.left = Node(40) 57 | root.left.right = Node(60) 58 | 59 | print(timeit(lambda: method1(root), number=10000)) # 0.5146278480024193 60 | """ 61 | -------------------------------------------------------------------------------- /Q_graphs/problems/E_bellmanford_shortest_path_algorithm.py: -------------------------------------------------------------------------------- 1 | class Graph: 2 | def __init__(self, vertices): 3 | self.V = vertices 4 | self.graph = [] 5 | 6 | def addEdge(self, u, v, w): 7 | self.graph.append([u, v, w]) 8 | 9 | def printArr(self, dist): 10 | print("Vertex Distance from Source") 11 | for i in range(self.V): 12 | print("{0}\t\t{1}".format(i, dist[i])) 13 | 14 | def BellmanFord(self, src): 15 | 16 | dist = [float("Inf")] * self.V 17 | dist[src] = 0 18 | 19 | for _ in range(self.V - 1): 20 | 21 | for u, v, w in self.graph: 22 | if dist[u] != float("Inf") and dist[u] + w < dist[v]: 23 | dist[v] = dist[u] + w 24 | 25 | for u, v, w in self.graph: 26 | if dist[u] != float("Inf") and dist[u] + w < dist[v]: 27 | print("Graph contains negative weight cycle") 28 | return 29 | 30 | self.printArr(dist) 31 | 32 | 33 | if __name__ == "__main__": 34 | """ 35 | from timeit import timeit 36 | 37 | g = Graph(5) 38 | g.addEdge(0, 1, -1) 39 | g.addEdge(0, 2, 4) 40 | g.addEdge(1, 2, 3) 41 | g.addEdge(1, 3, 2) 42 | g.addEdge(1, 4, 2) 43 | g.addEdge(3, 2, 5) 44 | g.addEdge(3, 1, 1) 45 | g.addEdge(4, 3, -3) 46 | 47 | print(timeit(lambda: g.BellmanFord(0), number=10000)) # 0.3252793579995341 48 | """ 49 | -------------------------------------------------------------------------------- /J_linked_list/problems/C_an_iterative_method_to_reverse_a_linked_list_.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.next = None 5 | 6 | 7 | class LinkedList: 8 | def __init__(self): 9 | self.head = None 10 | 11 | def reverse(self): 12 | if self.head is None or self.head.next is None: 13 | return 14 | 15 | prev = None 16 | cur = self.head 17 | 18 | while cur: 19 | next_element = cur.next 20 | cur.next = prev 21 | prev = cur 22 | cur = next_element 23 | 24 | self.head = prev 25 | 26 | def push(self, data): 27 | new_node = Node(data) 28 | new_node.next = self.head 29 | self.head = new_node 30 | 31 | def print_list(self): 32 | cur = self.head 33 | l1 = [] 34 | while cur: 35 | l1.append(cur.data) 36 | cur = cur.next 37 | return l1 38 | 39 | 40 | if __name__ == "__main__": 41 | """ 42 | from timeit import timeit 43 | llist = LinkedList() 44 | llist.push(1) 45 | llist.push(2) 46 | llist.push(3) 47 | llist.push(4) 48 | print(timeit(lambda: llist.print_list(), number=10000)) # 0.0039678699995420175 49 | print(timeit(lambda: llist.reverse(), number=10000)) # 0.004114342000320903 50 | print(timeit(lambda: llist.print_list(), number=10000)) # 0.003999239999757265 51 | """ 52 | -------------------------------------------------------------------------------- /N_tree/problems/N_burn_a_binary_tree_from_a_leaf.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, key): 3 | self.left = None 4 | self.right = None 5 | self.value = key 6 | 7 | 8 | def _recurse(node, start): 9 | if node is None: 10 | return (None, 0) 11 | else: 12 | max_left, dist_left = _recurse(node.left, start) 13 | max_right, dist_right = _recurse(node.right, start) 14 | 15 | if node == start: 16 | return (0, 0) 17 | 18 | elif max_right is not None or max_left is not None: 19 | return ( 20 | dist_right + dist_left + 1, 21 | (dist_left if max_right is None else dist_right) + 1, 22 | ) 23 | 24 | else: 25 | return (None, max(dist_left, dist_right) + 1) 26 | 27 | 28 | def time_to_burn(root, start): 29 | return _recurse(root, start)[0] 30 | 31 | 32 | if __name__ == "__main__": 33 | """ 34 | from timeit import timeit 35 | 36 | root = Node(1) 37 | root.left = Node(1) 38 | root.right = Node(1) 39 | root.left.left = Node(1) 40 | root.left.right = Node(1) 41 | root.left.right.left = Node(1) 42 | root.left.right.right = Node(1) 43 | root.right.right = Node(1) 44 | root.right.right.right = Node(1) 45 | root.right.right.right.right = Node(1) 46 | 47 | print(timeit(lambda: time_to_burn(root, root.left.right.right), number=10000)) # 0.026541252998868003 48 | """ -------------------------------------------------------------------------------- /N_tree/problems/J_construct_binary_tree_from_inorder_and_preorder.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.left = None 5 | self.right = None 6 | 7 | 8 | def buildTree(inOrder, preOrder, inStrt, inEnd): 9 | 10 | if inStrt > inEnd: 11 | return None 12 | 13 | buildTree.preIndex = 0 14 | tNode = Node(preOrder[buildTree.preIndex]) 15 | buildTree.preIndex += 1 16 | 17 | if inStrt == inEnd: 18 | return tNode 19 | 20 | inIndex = search(inOrder, inStrt, inEnd, tNode.data) 21 | 22 | tNode.left = buildTree(inOrder, preOrder, inStrt, inIndex - 1) 23 | tNode.right = buildTree(inOrder, preOrder, inIndex + 1, inEnd) 24 | 25 | return tNode 26 | 27 | 28 | def search(arr, start, end, value): 29 | for i in range(start, end + 1): 30 | if arr[i] == value: 31 | return i 32 | 33 | 34 | def method1(node): 35 | if node is None: 36 | return 37 | 38 | method1(node.left) 39 | 40 | print(node.data) 41 | 42 | method1(node.right) 43 | 44 | 45 | if __name__ == "__main__": 46 | """ 47 | from timeit import timeit 48 | 49 | inOrder = ["D", "B", "E", "A", "F", "C"] 50 | preOrder = ["A", "B", "D", "E", "C", "F"] 51 | 52 | buildTree.preIndex = 0 53 | root = buildTree(inOrder, preOrder, 0, len(inOrder) - 1) 54 | 55 | print(timeit(lambda: method1(root), number=10000)) # 0.2564627779938746 56 | """ 57 | -------------------------------------------------------------------------------- /Q_graphs/problems/detecting_cycle/A_in_the_undirected_graph.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | 4 | class Graph: 5 | def __init__(self, vertices): 6 | 7 | self.V = vertices 8 | 9 | self.graph = defaultdict(list) 10 | 11 | def addEdge(self, v, w): 12 | 13 | self.graph[v].append(w) 14 | 15 | self.graph[w].append(v) 16 | 17 | def isCyclicUtil(self, v, visited, parent): 18 | 19 | visited[v] = True 20 | 21 | for i in self.graph[v]: 22 | 23 | if visited[i] == False: 24 | if self.isCyclicUtil(i, visited, v): 25 | return True 26 | 27 | elif parent != i: 28 | return True 29 | 30 | return False 31 | 32 | def isCyclic(self): 33 | 34 | visited = [False] * (self.V) 35 | 36 | for i in range(self.V): 37 | 38 | if visited[i] == False: 39 | if (self.isCyclicUtil(i, visited, -1)) == True: 40 | return True 41 | 42 | return False 43 | 44 | 45 | if __name__ == "__main__": 46 | """ 47 | from timeit import timeit 48 | 49 | g = Graph(5) 50 | g.addEdge(1, 0) 51 | g.addEdge(1, 2) 52 | g.addEdge(2, 0) 53 | g.addEdge(0, 3) 54 | g.addEdge(3, 4) 55 | 56 | g1 = Graph(3) 57 | g1.addEdge(0, 1) 58 | g1.addEdge(1, 2) 59 | 60 | print(timeit(lambda: g1.isCyclic(), number=10000)) # 0.01144661000216729 61 | """ 62 | -------------------------------------------------------------------------------- /V_segment_tree/A_construction.py: -------------------------------------------------------------------------------- 1 | # limit for array size 2 | N = 100000 3 | 4 | a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] 5 | 6 | n = len(a) 7 | 8 | # Max size of tree 9 | tree = [0] * (2 * N) 10 | 11 | # function to build the tree 12 | def build(arr): 13 | 14 | # insert leaf nodes in tree 15 | for i in range(n): 16 | tree[n + i] = arr[i] 17 | 18 | # build the tree by calculating parents 19 | for i in range(n - 1, 0, -1): 20 | tree[i] = tree[i << 1] + tree[i << 1 | 1] 21 | 22 | 23 | # function to update a tree node 24 | def updateTreeNode(p, value): 25 | 26 | # set value at position p 27 | tree[p + n] = value 28 | p = p + n 29 | 30 | # move upward and update parents 31 | i = p 32 | 33 | while i > 1: 34 | 35 | tree[i >> 1] = tree[i] + tree[i ^ 1] 36 | i >>= 1 37 | 38 | 39 | # function to get sum on interval [l, r) 40 | def query(l, r): 41 | 42 | res = 0 43 | 44 | # loop to find the sum in the range 45 | l += n 46 | r += n 47 | 48 | while l < r: 49 | 50 | if l & 1: 51 | res += tree[l] 52 | l += 1 53 | 54 | if r & 1: 55 | r -= 1 56 | res += tree[r] 57 | 58 | l >>= 1 59 | r >>= 1 60 | 61 | return res 62 | 63 | 64 | if __name__ == "__main__": 65 | """ 66 | from timeit import timeit 67 | 68 | print(timeit(lambda: build(a), number=10000)) # 0.023785294994013384 69 | """ 70 | -------------------------------------------------------------------------------- /I_string/Z_string.md: -------------------------------------------------------------------------------- 1 | # List of Contents 2 | 3 | - [Given A String Check If They Are An Anagram Of Each Other](https://github.com/thisisshub/DSA/blob/main/I_string/A_given_a_string_check_if_they_are_an_anagram_of_each_other.py) 4 | - [Given A String Find The Leftmost Character That Repeats](https://github.com/thisisshub/DSA/blob/main/I_string/B_given_a_string_find_the_leftmost_character_that_repeats.py) 5 | - [Given A String Find The Leftmost Character That Does Not Repeat](https://github.com/thisisshub/DSA/blob/main/I_string/C_given_a_string_find_the_leftmost_character_that_does_not_repeat.py) 6 | - [Given A String Find The Lexicographic Rank](https://github.com/thisisshub/DSA/blob/main/I_string/D_given_a_string_find_the_lexicographic_rank.py) 7 | - [Given A Text String And A Pattern String Find If A Permutation Of The Pattern Exists In The Text](https://github.com/thisisshub/DSA/blob/main/I_string/E_given_a_text_string_and_a_pattern_string_find_if_a_permutation_of_the_pattern_exists_in_the_text.py) 8 | - [Given Two Strings Check If They Are Rotations Of Each Other Or Not](https://github.com/thisisshub/DSA/blob/main/I_string/F_given_two_strings_check_if_they_are_rotations_of_each_other_or_not.py) 9 | - [Palindrome Check](https://github.com/thisisshub/DSA/blob/main/I_string/G_palindrome_check.py) 10 | - [Rabin Karp Algorithm](https://github.com/thisisshub/DSA/blob/main/I_string/H_rabin_karp_algorithm.py) 11 | - [Kmp Algorithm](https://github.com/thisisshub/DSA/blob/main/I_string/I_kmp_algorithm.py) -------------------------------------------------------------------------------- /S_backtracking/B_n_queen_problem.py: -------------------------------------------------------------------------------- 1 | global N 2 | N = 4 3 | 4 | 5 | def printSolution(board): 6 | for i in range(N): 7 | for j in range(N): 8 | print(board[i][j], end=" ") 9 | print() 10 | 11 | 12 | def isSafe(board, row, col): 13 | 14 | for i in range(col): 15 | if board[row][i] == 1: 16 | return False 17 | 18 | for i, j in zip(list(range(row, -1, -1)), list(range(col, -1, -1))): 19 | if board[i][j] == 1: 20 | return False 21 | 22 | for i, j in zip(list(range(row, N, 1)), list(range(col, -1, -1))): 23 | if board[i][j] == 1: 24 | return False 25 | 26 | return True 27 | 28 | 29 | def solveNQUtil(board, col): 30 | 31 | if col >= N: 32 | return True 33 | 34 | for i in range(N): 35 | 36 | if isSafe(board, i, col): 37 | 38 | board[i][col] = 1 39 | 40 | if solveNQUtil(board, col + 1) == True: 41 | return True 42 | 43 | board[i][col] = 0 44 | 45 | return False 46 | 47 | 48 | def solveNQ(): 49 | board = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] 50 | 51 | if solveNQUtil(board, 0) == False: 52 | print("Solution does not exist") 53 | return False 54 | 55 | printSolution(board) 56 | return True 57 | 58 | 59 | if __name__ == "__main__": 60 | """ 61 | from timeit import timeit 62 | 63 | print(timeit(lambda: solveNQ(), number=10000)) # 0.514471112001047 64 | """ 65 | -------------------------------------------------------------------------------- /T_dynamic_programming/problems/F_optimal_strategy_for_a_game.py: -------------------------------------------------------------------------------- 1 | def method1(arr, n): 2 | 3 | # Create a table to store 4 | # solutions of subproblems 5 | table = [[0 for i in range(n)] for i in range(n)] 6 | 7 | # Fill table using above recursive 8 | # formula. Note that the table is 9 | # filled in diagonal fashion 10 | # from diagonal elements to 11 | # table[0][n-1] which is the result. 12 | for gap in range(n): 13 | for j in range(gap, n): 14 | i = j - gap 15 | 16 | # Here x is value of F(i + 2, j), 17 | # y is F(i + 1, j-1) and z is 18 | # F(i, j-2) in above recursive 19 | # formula 20 | x = 0 21 | if (i + 2) <= j: 22 | x = table[i + 2][j] 23 | y = 0 24 | if (i + 1) <= (j - 1): 25 | y = table[i + 1][j - 1] 26 | z = 0 27 | if i <= (j - 2): 28 | z = table[i][j - 2] 29 | table[i][j] = max(arr[i] + min(x, y), arr[j] + min(y, z)) 30 | return table[0][n - 1] 31 | 32 | 33 | if __name__ == "__main__": 34 | """ 35 | from timeit import timeit 36 | 37 | arr1 = [8, 15, 3, 7] 38 | n = len(arr1) 39 | print(method1(arr1, n)) 40 | 41 | arr2 = [2, 2, 2, 2] 42 | n = len(arr2) 43 | print(method1(arr2, n)) 44 | 45 | arr3 = [20, 30, 2, 2, 2, 10] 46 | n = len(arr3) 47 | print( 48 | timeit(lambda: method1(arr3, n), number=10000) 49 | ) # 0.13903403500444256 50 | """ 51 | -------------------------------------------------------------------------------- /Q_graphs/problems/topological_sorting/A_kahn's_bfs_based_algorithm.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | 4 | class Graph: 5 | def __init__(self, vertices): 6 | self.graph = defaultdict(list) 7 | self.V = vertices 8 | 9 | def addEdge(self, u, v): 10 | self.graph[u].append(v) 11 | 12 | def topologicalSort(self): 13 | 14 | in_degree = [0] * (self.V) 15 | 16 | for i in self.graph: 17 | for j in self.graph[i]: 18 | in_degree[j] += 1 19 | 20 | queue = [] 21 | for i in range(self.V): 22 | if in_degree[i] == 0: 23 | queue.append(i) 24 | 25 | cnt = 0 26 | 27 | top_order = [] 28 | 29 | while queue: 30 | 31 | u = queue.pop(0) 32 | top_order.append(u) 33 | 34 | for i in self.graph[u]: 35 | in_degree[i] -= 1 36 | 37 | if in_degree[i] == 0: 38 | queue.append(i) 39 | 40 | cnt += 1 41 | 42 | if cnt != self.V: 43 | print("There exists a cycle in the graph") 44 | else: 45 | 46 | print(top_order) 47 | 48 | 49 | if __name__ == "__main__": 50 | """ 51 | from timeit import timeit 52 | 53 | g = Graph(6) 54 | g.addEdge(5, 2) 55 | g.addEdge(5, 0) 56 | g.addEdge(4, 0) 57 | g.addEdge(4, 1) 58 | g.addEdge(2, 3) 59 | g.addEdge(3, 1) 60 | 61 | print(timeit(lambda: g.topologicalSort(), number=10000)) # 0.12342081200040411 62 | """ 63 | -------------------------------------------------------------------------------- /N_tree/problems/I_convert_binary_tree_to_doubly_linked_list.py: -------------------------------------------------------------------------------- 1 | class Node(object): 2 | 3 | def __init__(self, item): 4 | self.data = item 5 | self.left = None 6 | self.right = None 7 | 8 | 9 | def BTToDLLUtil(root): 10 | 11 | if root is None: 12 | return root 13 | 14 | if root.left: 15 | 16 | left = BTToDLLUtil(root.left) 17 | 18 | while left.right: 19 | left = left.right 20 | 21 | left.right = root 22 | 23 | root.left = left 24 | 25 | if root.right: 26 | 27 | right = BTToDLLUtil(root.right) 28 | 29 | while right.left: 30 | right = right.left 31 | 32 | right.left = root 33 | 34 | root.right = right 35 | 36 | return root 37 | 38 | 39 | def BTToDLL(root): 40 | if root is None: 41 | return root 42 | 43 | root = BTToDLLUtil(root) 44 | 45 | while root.left: 46 | root = root.left 47 | 48 | return root 49 | 50 | 51 | def method1(head): 52 | 53 | if head is None: 54 | return 55 | while head: 56 | print(head.data, end=" ") 57 | head = head.right 58 | 59 | 60 | if __name__ == "__main__": 61 | """ 62 | from timeit import timeit 63 | 64 | root = Node(10) 65 | root.left = Node(12) 66 | root.right = Node(15) 67 | root.left.left = Node(25) 68 | root.left.right = Node(30) 69 | root.right.left = Node(36) 70 | 71 | head = BTToDLL(root) 72 | print(timeit(lambda: method1(head), number=10000)) # 0.05323586200393038 73 | """ 74 | -------------------------------------------------------------------------------- /J_linked_list/problems/E_reverse_in_group_of_size_k.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.next = None 5 | 6 | 7 | class LinkedList: 8 | def __init__(self): 9 | self.head = None 10 | 11 | def reverse(self, head, k): 12 | current = head 13 | next = None 14 | prev = None 15 | count = 0 16 | 17 | while current is not None and count < k: 18 | next = current.next 19 | current.next = prev 20 | prev = current 21 | current = next 22 | count += 1 23 | 24 | if next is not None: 25 | head.next = self.reverse(next, k) 26 | 27 | return prev 28 | 29 | def push(self, new_data): 30 | new_node = Node(new_data) 31 | new_node.next = self.head 32 | self.head = new_node 33 | 34 | def printList(self): 35 | temp = self.head 36 | while temp: 37 | print(temp.data) 38 | temp = temp.next 39 | 40 | 41 | if __name__ == "__main__": 42 | """ 43 | from timeit import timeit 44 | llist = LinkedList() 45 | llist.push(9) 46 | llist.push(8) 47 | llist.push(7) 48 | llist.push(6) 49 | llist.push(5) 50 | llist.push(4) 51 | llist.push(3) 52 | llist.push(2) 53 | llist.push(1) 54 | print(timeit(lambda: llist.printList(), number=10000)) # 0.35493226000107825 55 | llist.head = llist.reverse(llist.head, 3) 56 | print(timeit(lambda: llist.printList(), number=10000)) # 0.412117505000424 57 | """ 58 | -------------------------------------------------------------------------------- /K_stack/Z_stack.md: -------------------------------------------------------------------------------- 1 | # List of Contents 2 | 3 | - [Implementation](https://github.com/thisisshub/DSA/blob/main/K_stack/A_implementation.py) 4 | 5 | ## Infix, Prefix and Postfix 6 | - [Infix To Postfix](https://github.com/thisisshub/DSA/blob/main/K_stack/infix_prefix_and_postfix/A_infix_to_postfix.py) 7 | - [Evaluation Of Postfix](https://github.com/thisisshub/DSA/blob/main/K_stack/infix_prefix_and_postfix/B_evaluation_of_postfix.py) 8 | - [Infix To Prefix](https://github.com/thisisshub/DSA/blob/main/K_stack/infix_prefix_and_postfix/C_infix_to_prefix.py) 9 | - [Evaluation Of Prefix](https://github.com/thisisshub/DSA/blob/main/K_stack/infix_prefix_and_postfix/D_evaluation_of_prefix.py) 10 | 11 | ## Problems 12 | - [Balanced Parenthesis ](https://github.com/thisisshub/DSA/blob/main/K_stack/problems/A_balanced_parenthesis_.py) 13 | - [Two Stacks In An Array ](https://github.com/thisisshub/DSA/blob/main/K_stack/problems/B_two_stacks_in_an_array_.py) 14 | - [K Stacks In An Array ](https://github.com/thisisshub/DSA/blob/main/K_stack/problems/C_k_stacks_in_an_array_.py) 15 | - [Stock Span Problem With Variations](https://github.com/thisisshub/DSA/blob/main/K_stack/problems/D_stock_span_problem_with_variations.py) 16 | - [Previous Greater Element ](https://github.com/thisisshub/DSA/blob/main/K_stack/problems/E_previous_greater_element_.py) 17 | - [Next Greater Element](https://github.com/thisisshub/DSA/blob/main/K_stack/problems/F_next_greater_element.py) 18 | - [Largest Rectangular Area In A Histogram](https://github.com/thisisshub/DSA/blob/main/K_stack/problems/G_largest_rectangular_area_in_a_histogram.py) 19 | -------------------------------------------------------------------------------- /T_dynamic_programming/problems/edit_distance_problem/B_dp_approach.py: -------------------------------------------------------------------------------- 1 | def editDistDP(str1, str2, m, n): 2 | # Create a table to store results of subproblems 3 | dp = [[0 for x in range(n + 1)] for x in range(m + 1)] 4 | 5 | # Fill d[][] in bottom up manner 6 | for i in range(m + 1): 7 | for j in range(n + 1): 8 | 9 | # If first string is empty, only option is to 10 | # insert all characters of second string 11 | if i == 0: 12 | dp[i][j] = j # Min. operations = j 13 | 14 | # If second string is empty, only option is to 15 | # remove all characters of second string 16 | elif j == 0: 17 | dp[i][j] = i # Min. operations = i 18 | 19 | # If last characters are same, ignore last char 20 | # and recur for remaining string 21 | elif str1[i - 1] == str2[j - 1]: 22 | dp[i][j] = dp[i - 1][j - 1] 23 | 24 | # If last character are different, consider all 25 | # possibilities and find minimum 26 | else: 27 | dp[i][j] = 1 + min( 28 | dp[i][j - 1], dp[i - 1][j], dp[i - 1][j - 1] # Insert # Remove 29 | ) # Replace 30 | 31 | return dp[m][n] 32 | 33 | 34 | if __name__ == "__main__": 35 | """ 36 | from timeit import timeit 37 | 38 | str1 = "sunday" 39 | str2 = "saturday" 40 | 41 | print( 42 | timeit(lambda: editDistDP(str1, str2, len(str1), len(str2)), number=10000) 43 | ) # 0.21078211800340796 44 | """ 45 | -------------------------------------------------------------------------------- /N_tree/implementation/E_tree_traversal_in_spiral_form.py: -------------------------------------------------------------------------------- 1 | class newNode: 2 | def __init__(self, key): 3 | self.data = key 4 | self.left = None 5 | self.right = None 6 | 7 | 8 | def printSpiral(root): 9 | 10 | h = height(root) 11 | 12 | ltr = False 13 | for i in range(1, h + 1): 14 | 15 | printGivenLevel(root, i, ltr) 16 | 17 | ltr = not ltr 18 | 19 | 20 | def printGivenLevel(root, level, ltr): 21 | 22 | if root == None: 23 | return 24 | if level == 1: 25 | print(root.data, end=" ") 26 | elif level > 1: 27 | 28 | if ltr: 29 | printGivenLevel(root.left, level - 1, ltr) 30 | printGivenLevel(root.right, level - 1, ltr) 31 | 32 | else: 33 | printGivenLevel(root.right, level - 1, ltr) 34 | printGivenLevel(root.left, level - 1, ltr) 35 | 36 | 37 | def height(node): 38 | 39 | if node == None: 40 | return 0 41 | else: 42 | 43 | lheight = height(node.left) 44 | rheight = height(node.right) 45 | 46 | if lheight > rheight: 47 | return lheight + 1 48 | else: 49 | return rheight + 1 50 | 51 | 52 | if __name__ == "__main__": 53 | """ 54 | from timeit import timeit 55 | 56 | root = newNode(1) 57 | root.left = newNode(2) 58 | root.right = newNode(3) 59 | root.left.left = newNode(7) 60 | root.left.right = newNode(6) 61 | root.right.left = newNode(5) 62 | root.right.right = newNode(4) 63 | 64 | print(timeit(lambda: printSpiral(root), number=10000)) # 0.08272517399745993 65 | """ 66 | --------------------------------------------------------------------------------