├── .gitignore ├── Additional ├── HackerrankHacks │ └── README.md └── OtherMaterials │ └── README.md ├── Consultation ├── README.md └── Tasks │ ├── 1.cpp │ ├── 2.cpp │ ├── 3.cpp │ ├── 4.cpp │ └── 5.cpp ├── Exams ├── exam_03 │ ├── README.md │ ├── bonus │ │ ├── solution_inorder_map.cpp │ │ └── solution_inorder_rewrite.cpp │ ├── exam_03.png │ ├── task1 │ │ ├── solution_deque.cpp │ │ └── solution_reverse.cpp │ └── task2 │ │ └── solution_postorder.cpp ├── exam_04 │ ├── README.md │ └── Solutions │ │ ├── Task1 │ │ ├── leetcode_solution_one_map.cpp │ │ └── simple_onemap.cpp │ │ ├── Task2 │ │ ├── add-constant_findMax-linear.cpp │ │ └── add-logN_findMax-logN.cpp │ │ └── bonus │ │ ├── bottom_up_dp.cpp │ │ └── one_variable.cpp ├── exam_05 │ ├── README.md │ └── Solutions │ │ ├── Task1 │ │ └── pq.cpp │ │ └── Task2 │ │ ├── adjlist.cpp │ │ └── edgelist.cpp ├── exam_06 │ ├── README.md │ └── Solutions │ │ ├── bonus │ │ └── solution.py │ │ ├── task1_ad │ │ └── solution_dijkstra.py │ │ ├── task1_si │ │ ├── solution_bfs.cpp │ │ ├── solution_dijkstra.cpp │ │ └── solution_dijkstra.py │ │ └── task2 │ │ ├── solution_disjoint_set.cpp │ │ ├── solution_disjoint_set.py │ │ └── solution_prim.cpp └── exam_final │ ├── README.md │ ├── task1 │ └── solution_sort.py │ ├── task2 │ └── solution_bfs.py │ ├── task3 │ └── solution_sums.py │ ├── task4 │ └── solution_disjoint_set.py │ └── task5 │ └── solution_dp.py ├── Homeworks └── hw_02 │ ├── README.md │ ├── Task1.cpp │ ├── Task2.cpp │ └── Task3.cpp ├── README.md ├── Week_00 ├── Practicum │ └── README.md └── Seminar │ ├── DS │ ├── README.md │ └── Tasks │ │ ├── Solutions │ │ ├── Task1.cpp │ │ ├── Task2.cpp │ │ └── Task3.cpp │ │ └── readme.md │ ├── GT │ ├── Complexity │ │ ├── README.md │ │ └── WhatIsTheComplexity.cpp │ ├── HackerrankHacks │ │ └── README.md │ ├── Locality │ │ ├── IteratingMatrixRowsVsCols.cpp │ │ └── README.md │ ├── PerformanceTester.cpp │ ├── README.md │ ├── Revision │ │ ├── CopyRefRvalue.cpp │ │ ├── DataTypes.cpp │ │ ├── Pointer.cpp │ │ └── Recursion.cpp │ ├── STL_Structures_How_To │ │ ├── MyStringSSO │ │ │ ├── MyStringSSO.cpp │ │ │ ├── MyStringSSO.h │ │ │ └── README.md │ │ ├── Pair.cpp │ │ ├── RangeBaseFor.cpp │ │ ├── String.cpp │ │ ├── Tuple.cpp │ │ ├── Vector.cpp │ │ └── auto.cpp │ └── Solutions │ │ ├── Tickets.cpp │ │ └── TwoSum.cpp │ ├── README.md │ └── TK │ ├── README.md │ ├── roommates │ └── solution.cpp │ ├── simple_array_sum │ ├── solution_array.cpp │ └── solution_vector.cpp │ ├── solve_me_first │ └── solution.cpp │ └── two_sum │ ├── solution_map.cpp │ ├── solution_naive.cpp │ └── solution_two_pointers.cpp ├── Week_01 ├── Practicum │ ├── Convert an Array Into a 2D Array With Conditions.cpp │ ├── Find if Digit Game Can Be Won.cpp │ ├── Group People By Size.cpp │ ├── Jewels and Stones.cpp │ ├── Permutation Difference between Two Strings.cpp │ ├── README.md │ ├── python │ │ ├── Convert an Array Into a 2D Array With Conditions.py │ │ ├── Find if Digit Game Can Be Won.py │ │ ├── Group the People Given the Group Size They Belong To.py │ │ ├── Jewels and Stones.py │ │ └── Permutation Difference between Two Strings.py │ └── К │ │ ├── Convert an Array Into a 2D Array With Conditions.cpp │ │ └── Group the People Given the Group Size They Belong To.cpp └── Seminar │ ├── GT │ ├── README.md │ └── Solutions │ │ ├── ContainerWithMostWater.cpp │ │ ├── MissingBusTickerHard.cpp │ │ ├── MoveZeroes.cpp │ │ ├── NumberOfIslands.cpp │ │ ├── PlusOne.cpp │ │ ├── RotateArray.cpp │ │ ├── RotateImage.cpp │ │ ├── SingleNumber1.cpp │ │ └── SingleNumber2.cpp │ ├── README.md │ ├── TG │ └── complexity.ipynb │ └── TK │ ├── README.md │ ├── missing_bus_ticket │ ├── solution_counting.cpp │ └── solution_set.cpp │ ├── move_zeros │ ├── solution_custom_sort.cpp │ └── solution_linear.cpp │ ├── plus_one │ └── solution.cpp │ ├── rotate_image │ └── solution.cpp │ ├── single_number │ ├── solution_counting.cpp │ ├── solution_map.cpp │ ├── solution_set.cpp │ ├── solution_sort.cpp │ └── solution_xor.cpp │ └── water_supplies │ ├── solution_naive.cpp │ └── solution_two_pointers.cpp ├── Week_02 ├── Practicum │ ├── Contains Duplicate II.cpp │ ├── Contains Duplicate.cpp │ ├── Count of Smaller Numbers After Self.cpp │ ├── Majority Element II.cpp │ ├── Maximum Ice Cream Bars.cpp │ ├── Merge Intervals.cpp │ ├── Merge Sorted Array.cpp │ ├── Python │ │ ├── Contains Duplicate II.py │ │ ├── Contains Duplicate.py │ │ ├── Count of Smaller Numbers After Self.py │ │ ├── Majority Element II.py │ │ ├── Maximum Ice Cream Bars.py │ │ ├── Merge Intervals.py │ │ └── Merge Sorted Array.py │ └── Tasks.md └── Seminar │ ├── GT │ ├── README.md │ ├── Solutions │ │ ├── ContainsDuplicate.cpp │ │ ├── FindTheDifference.cpp │ │ ├── FindTheKthLargestIntegerinTheArray.cpp │ │ ├── IntersectionOfTwoArrays2.cpp │ │ ├── KthLargestElementInArray.cpp │ │ ├── Maximum-Product-Of-Three-Elements.cpp │ │ ├── MergeIntervals.cpp │ │ ├── MergeSortedArrays.cpp │ │ ├── NonOverlappingIntervals.cpp │ │ ├── SortCharactersByFrequency.cpp │ │ └── SquaresOfASortedArray.cpp │ └── naive │ │ ├── insertion.cpp │ │ └── mergesort.cpp │ ├── README.md │ ├── TG │ └── sorting.ipynb │ ├── TK │ ├── contains_duplicate │ │ ├── solution_map.cpp │ │ ├── solution_set.cpp │ │ └── solution_sort.cpp │ ├── find_the_difference │ │ ├── solution_counting.cpp │ │ └── solution_sort.cpp │ ├── first_missing_positive │ │ └── solution.cpp │ └── merge_sorted_arrays │ │ ├── solution_copy.cpp │ │ └── solution_inplace.cpp │ ├── all_sorts │ ├── bubble_sort.cpp │ ├── bubble_sort_comparisons.cpp │ ├── counting_sort.cpp │ ├── insertion_sort.cpp │ ├── merge_sort.cpp │ ├── quick_sort.cpp │ └── selection_sort.cpp │ └── stl_funcs.md ├── Week_03 ├── Practicum │ ├── Find First and Last Position of Element in Sorted Array.cpp │ ├── Find Minimum in Rotated Sorted Array II.cpp │ ├── First Bad Version.cpp │ ├── PythonAdditional │ │ ├── Find the Difference.py │ │ ├── Find the Index.py │ │ ├── Merge Strings Alternately.py │ │ ├── Repeated Substring Pattern.py │ │ ├── Sign of the Product of an Array.py │ │ ├── Tasks.md │ │ └── Valid Anagram.py │ ├── Quiz.md │ ├── Search a 2D Matrix II.cpp │ ├── Search in Rotated Sorted Array.cpp │ ├── Sqrt(x).cpp │ ├── Tasks.md │ └── Upper and Lower bound.cpp └── Seminar │ ├── README.md │ ├── Solutions │ ├── BinarySearch.cpp │ ├── BonusTasks │ │ ├── SearchInRotatedSortedArray.cpp │ │ └── SingleElementInASortedArray.cpp │ ├── FindFirstAndLastPositionOfElementInSortedArray.cpp │ ├── FirstBadVersion.cpp │ ├── PeekIndexInMountainArray │ │ ├── Binary.cpp │ │ └── Ternary.cpp │ ├── Puncakes.cpp │ ├── SafeSort │ │ ├── MergeSort.cpp │ │ └── StdSort.cpp │ ├── Search2DMatrix │ │ ├── BinaryBinary.cpp │ │ ├── JumpSearch.cpp │ │ └── OneBinary.cpp │ ├── SearchInsertPosition.cpp │ └── Sqrt.cpp │ └── all_searches │ ├── binary_search.cpp │ ├── exponential_search.cpp │ ├── jump_search.cpp │ ├── monotonic_function.cpp │ ├── pancakes_example.cpp │ └── ternary_search.cpp ├── Week_04 ├── Practicum │ ├── Flatten a Multilevel Doubly Linked List.cpp │ ├── Merge Two Sorted Lists.cpp │ ├── Merge k Sorted Lists.cpp │ ├── Middle of the Linked List.cpp │ ├── PythonAdditional │ │ ├── Arranging Coins.py │ │ ├── Binary Search.py │ │ ├── Find Right Interval.py │ │ ├── Find Smallest Letter_1.py │ │ ├── Find Smallest Letter_2.py │ │ ├── First Bad Version.py │ │ ├── Search Insert Position_1.py │ │ ├── Search Insert Position_2.py │ │ └── Tasks.md │ ├── Remove Linked List Elements.cpp │ ├── Reverse Linked List II.cpp │ └── Tasks.md └── Seminar │ ├── LinkedLists │ ├── DoublyLinkedList.hpp │ ├── SinglyLinkedList.hpp │ └── XORLinkedList.hpp │ ├── Python │ ├── delete-duplicate-value-nodes-from-a-sorted-linked-list.py │ ├── linkedlist.ipynb │ ├── merge-two-sorted-linked-lists.py │ └── reverse-linked-list.py │ ├── README.md │ └── Solutions │ ├── Bonus │ └── LinkedListCycle2.cpp │ ├── DeleteNodeInALinkedList.cpp │ ├── IntersectionOfTwoLinkedLists │ ├── WithLength.cpp │ └── WithoutLength.cpp │ ├── LinkedListCycle.cpp │ ├── MergeTwoSortedLists │ ├── Iterative.cpp │ └── Recursive.cpp │ ├── MiddleOfTheLinkedList.cpp │ ├── OddEvenLinkedList.cpp │ ├── PalindromeLinkedList.cpp │ ├── RemoveDuplicatesFromSortedList.cpp │ ├── RemoveNthNodeFromEndOfList.cpp │ └── ReverseLinkedList.cpp ├── Week_05 ├── Practicum │ ├── Asteroid Collision.cpp │ ├── Asteroid Collision.py │ ├── Next Greater Element II.cpp │ ├── Next Greater Element II.py │ ├── PythonAdditional │ │ ├── Convert Binary_1.py │ │ ├── Convert Binary_2.py │ │ ├── Delete Middle.py │ │ ├── Double a Number.py │ │ ├── Middle of the Linked List.py │ │ ├── Odd Even Linked List.py │ │ ├── Remove Duplicates from Sorted List.py │ │ ├── Remove Linked List Elements.py │ │ ├── Reverse Linked List.py │ │ └── Tasks.md │ ├── README.md │ ├── Removing Stars From a String.cpp │ ├── Removing Stars From a String.py │ ├── Shortest Unsorted Continuous Subarray.cpp │ ├── Shortest Unsorted Continuous Subarray.py │ ├── Sliding Window Maximum.cpp │ ├── Sliding Window Maximum.py │ ├── Trapping Rain Water.cpp │ ├── Trapping Rain Water.py │ ├── Valid Parentheses.cpp │ ├── Valid Parentheses.py │ └── media │ │ ├── blocks-1.png │ │ ├── blocks-2.png │ │ └── blocks-3.png └── Seminar │ ├── Implementations │ ├── Deque │ │ └── DequeList.hpp │ ├── Queue │ │ └── QueueArray.hpp │ └── Stack │ │ └── StackList.hpp │ ├── Python │ ├── backspace-string-compare-with-eq.py │ ├── backspace-string-compare-without-eq.py │ ├── baseball-game-with-list.py │ ├── baseball-game-with-stack.py │ ├── number-of-recent-calls.py │ ├── stack-and-queue.ipynb │ └── valid-parentheses.py │ ├── PythonAdditional │ ├── multidimensional_arrays.py │ ├── multidimensional_arrays_1.py │ ├── multidimensional_arrays_2.py │ └── strings_13.py │ ├── README.md │ └── Solutions │ ├── MonotonicStack │ ├── DailyTemperatures.cpp │ ├── NextGreaterElementInList.cpp │ └── WelcomeToTheJungle.cpp │ ├── QueueAndStack │ ├── AsteroidCollision.cpp │ ├── BackspaceStringComparer.cpp │ ├── BaseballGame.cpp │ ├── EvaluateReversePolishNotation.cpp │ ├── ImplementQueueUsingStacks.cpp │ ├── MaximumNestingDepthoftheParentheses.cpp │ ├── MinStack │ │ ├── 2NMemory.cpp │ │ └── NMemory.cpp │ ├── NumberOfRecentCalls.cpp │ ├── NumberOfStudentsUnableToEatLunch.cpp │ ├── RemoveAllAdjacentDuplicatesInString.cpp │ └── ValidParentheses.cpp │ └── SlidingWindow │ ├── MaximumAverageSubarray_array.cpp │ ├── MaximumAverageSubarray_queue.cpp │ └── SlindingWindowMaximum.cpp ├── Week_06 ├── Practicum │ ├── Binary Tree Level Order Traversal.cpp │ ├── Binary Tree Level Order Traversal.py │ ├── Binary Tree Preorder Traversal.cpp │ ├── Binary Tree Preorder Traversal.py │ ├── Binary Tree Right Side View.cpp │ ├── Binary Tree Right Side View.py │ ├── Contains Duplicate III.cpp │ ├── Contains Duplicate III.py │ ├── Maximum Depth of Binary Tree.cpp │ ├── Maximum Depth of Binary Tree.py │ ├── Maximum Depth of N-ary Tree.cpp │ ├── My Calendar I.cpp │ ├── My Calendar I.py │ ├── Path Sum III.cpp │ ├── Path Sum III.py │ ├── PythonAdditional │ │ └── Tasks.md │ ├── README.md │ ├── Stock Price Fluctuation.cpp │ ├── Stock Price Fluctuation.py │ ├── Tasks.md │ ├── Validate Binary Search Tree.py │ └── media │ │ ├── avl-double-rotation.png │ │ ├── avl-simple-rotation.png │ │ ├── red-black-tree.png │ │ └── unbalanced-avl-tree.png └── Seminar │ ├── Implementations │ ├── BST.hpp │ └── NOT_FULLY_TESTED_BST_WithDumbBidirectionalIterator.hpp │ ├── README.md │ └── Solutions │ ├── Bonus │ ├── BSTToGreaterTree.cpp │ └── TrimBST.cpp │ ├── Fundamentals │ ├── DeleteNodeInBST │ │ └── Solution.cpp │ ├── InsertIntoBST │ │ ├── Iterative.cpp │ │ └── Recusive.cpp │ ├── MaxDepthOfBinaryTree │ │ └── Recursive.cpp │ ├── SearchInBinaryTree │ │ ├── Iterative.cpp │ │ └── Recursive.cpp │ ├── Traversals │ │ ├── Inorder │ │ │ ├── Iterative.cpp │ │ │ └── Recursive.cpp │ │ ├── LevelOrder │ │ │ └── Solution.cpp │ │ ├── Postorder │ │ │ └── Recursive.cpp │ │ └── Preorder │ │ │ └── Recursive.cpp │ └── ValidateBST │ │ ├── ExtraSpace_Inorder.cpp │ │ └── IntervalChecks.cpp │ └── Other │ ├── RangeSum │ ├── LevelOrder.cpp │ └── Recursive.cpp │ ├── RightSideView │ ├── DfsInClassTest_Georgi.cpp │ └── LevelOrder.cpp │ ├── SameTree │ ├── Dfs.cpp │ └── InorderVector.cpp │ └── SymetricTree.cpp ├── Week_07 ├── Practicum │ ├── Climbing Stairs.cpp │ ├── Climbing Stairs.py │ ├── Guess Number Higher or Lower II.cpp │ ├── Longest Increasing Subsequence.cpp │ ├── Longest Increasing Subsequence.py │ ├── Min Cost Climbing Stairs.cpp │ ├── Min Cost Climbing Stairs.py │ ├── PythonAdditional │ │ ├── Average of Levels in Binary Tree.py │ │ ├── Deepest Leaves Sum.py │ │ ├── Employee Importance.py │ │ ├── Invert Binary Tree.py │ │ ├── Maximum Level Sum of a Binary Tree.py │ │ ├── Merge Two Binary Trees.py │ │ ├── Minimum Distance Between BST Nodes.py │ │ ├── Sum of Left Leaves.py │ │ └── Tasks.md │ ├── Tasks.md │ ├── Unique Paths II.cpp │ ├── Unique Paths II.py │ ├── Unique Paths III.cpp │ ├── Unique Paths.cpp │ └── Unique Paths.py └── Seminar │ ├── README.md │ └── Solutions │ ├── Lab │ ├── Fibonacci │ │ ├── BottomUpApproach.cpp │ │ └── TopDownApproach.cpp │ ├── HouseRobber │ │ ├── ConstantMemory.cpp │ │ └── DpArray.cpp │ ├── LCS │ │ └── Solution.cpp │ └── UniquePaths2 │ │ ├── Matrix.cpp │ │ └── OnlyOneRow.cpp │ ├── Lecture │ ├── CoinChecker │ │ └── Solution.cpp │ ├── LIS │ │ └── Solution.cpp │ └── MinimumPathSum │ │ └── UsingTheInputAsDP.cpp │ └── Other │ ├── ClimbingStairs │ └── Solution.cpp │ ├── JumpGame │ └── Solution.cpp │ ├── MinCostClimbingStairs │ └── Solutions.cpp │ └── Tribonacci │ └── Solution.cpp ├── Week_08 ├── Practicum │ ├── 3Sum.cpp │ ├── 3Sum.py │ ├── Distinct Echo Substrings.cpp │ ├── Distribute Candies.cpp │ ├── Distribute Candies.py │ ├── Find Occurrences of an Element in an Array.cpp │ ├── Find Occurrences of an Element in an Array.py │ ├── Find Unique Binary String.cpp │ ├── Find Unique Binary String.py │ ├── Longest Common Subpath.cpp │ ├── Longest Happy Prefix.cpp │ ├── Maximum Equal Frequency.cpp │ ├── Maximum Erasure Value.cpp │ ├── Maximum Erasure Value.py │ ├── Maximum Length of Repeated Subarray.cpp │ ├── Shortest Impossible Sequence of Rolls.cpp │ ├── Shortest Impossible Sequence of Rolls.py │ ├── Tasks.md │ ├── Two Sum.cpp │ └── Two Sum.py └── Seminar │ ├── Examples │ ├── HashMapWithCustomStructAsKey.cpp │ ├── MultiMapExample.cpp │ └── OrderedMapWithCustomStructAsKey.cpp │ ├── HelpingExplanations.md │ ├── README.md │ └── Solutions │ ├── 0-1_subarray │ ├── SumZero.cpp │ └── solution_sum_zero.py │ ├── contains_duplicate_ii │ ├── solution_dict.py │ ├── solution_set.py │ └── solution_unordered_map.cpp │ ├── count_number_of_bad_pairs │ ├── solution_dict.py │ └── solution_unordered_map.cpp │ ├── group_anagrams │ ├── solution_counting.py │ ├── solution_custom_hash.cpp │ ├── solution_sort.cpp │ └── solution_sort.py │ ├── k-diff_pairs_in_an_array │ ├── solution_hashmap.cpp │ ├── solution_sets.py │ ├── solution_two_hashmaps.cpp │ └── solution_two_sets.cpp │ ├── longest_consecutive_sequence │ ├── solution_set.py │ ├── solution_set_pop.py │ ├── solution_sort.py │ └── unordered_set.cpp │ ├── longest_substring_without_repeating_chars │ └── unordered_map.cpp │ ├── repeated_dna_sequences │ ├── rollinghash.cpp │ ├── solution_counting.py │ ├── solution_rolling_hash.py │ ├── solution_set.py │ └── two_set_solution.cpp │ ├── subarray_sum_equals_k │ ├── solution_dict.py │ └── solution_unordered_map.cpp │ └── volleyball_friends │ ├── solution_set.cpp │ └── solution_set.py ├── Week_09 ├── Practicum │ ├── Find Median from Data Stream.cpp │ ├── Find Median from Data Stream.py │ ├── Kth Largest Element in a Stream.cpp │ ├── Kth Largest Element in a Stream.py │ ├── Merge k Sorted Lists.cpp │ ├── PythonAdditional │ │ ├── Remove Stones to Minimize the Total.py │ │ ├── Seat Reservation Manager.py │ │ └── Tasks.md │ ├── Relative Ranks.cpp │ ├── Relative Ranks.py │ ├── Task Scheduler.cpp │ ├── Tasks.md │ ├── The Number of the Smallest Unoccupied Chair.cpp │ ├── The Number of the Smallest Unoccupied Chair.py │ └── Магазин за Баници.cpp └── Seminar │ ├── README.md │ └── Solutions │ ├── banitsa_shop │ ├── solution_heapq.py │ ├── solution_pairs_no_comparators.cpp │ ├── solution_pq.py │ └── solution_struct_with_comparators.cpp │ ├── find_median_from_data_stream │ └── two_pq.cpp │ ├── find_the_running_median │ ├── bad_solution_median.py │ └── solution_two_pq.py │ ├── gym │ ├── pq_ends.cpp │ ├── solution_two_pqs.cpp │ └── solution_two_pqs_comparators.cpp │ ├── jesse_and_cookies │ ├── solution_heapq.py │ ├── solution_pq.cpp │ └── solution_pq.py │ ├── k_closests_points_to_origin │ └── priority_queue.cpp │ ├── kth_largest_element │ ├── solution_heapq.py │ ├── solution_heapq_negative.py │ ├── solution_make_heap.cpp │ ├── solution_pq.cpp │ ├── solution_pq.py │ ├── solution_pq_negative.py │ └── solution_sort.py │ ├── last_stone_weight │ └── priority_queue.cpp │ ├── maximal_score_after_k_operations │ ├── solution_heapq_negative.py │ ├── solution_heapq_order.py │ ├── solution_make_heap.cpp │ ├── solution_pq_negative.py │ └── solution_pq_order.py │ ├── merge_k_sorted_lists │ ├── pq_with_all_elements.cpp │ └── pq_with_k_elements.cpp │ ├── single_threaded_cpu │ └── solution.cpp │ └── task_scheduler │ └── solution.cpp ├── Week_10 ├── Practicum │ ├── Count the Number of Complete Components.cpp │ ├── Count the Number of Complete Components.py │ ├── Course Schedule II.cpp │ ├── Course Schedule II.py │ ├── Find Center of Star Graph.cpp │ ├── Find Center of Star Graph.py │ ├── Find Champion II.cpp │ ├── Find Champion II.py │ ├── Find The Town Judge.py │ ├── Find if Path Exists in Graph.cpp │ ├── Find if Path Exists in Graph.py │ ├── Find the Town Judge.cpp │ ├── Keys and Rooms.cpp │ ├── Keys and Rooms.py │ ├── Number of Provinces.cpp │ ├── Number of Provinces.py │ ├── Remove Methods From Project.py │ └── Tasks.md └── Seminar │ ├── Examples │ ├── bfs.cpp │ ├── dfs.cpp │ ├── python_playground.ipynb │ └── topologicalSort.cpp │ ├── README.md │ ├── Solutions │ ├── all_paths_from_source_to_target │ │ └── solutions_dfs.cpp │ ├── breadth_first_search_shortest_reach │ │ ├── solution_bfs.cpp │ │ └── solution_bfs.py │ ├── clone_graph │ │ └── solution_umap.cpp │ ├── count_of_areas │ │ ├── solution_bfs.cpp │ │ ├── solution_bfs.py │ │ ├── solution_dfs_recursive.cpp │ │ ├── solution_dfs_recursive.py │ │ ├── solution_dfs_stack.cpp │ │ └── solution_dfs_stack.py │ ├── course_shedule_ii │ │ ├── solution_topological_bfs.cpp │ │ ├── solution_topological_bfs.py │ │ ├── solution_topological_dfs_with_cycle_check.cpp │ │ └── solution_topological_with_cycle_checking.cpp │ ├── cyclic_graph │ │ ├── solution_coloring.cpp │ │ ├── solution_coloring.py │ │ ├── solution_two_sets.cpp │ │ ├── solution_two_sets_default_dict.py │ │ └── solutions_two_sets_ordinary_dict.py │ ├── find_the_celebrity │ │ ├── brute_force.cpp │ │ └── smart_linear.cpp │ ├── find_the_town_judge │ │ ├── in_and_out_degree.cpp │ │ └── potential_array.cpp │ ├── possible_bipartition │ │ └── bfs_with_coloring.cpp │ └── remove_edges │ │ └── solution_dfs.cpp │ └── media │ ├── directed_graph.png │ ├── graph_example.png │ ├── graph_for_traversing.png │ └── undirected_graph.png ├── Week_11 ├── Practicum │ ├── Get Watched Videos by Your Friends.cpp │ ├── Path with Maximum Probability.cpp │ ├── Path with Maximum Probability.py │ ├── Reachable Nodes In Subdivided Graph.cpp │ ├── Shortest paths.cpp │ ├── Shortest paths.py │ ├── Tasks.md │ ├── Two Sets.cpp │ └── Two Sets.py └── Seminar │ ├── Examples │ └── playground_11.ipynb │ ├── README.md │ ├── Solutions │ ├── cheapest_flights_within_k_stops │ │ └── solution_bellman-ford.cpp │ ├── dijkstra_shortest_reach_2 │ │ ├── dijkstra_solution_GT.cpp │ │ ├── solution_dijkstra.py │ │ └── solution_dijkstra_TK.cpp │ ├── floyd_city_of_blinding_lights │ │ └── solution_floyd.py │ ├── long_long │ │ ├── solution_bellman_ford.py │ │ ├── solution_bellman_ford_GT.cpp │ │ ├── solution_bellman_ford_adjacency_list.py │ │ ├── solution_bellman_ford_max.py │ │ └── solution_broken_dijkstra.py │ ├── minimum_cost_to_make_at_least_one_valid_path │ │ └── solution_dijkstra.cpp │ ├── minimum_obstacles_removal_to_reach_corner │ │ └── solution_dijkstra_GT.cpp │ ├── network_delay_time │ │ ├── solution_dijkstra.py │ │ ├── solution_dijkstra_GT.cpp │ │ └── solution_dijkstra_TK.cpp │ ├── path_with_maximum_probability │ │ ├── solution_dijkstra.py │ │ ├── solution_dijkstra_GT.cpp │ │ └── solution_dijkstra_TK.cpp │ └── path_with_minimum_effort │ │ └── solution_dijkstra_GT.cpp │ └── media │ ├── dijkstra_negative_edge_graph.png │ └── dijkstra_undirected_graph.png ├── Week_12 ├── Practicum │ ├── Cleaning.py │ ├── Find if Path Exists in Graph.cpp │ ├── Find if Path Exists in Graph.py │ ├── Kruskal_MST.py │ ├── Kruskal_MST_Really_Special_Subtree.cpp │ ├── Min Cost to Connect All Points.cpp │ ├── Tasks.md │ ├── Почистване.cpp │ └── Скорости.cpp └── Seminar │ ├── README.md │ ├── Solutions │ ├── find_critical_and_pseudo_critical_edges │ │ └── kruskal_with_and_without_every_edge.cpp │ ├── hamiltonian_path.cpp │ ├── kruskals_really_special_subtree │ │ ├── solution_kruskal_best.py │ │ ├── solution_kruskal_better.py │ │ ├── solution_kruskal_medium.py │ │ ├── solution_kruskal_worst.py │ │ └── solution_prim.py │ ├── min_cost_to_connect_all_points │ │ └── prim.cpp │ ├── number_of_provinces │ │ └── kruskal.cpp │ ├── optimize_water_supply │ │ └── addingDummyNode.cpp │ └── prims_special_subtree │ │ ├── solution_kruskal.py │ │ ├── solution_prim.py │ │ └── solution_prim_hardcoded_start.cpp │ ├── UnionFind │ ├── UnionFind.cpp │ └── UnionFind.h │ ├── media │ ├── kruskals_algorithm_example.png │ ├── minimum_spanning_trees.png │ ├── mst_vs_dijkstra.png │ ├── prims_algorithm_example.png │ ├── spanning_trees.png │ └── weighted_graph.png │ └── playground_12.ipynb └── Week_13 ├── Practicum ├── 01. Sorting Algorithms │ ├── Kontrolno 1 2020-2021 │ │ └── repeating_numbers.cpp │ └── Kontrolno 1 2023-2024 │ │ └── zadacha_01.cpp ├── 02. Binary Search │ ├── binary_search.cpp │ ├── find_el.cpp │ └── puncakes.cpp ├── 03. Linked List │ ├── linked_numbers.cpp │ └── reverse_linked_list.cpp ├── 04. Stack & Queue │ └── max_sliding_window.cpp ├── 05. Trees │ ├── convert_to_bst.cpp │ ├── left_view.cpp │ └── penultimate_descendants.cpp ├── 06. Heap │ └── maintenance.cpp ├── 07. Hash │ ├── anagram.cpp │ ├── dundee_the_crocodile.cpp │ ├── roman.cpp │ └── subarray.cpp ├── 08. Graphs │ ├── check_paths.cpp │ ├── cycles_in_graph.cpp │ ├── detect_cycle.cpp │ ├── green_school.cpp │ ├── holiday.cpp │ ├── path_in_graph.cpp │ ├── remove_edges.cpp │ ├── santa_claus.cpp │ └── shortest_tour.cpp └── Tasks.md └── Seminar ├── README.md ├── Solutions ├── Bonus │ ├── add_and_search_words │ │ ├── solution.cpp │ │ └── string_view.cpp │ └── implement_trie │ │ ├── array.cpp │ │ └── unordered_map.cpp ├── all_paths_from_source_to_target │ ├── cpp_solution_backtracking.cpp │ └── solution_backtracking.py ├── permutations │ ├── cpp_solution_backtracking.cpp │ ├── solution_backtracking.py │ └── solution_itertools.py ├── reconstruct_itinerary │ ├── solution_euler.py │ └── solution_euler_path.cpp └── the_islander │ └── solution_euler_dfs.py └── media ├── complex_eulerian_path_and_cycle.png ├── eulerian_path_famous.png ├── eulerian_path_simple.png ├── hamiltonian_path_and_cycle.png └── simple_eulerian_path_and_cycle.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | .vscode -------------------------------------------------------------------------------- /Additional/OtherMaterials/README.md: -------------------------------------------------------------------------------- 1 | ## [Домашни и контролни през годините](https://docs.google.com/document/d/1W0gjdUR_aEuCiyCnP8njMuswomJlZle6riAu0BaE038) 2 | 3 | ## Quizes for revision 4 | - [Part 1](https://create.kahoot.it/share/sda-recap-part-1/d4964f5d-c033-47d2-a33f-14ca5cef0697) 5 | - [Part 2](https://create.kahoot.it/share/sda-recap-part-2/c5b1bf39-35ed-46d2-9985-706d7a096182) -------------------------------------------------------------------------------- /Consultation/README.md: -------------------------------------------------------------------------------- 1 | # Консултация 27.01.2025 2 | 3 | ## Преговор на теория 4 | 5 | ## Задачи 6 | - [Премахване на ребра](https://www.hackerrank.com/contests/sda-test5-2022-2023-43wdst52/challenges/challenge-1761) 7 | - [Много МПД-ата](https://www.hackerrank.com/contests/2023-2024-2/challenges/components-mst-k) 8 | - [Оцветяване на дърво](https://www.hackerrank.com/contests/2023-2024-2/challenges/challenge-4607) 9 | - [Най-кратка поредица от пътища](https://www.hackerrank.com/contests/sda-exam-20222023-part-2/challenges/--152/problem) 10 | - [Най-продаван артикул](https://www.hackerrank.com/contests/sda-exam-20222023-part-2/challenges/challenge-3881) 11 | -------------------------------------------------------------------------------- /Exams/exam_03/README.md: -------------------------------------------------------------------------------- 1 | ## Exam 03 2 | 3 | ![Exam statement](exam_03.png) 4 | 5 | ### Task 1 6 | Can be found in Leetcode: [Binary Tree Zigzag Level Order Traversal](https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal) 7 | 8 | Input tree: `[8, 3, 10, 1, 6, null, 14, null, null, 4, 7, 13]` 9 | -------------------------------------------------------------------------------- /Exams/exam_03/bonus/solution_inorder_rewrite.cpp: -------------------------------------------------------------------------------- 1 | // We can not return the result with one inorder traversal, 2 | // because the height of right subtree is still unkown at the time of print 3 | int dfs(TreeNode *root, const int depth) 4 | { 5 | if (!root) 6 | { 7 | return 0; 8 | } 9 | int left_depth = dfs(root->left, depth + 1); 10 | int right_depth = dfs(root->right, depth + 1); 11 | 12 | int max_depth = std::max({depth, left_depth, right_depth}); 13 | root->val = max_depth; 14 | 15 | return std::max(left_depth, right_depth) + 1; 16 | } 17 | 18 | void print_inorder(TreeNode *root) 19 | { 20 | if (!root) 21 | { 22 | return; 23 | } 24 | print_inorder(root->left); 25 | std::cout << root->val << " "; 26 | print_inorder(root->right); 27 | } 28 | 29 | void main(TreeNode *root) 30 | { 31 | dfs(root, 0); 32 | print_inorder(root); 33 | 34 | return; 35 | } -------------------------------------------------------------------------------- /Exams/exam_03/exam_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Exams/exam_03/exam_03.png -------------------------------------------------------------------------------- /Exams/exam_03/task2/solution_postorder.cpp: -------------------------------------------------------------------------------- 1 | int dfs(TreeNode *root, const int depth = 0) 2 | { 3 | if (!root) 4 | { 5 | return 0; 6 | } 7 | int left_depth = dfs(root->left, depth + 1); 8 | int right_depth = dfs(root->right, depth + 1); 9 | 10 | int max_depth = std::max({depth, left_depth, right_depth}); 11 | std::cout << max_depth << " "; 12 | 13 | return std::max(left_depth, right_depth) + 1; 14 | } -------------------------------------------------------------------------------- /Exams/exam_04/Solutions/Task1/simple_onemap.cpp: -------------------------------------------------------------------------------- 1 | void intersect(vector& nums1, vector& nums2) { 2 | // for making space complexity O(min(n, m)) 3 | // where n is the size of nums1 4 | // m of nums2 5 | if (nums1.size() > nums2.size()) { 6 | return intersect(nums2, nums1); 7 | } 8 | 9 | unordered_map counter; 10 | for (auto n : nums1) { 11 | counter[n]++; 12 | } 13 | 14 | for (auto n : nums2) { 15 | auto it = counter.find(n); 16 | if (it != counter.end() && it->second > 0) { 17 | it->second--; 18 | cout << it->first << " "; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Exams/exam_04/Solutions/bonus/bottom_up_dp.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool canJump(vector& nums) { 4 | // dp if position can be reached 5 | vector dp(nums.size(), false); 6 | dp[0] = true; 7 | for(size_t i = 0; i < nums.size(); i++) { 8 | if(!dp[i]) { // this position can't be reached 9 | return false; 10 | } 11 | int furthestJump = min(i + nums[i], nums.size() - 1); 12 | // mark all possible jumps 13 | for(int j = furthestJump; j >= i; j--) { 14 | // if j is marked => j-1 is marked => linear solution, we mark each dp only once 15 | if(dp[j]) { 16 | break; 17 | } 18 | dp[j] = true; 19 | } 20 | } 21 | 22 | return dp[nums.size() - 1]; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /Exams/exam_04/Solutions/bonus/one_variable.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool canJump(vector& nums) { 4 | int maxReach = 0; 5 | for(int i = 0; i < nums.size(); i++) { 6 | if(maxReach < i) { 7 | return false; 8 | } 9 | maxReach = max(maxReach, i + nums[i]); 10 | } 11 | return true; 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /Exams/exam_05/Solutions/Task1/pq.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | int n, k; 7 | std::cin >> n >> k; 8 | std::unordered_map m; 9 | for(int i = 0; i < n; i++) { 10 | int x; 11 | std::cin >> x; 12 | m[x]++; 13 | } 14 | 15 | std::priority_queue> pq; 16 | for(auto& i : m) { 17 | pq.push({i.second, i.first}); 18 | } 19 | 20 | while(k--) { 21 | if(pq.empty()) { 22 | return 0; 23 | } 24 | auto t = pq.top(); 25 | pq.pop(); 26 | std::cout << t.second << std::endl; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Exams/exam_05/Solutions/Task2/adjlist.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | int towns, roads; 6 | std::cin >> towns >> roads; 7 | // key: from 8 | // value: key: to, value: weight 9 | std::unordered_map> townMap; 10 | 11 | for(int i = 0; i < roads; i++) { 12 | int from, to, weight; 13 | std::cin >> from >> to >> weight; 14 | if(townMap.find(from) == townMap.end()) { 15 | townMap[from][to] = INT_MAX; 16 | townMap[to][from] = INT_MAX; 17 | } 18 | townMap[from][to] = std::min(townMap[from][to], weight); 19 | townMap[to][from] = std::min(townMap[to][from], weight); 20 | } 21 | 22 | int start, end; 23 | std::cin >> start >> end; 24 | if(townMap[start].find(end) == townMap[start].end()) { 25 | std::cout << -1 << std::endl; 26 | return 0; 27 | } 28 | 29 | std::cout << townMap[start][end] << std::endl; 30 | } 31 | -------------------------------------------------------------------------------- /Exams/exam_05/Solutions/Task2/edgelist.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Edge { 5 | int from, to, weight; 6 | }; 7 | 8 | int main() { 9 | int towns, roads; 10 | std::cin >> towns >> roads; 11 | std::vector edges; 12 | 13 | for(int i = 0; i < roads; i++) { 14 | Edge edge; 15 | std::cin >> edge.from >> edge.to >> edge.weight; 16 | edges.push_back(edge); 17 | } 18 | 19 | int start, end; 20 | std::cin >> start >> end; 21 | 22 | int minWeight = INT_MAX; 23 | for (int i = 0; i < edges.size(); i++) { 24 | if(edges[i].from == start && edges[i].to == end) { 25 | minWeight = std::min(minWeight, edges[i].weight); 26 | } 27 | } 28 | 29 | if(minWeight == INT_MAX) { 30 | std::cout << -1 << std::endl; 31 | } else { 32 | std::cout << minWeight << std::endl; 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /Exams/exam_06/README.md: -------------------------------------------------------------------------------- 1 | ## [Exam06 - SE](https://www.hackerrank.com/gtkd5-20242025) 2 | ## [Exam06 - DA](https://www.hackerrank.com/gtkd6-20242025) -------------------------------------------------------------------------------- /Exams/exam_06/Solutions/task1_si/solution_bfs.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Exams/exam_06/Solutions/task1_si/solution_bfs.cpp -------------------------------------------------------------------------------- /Exams/exam_06/Solutions/task2/solution_disjoint_set.py: -------------------------------------------------------------------------------- 1 | def find(x): 2 | if x == parent[x]: 3 | return x 4 | 5 | root = find(parent[x]) 6 | parent[x] = root 7 | return root 8 | 9 | 10 | def union_(x, y): 11 | root_x = find(x) 12 | root_y = find(y) 13 | 14 | parent[root_x] = root_y 15 | 16 | 17 | v, e = map(int, input().split()) 18 | 19 | edges = [] 20 | parent = [i for i in range(v + 1)] 21 | for _ in range(e): 22 | x, y, w = map(int, input().split()) 23 | edges.append((x, y, w)) 24 | 25 | edges.sort(key=lambda el: -el[2]) 26 | val = 0 27 | comps = v 28 | 29 | for x, y, w in edges: 30 | if not (find(x) == find(y)): 31 | union_(x, y) 32 | val += w 33 | comps -= 1 34 | if comps == 0: 35 | break 36 | print(f"{comps} {val}") 37 | -------------------------------------------------------------------------------- /Exams/exam_final/README.md: -------------------------------------------------------------------------------- 1 | ## [Final Exam](https://www.hackerrank.com/contests/2024-2025-2/challenges) -------------------------------------------------------------------------------- /Exams/exam_final/task1/solution_sort.py: -------------------------------------------------------------------------------- 1 | N = int(input()) 2 | inputs = [(i, list(map(int, input().split()))) for i in range(1, N + 1)] 3 | inputs.sort(key=lambda value: ((value[1][0] * value[1][0]) / value[1][1], value[1][0]), reverse=True) 4 | 5 | output = [value[0] for value in inputs] 6 | print(*output) 7 | -------------------------------------------------------------------------------- /Exams/exam_final/task3/solution_sums.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | N, K = map(int, input().split()) 4 | zones = [int(input()) for _ in range(N)] 5 | 6 | m = defaultdict(lambda: [0, 0]) # Cumsum -> ways to get there, earliest index 7 | m[0] = [1, 0] # We can get to 0 cum_sum in 1 way, it is starting from index 0 8 | cum_sum = 0 9 | 10 | groups = 0 11 | max_group = 0 12 | 13 | 14 | for i, zone in enumerate(zones): 15 | cum_sum += zone 16 | m[cum_sum][0] += 1 17 | 18 | if m[cum_sum][1] == 0: # If it is the first time 19 | m[cum_sum][1] = i 20 | 21 | if m[cum_sum - K][0] > 0: # If there is the sum needed 22 | groups += m[cum_sum - K][0] 23 | max_group = max(i - m[cum_sum - K][1], max_group) 24 | 25 | 26 | if groups == 0: 27 | print(-1) 28 | else: 29 | print(max_group, groups) 30 | -------------------------------------------------------------------------------- /Exams/exam_final/task5/solution_dp.py: -------------------------------------------------------------------------------- 1 | s1 = input() 2 | s2 = input() 3 | m, n = len(s1), len(s2) 4 | 5 | dp = [[0] * (n + 1) for _ in range(m + 1)] 6 | 7 | for i in range(1, m + 1): 8 | for j in range(1, n + 1): 9 | if s1[i - 1] == s2[j - 1]: 10 | dp[i][j] = dp[i - 1][j - 1] + 1 11 | else: 12 | dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) 13 | 14 | print(dp[m][n]) 15 | -------------------------------------------------------------------------------- /Homeworks/hw_02/README.md: -------------------------------------------------------------------------------- 1 | https://www.hackerrank.com/contests/sda-24-25-2/challenges 2 | 3 | Третата задача е всъщност добре позната задача - https://leetcode.com/problems/split-array-largest-sum/ 4 | -------------------------------------------------------------------------------- /Week_00/Practicum/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_00/Practicum/README.md -------------------------------------------------------------------------------- /Week_00/Seminar/DS/Tasks/Solutions/Task1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | 9 | int main() { 10 | int n, k; 11 | cin >> n >> k; 12 | vector v(n); 13 | 14 | for(int i = 0; i < n; i++) 15 | { 16 | cin >> v[i]; 17 | } 18 | 19 | for(int i = 0; i < v.size(); i++) 20 | { 21 | if(v[i] == k) 22 | { 23 | v.erase(v.begin() + i); 24 | i--; 25 | } 26 | } 27 | 28 | for(int i = 0; i < v.size(); i++) 29 | cout << v[i] << " "; 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /Week_00/Seminar/DS/Tasks/Solutions/Task2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | 9 | int main() { 10 | int n; 11 | cin >> n; 12 | vector v(n); 13 | 14 | for(int i = 0; i < n; i++) 15 | { 16 | cin >> v[i]; 17 | } 18 | 19 | for(int i = v.size() - 1; i >= 0; i--) { 20 | v[i] += 1; 21 | if(v[i] < 10) { 22 | break; 23 | } 24 | 25 | v[i] = 0; 26 | } 27 | 28 | if(v[0] == 0) { 29 | v.insert(v.begin(), 1); 30 | } 31 | 32 | for(auto it = v.begin(); it != v.end(); it++) 33 | cout << *it; 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /Week_00/Seminar/DS/Tasks/Solutions/Task3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | 9 | int main() { 10 | int n, k; 11 | cin >> n >> k; 12 | vector> v; 13 | 14 | for(int i = 0; i < n; i++) { 15 | pair p; 16 | cin >> p.first; 17 | p.second = i; 18 | v.push_back(p); 19 | } 20 | 21 | sort(v.begin(), v.end()); 22 | 23 | int beg = 0; 24 | int end = v.size() - 1; 25 | 26 | while(beg != end) { 27 | int currSum = v[beg].first + v[end].first; 28 | 29 | if(currSum == k) { 30 | cout << v[beg].second << " " << v[end].second; 31 | break; 32 | } 33 | 34 | if(currSum > k) 35 | end--; 36 | else 37 | beg++; 38 | } 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /Week_00/Seminar/DS/Tasks/readme.md: -------------------------------------------------------------------------------- 1 | https://www.hackerrank.com/sem1 2 | -------------------------------------------------------------------------------- /Week_00/Seminar/GT/Complexity/README.md: -------------------------------------------------------------------------------- 1 | https://devopedia.org/algorithmic-complexity 2 | -------------------------------------------------------------------------------- /Week_00/Seminar/GT/Complexity/WhatIsTheComplexity.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void whatIsTheComplexity(int n) { 5 | for (size_t i = 0; i < n; i++) { 6 | for (size_t j = i + 1; j < n; j++) { 7 | if (j == i + 3) { 8 | break; 9 | i += 2; 10 | } 11 | } 12 | } 13 | } 14 | 15 | int main() { 16 | } -------------------------------------------------------------------------------- /Week_00/Seminar/GT/Locality/README.md: -------------------------------------------------------------------------------- 1 | # Locality 2 | 3 | https://www.geeksforgeeks.org/locality-of-reference-and-cache-operation-in-cache-memory/ -------------------------------------------------------------------------------- /Week_00/Seminar/GT/PerformanceTester.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | std::chrono::duration measureTime(void(*testedFunction)()) { 6 | auto start = std::chrono::steady_clock::now(); 7 | testedFunction(); 8 | auto end = std::chrono::steady_clock::now(); 9 | return (end - start); 10 | } 11 | 12 | void printMeasuredTime(void(*testedFunction)()) { 13 | auto elapsedTime = measureTime(testedFunction); 14 | std::cout << "Time taken: " << elapsedTime.count() << " seconds" << std::endl; 15 | } 16 | 17 | int main() { 18 | printMeasuredTime([]() { 19 | // sleep for 1 second 20 | // printed time will be > 1 second! 21 | // this is not 100% reliable because there are other 22 | // processes on your computer 23 | std::this_thread::sleep_for(std::chrono::milliseconds(1000)); 24 | }); 25 | } -------------------------------------------------------------------------------- /Week_00/Seminar/GT/STL_Structures_How_To/MyStringSSO/README.md: -------------------------------------------------------------------------------- 1 | # Small string optimization - implementation from OOP 2022/2023 2 | 3 | Idea if the length of the string is less than sizeof(pointer) + sizeof(length) => then use the allocated 4 | bytes for the pointer and for the length to store the string. Otherwise allocate on the heap. -------------------------------------------------------------------------------- /Week_00/Seminar/GT/STL_Structures_How_To/Tuple.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | // like a pair but can hold more elements 6 | std::tuple t(1, 2.5, 'c'); 7 | // std::make_tuple; 8 | // set 9 | std::get<0>(t) = 10; 10 | // get 11 | std::cout << std::get<0>(t) << std::endl; 12 | // t.swap - swap two tuples 13 | // auto [a, b, c] = t; - c++ 17 14 | } -------------------------------------------------------------------------------- /Week_00/Seminar/GT/STL_Structures_How_To/auto.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // it can also be a return type 5 | auto f() { 6 | return 1; 7 | } 8 | 9 | int main() { 10 | // The auto keyword directs the compiler to use the initialization expression of a declared variable, 11 | // or lambda expression parameter, to deduce its type. 12 | // Useful for iterators, lambdas, and complex types. 13 | // https://learn.microsoft.com/en-us/cpp/cpp/auto-cpp?view=msvc-170#remarks 14 | auto v1 = std::vector(100, 0); 15 | auto v2 = v1; 16 | 17 | auto member = v1[0]; 18 | f(); 19 | } -------------------------------------------------------------------------------- /Week_00/Seminar/GT/Solutions/Tickets.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | bool numbersCounter[10000000 + 1]{}; 9 | 10 | int main() { 11 | size_t count; 12 | std::cin >> count; 13 | 14 | int current; 15 | for(size_t i = 0; i < count; i++) { 16 | std::cin >> current; 17 | if(current > 0) { 18 | numbersCounter[current] = true; 19 | } 20 | } 21 | 22 | size_t missingNumber = count + 1; 23 | for(size_t i = 1; i <= count; i++) { 24 | if(!numbersCounter[i]) { 25 | missingNumber = i; 26 | break; 27 | } 28 | } 29 | std::cout << missingNumber; 30 | } -------------------------------------------------------------------------------- /Week_00/Seminar/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_00/Seminar/README.md -------------------------------------------------------------------------------- /Week_00/Seminar/TK/roommates/solution.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int Q, len; 6 | std::cin >> Q; 7 | 8 | for (int q = 0; q < Q; q++) 9 | { 10 | std::string str; 11 | 12 | std::cin >> len; 13 | std::cin >> str; 14 | 15 | int count = 0; 16 | 17 | for (int c = 1; c < len; c++) 18 | { 19 | if (str[c - 1] == str[c]) 20 | { 21 | count++; 22 | } 23 | } 24 | 25 | std::cout << count << "\n"; 26 | } 27 | 28 | return 0; 29 | } -------------------------------------------------------------------------------- /Week_00/Seminar/TK/simple_array_sum/solution_array.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Since we know the max number of elements is 1000 4 | // we can preemptively allocate the memory. 5 | const int MAXSIZE = 1000; 6 | 7 | int main() 8 | { 9 | int n; 10 | int arr[MAXSIZE]; 11 | 12 | std::cin >> n; 13 | 14 | for (int i = 0; i < n; i++) 15 | { 16 | std::cin >> arr[i]; 17 | } 18 | 19 | // Using "int" is also possible since 20 | // the max sum is 1000 elements each one being 1000 => 1_000_000 21 | // which can be stored inside an int. 22 | 23 | long long sum = 0; 24 | for (int i = 0; i < n; i++) 25 | { 26 | sum += arr[i]; 27 | } 28 | 29 | std::cout << sum; 30 | } 31 | -------------------------------------------------------------------------------- /Week_00/Seminar/TK/simple_array_sum/solution_vector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | int n; 7 | std::cin >> n; 8 | 9 | std::vector v(n); 10 | 11 | for (int i = 0; i < n; i++) 12 | { 13 | std::cin >> v[i]; 14 | } 15 | 16 | long long sum = 0; 17 | for (int i = 0; i < n; i++) 18 | { 19 | sum += v[i]; 20 | } 21 | 22 | std::cout << sum; 23 | } 24 | -------------------------------------------------------------------------------- /Week_00/Seminar/TK/solve_me_first/solution.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | // Using type "int" is ok since "a" and "b" are between 1 and 1000. 6 | int a, b; 7 | std::cin >> a >> b; 8 | 9 | std::cout << a + b; 10 | 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /Week_00/Seminar/TK/two_sum/solution_map.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Solution 5 | { 6 | public: 7 | std::vector twoSum(std::vector &nums, int target) 8 | { 9 | std::unordered_map seen_nums; 10 | 11 | for (int i = 0; i < nums.size(); i++) 12 | { 13 | int friend_num = target - nums[i]; 14 | 15 | if (seen_nums.find(friend_num) != seen_nums.end()) 16 | { 17 | return {seen_nums[friend_num], i}; 18 | } 19 | 20 | seen_nums[nums[i]] = i; 21 | } 22 | 23 | return {}; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /Week_00/Seminar/TK/two_sum/solution_naive.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Solution 5 | { 6 | public: 7 | std::vector twoSum(std::vector &nums, int target) 8 | { 9 | 10 | for (int i = 0; i < nums.size(); i++) 11 | { 12 | for (int j = i + 1; j < nums.size(); j++) 13 | { 14 | if (nums[i] + nums[j] == target) 15 | { 16 | return {i, j}; 17 | } 18 | } 19 | } 20 | 21 | return {}; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /Week_01/Practicum/python/Convert an Array Into a 2D Array With Conditions.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findMatrix(self, nums: List[int]) -> List[List[int]]: 3 | count_lst = [0 for _ in range(max(nums) + 1)] 4 | 5 | for num in nums: 6 | count_lst[num] += 1 7 | 8 | matrix = [] 9 | 10 | for _ in range(max(count_lst)): 11 | row = [] 12 | 13 | for i in range(len(count_lst)): 14 | if count_lst[i] != 0: 15 | row.append(i) 16 | count_lst[i] -= 1 17 | 18 | matrix.append(row) 19 | 20 | return matrix -------------------------------------------------------------------------------- /Week_01/Practicum/python/Find if Digit Game Can Be Won.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def canAliceWin(self, nums: List[int]) -> bool: 3 | one_sum, two_sum = 0, 0 4 | 5 | for num in nums: 6 | if len(str(num)) == 1: 7 | one_sum += num 8 | else: 9 | two_sum += num 10 | 11 | return one_sum != two_sum -------------------------------------------------------------------------------- /Week_01/Practicum/python/Group the People Given the Group Size They Belong To.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def groupThePeople(self, groupSizes: List[int]) -> List[List[int]]: 3 | 4 | count_lst = [[] for _ in range(501)] 5 | 6 | for i, num in enumerate(groupSizes): 7 | count_lst[num].append(i) 8 | 9 | groups = [] 10 | 11 | for idx, group_lst in enumerate(count_lst): 12 | if len(group_lst) == 0: 13 | continue 14 | 15 | groups_count = int(len(group_lst) / idx) 16 | group_idx = 0 17 | for group in range(groups_count): 18 | current_group = [] 19 | for _ in range(idx): 20 | current_group.append(group_lst[group_idx]) 21 | group_idx += 1 22 | 23 | groups.append(current_group) 24 | 25 | return groups -------------------------------------------------------------------------------- /Week_01/Practicum/python/Jewels and Stones.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def numJewelsInStones(self, jewels: str, stones: str) -> int: 3 | res = 0 4 | for stone in stones: 5 | for jewel in jewels: 6 | if stone == jewel: 7 | res += 1 8 | break 9 | 10 | return res -------------------------------------------------------------------------------- /Week_01/Practicum/python/Permutation Difference between Two Strings.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findPermutationDifference(self, s: str, t: str) -> int: 3 | sum_ = 0 4 | for i, char_s in enumerate(s): 5 | for j, char_t in enumerate(t): 6 | if char_s == char_t: 7 | sum_ += abs(i - j) 8 | 9 | return sum_ -------------------------------------------------------------------------------- /Week_01/Seminar/GT/Solutions/ContainerWithMostWater.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int maxArea(vector& heights) { 4 | int leftIdx = 0; 5 | int rightIdx = heights.size() - 1; 6 | int max = std::min(heights[leftIdx], heights[rightIdx]) * (rightIdx - leftIdx); 7 | 8 | while(leftIdx < rightIdx) { 9 | int currentMax = std::min(heights[leftIdx], heights[rightIdx]) * (rightIdx - leftIdx); 10 | 11 | max = std::max(max, currentMax); 12 | if(heights[leftIdx] > heights[rightIdx]) { 13 | rightIdx--; 14 | } 15 | else { 16 | leftIdx++; 17 | } 18 | } 19 | return max; 20 | } 21 | }; -------------------------------------------------------------------------------- /Week_01/Seminar/GT/Solutions/MissingBusTickerHard.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int firstMissingPositive(vector& nums) { 4 | for(size_t i = 0; i < nums.size(); i++) { 5 | while(nums[i] >= 1 && nums[i] <= nums.size() && nums[nums[i] - 1] != nums[i]) { 6 | std::swap(nums[i], nums[nums[i] - 1]); 7 | } 8 | } 9 | 10 | for(size_t i = 0; i < nums.size(); i++) { 11 | if(nums[i] != i + 1) { 12 | return i + 1; 13 | } 14 | } 15 | 16 | return nums.size() + 1; 17 | } 18 | }; -------------------------------------------------------------------------------- /Week_01/Seminar/GT/Solutions/MoveZeroes.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | void moveZeroes(vector& nums) { 4 | for(size_t iter = 0, nextNumberIndex = 0; iter < nums.size(); iter++) { 5 | if(nums[iter] != 0) { 6 | swap(nums[nextNumberIndex], nums[iter]); 7 | nextNumberIndex++; 8 | } 9 | } 10 | 11 | } 12 | }; -------------------------------------------------------------------------------- /Week_01/Seminar/GT/Solutions/PlusOne.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector plusOne(vector& digits) { 4 | int iter = digits.size() - 1; 5 | int takeOver = 1; 6 | while(iter >= 0 && takeOver > 0) { 7 | digits[iter]++; 8 | digits[iter] %= 10; 9 | takeOver = (digits[iter] == 0); 10 | iter--; 11 | } 12 | 13 | if(iter == -1 && takeOver) { 14 | digits.insert(digits.begin(), 1); 15 | } 16 | 17 | return digits; 18 | } 19 | }; -------------------------------------------------------------------------------- /Week_01/Seminar/GT/Solutions/RotateArray.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | 3 | void reverse(vector& nums, int startIndex, int endIndex) { 4 | if(startIndex >= endIndex) { 5 | return; 6 | } 7 | for(int i = 0; i <= (endIndex - startIndex) / 2; i++) { 8 | std::swap(nums[startIndex + i], nums[endIndex - i]); 9 | } 10 | } 11 | public: 12 | void rotate(vector& nums, int k) { 13 | k %= nums.size(); 14 | reverse(nums, nums.size() - k, nums.size() - 1); 15 | reverse(nums, 0, nums.size() - k - 1); 16 | reverse(nums, 0, nums.size() - 1); 17 | } 18 | }; -------------------------------------------------------------------------------- /Week_01/Seminar/GT/Solutions/RotateImage.cpp: -------------------------------------------------------------------------------- 1 | // TODO: solve -------------------------------------------------------------------------------- /Week_01/Seminar/GT/Solutions/SingleNumber1.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int singleNumber(vector& nums) { 4 | int result = 0; 5 | 6 | for(auto& num: nums) { 7 | result ^= num; 8 | } 9 | 10 | return result; 11 | } 12 | }; -------------------------------------------------------------------------------- /Week_01/Seminar/GT/Solutions/SingleNumber2.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | void addBits(unsigned n, vector& counter) { 4 | int i = 0; 5 | while(n > 0) { 6 | if(n & 1) { 7 | counter[i]++; 8 | } 9 | i++; 10 | n /= 2; 11 | } 12 | } 13 | int singleNumber(vector& nums) { 14 | vector counter(32, 0); 15 | 16 | for(auto& n: nums) { 17 | addBits(n, counter); 18 | } 19 | 20 | int result = 0; 21 | for(size_t i = 0, powOf2 = 1; i < counter.size(); i++, powOf2*=2) { 22 | if(counter[i] % 3 != 0) { 23 | result += powOf2; 24 | } 25 | } 26 | 27 | return result; 28 | } 29 | }; -------------------------------------------------------------------------------- /Week_01/Seminar/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_01/Seminar/README.md -------------------------------------------------------------------------------- /Week_01/Seminar/TK/missing_bus_ticket/solution_set.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | std::unordered_set s; 6 | 7 | int main() 8 | { 9 | std::cin.tie(NULL); 10 | std::ios::sync_with_stdio(false); 11 | 12 | long N; 13 | std::cin >> N; 14 | 15 | long num; 16 | 17 | for (long i = 0; i < N; i++) 18 | { 19 | std::cin >> num; 20 | if (num < 0) 21 | { 22 | continue; 23 | } 24 | 25 | s.insert(num); 26 | } 27 | 28 | for (long i = 1; i < 1000002; i++) 29 | { 30 | if (s.count(i) <= 0) 31 | { 32 | std::cout << i; 33 | break; 34 | } 35 | } 36 | 37 | return 0; 38 | } -------------------------------------------------------------------------------- /Week_01/Seminar/TK/move_zeros/solution_custom_sort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | class Solution 8 | { 9 | public: 10 | static bool compareZero(const int &left, const int &right) 11 | { 12 | return left != 0 && right == 0; 13 | } 14 | 15 | void moveZeroes(vector &nums) 16 | { 17 | std::stable_sort(nums.begin(), nums.end(), compareZero); 18 | } 19 | }; -------------------------------------------------------------------------------- /Week_01/Seminar/TK/move_zeros/solution_linear.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Solution 5 | { 6 | public: 7 | void moveZeroes(std::vector &nums) 8 | { 9 | int first_zero = 0; 10 | 11 | for (int i = 0; i < nums.size(); i++) 12 | { 13 | if (nums[i] != 0) 14 | { 15 | nums[first_zero] = nums[i]; 16 | first_zero += 1; 17 | } 18 | } 19 | 20 | while (first_zero < nums.size()) 21 | { 22 | nums[first_zero] = 0; 23 | first_zero += 1; 24 | } 25 | } 26 | }; -------------------------------------------------------------------------------- /Week_01/Seminar/TK/plus_one/solution.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | class Solution 6 | { 7 | public: 8 | vector plusOne(vector &digits) 9 | { 10 | int n = digits.size(); 11 | 12 | for (int i = n - 1; i >= 0; --i) 13 | { 14 | digits[i] += 1; 15 | digits[i] %= 10; 16 | 17 | if (digits[i] != 0) 18 | { 19 | return digits; 20 | } 21 | } 22 | 23 | // If all digits are zero, insert 1 at the beginning 24 | digits.insert(digits.begin(), 1); 25 | return digits; 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /Week_01/Seminar/TK/rotate_image/solution.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | class Solution 7 | { 8 | public: 9 | void rotate(vector> &matrix) 10 | { 11 | int N = matrix.size(); 12 | 13 | // Transposing the matrix 14 | for (int i = 0; i < N; ++i) 15 | { 16 | for (int j = i + 1; j < N; ++j) 17 | { 18 | std::swap(matrix[i][j], matrix[j][i]); 19 | } 20 | } 21 | 22 | // Reversing each row 23 | for (int i = 0; i < N; ++i) 24 | { 25 | std::reverse(matrix[i].begin(), matrix[i].end()); 26 | } 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /Week_01/Seminar/TK/single_number/solution_counting.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | class Solution 7 | { 8 | public: 9 | int singleNumber(vector &nums) 10 | { 11 | vector count(60001, 0); 12 | 13 | for (int num : nums) 14 | { 15 | count[num + 30000]++; 16 | } 17 | 18 | for (int i = 0; i < count.size(); ++i) 19 | { 20 | if (count[i] == 1) 21 | { 22 | return i - 30000; 23 | } 24 | } 25 | 26 | return 0; 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /Week_01/Seminar/TK/single_number/solution_map.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | class Solution 8 | { 9 | public: 10 | int singleNumber(vector &nums) 11 | { 12 | unordered_map countMap; 13 | 14 | for (int num : nums) 15 | { 16 | countMap[num]++; 17 | } 18 | 19 | for (const auto &pair : countMap) 20 | { 21 | if (pair.second == 1) 22 | { 23 | return pair.first; 24 | } 25 | } 26 | 27 | return 0; 28 | } 29 | }; -------------------------------------------------------------------------------- /Week_01/Seminar/TK/single_number/solution_set.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | class Solution 8 | { 9 | public: 10 | int singleNumber(vector &nums) 11 | { 12 | unordered_set seen; 13 | 14 | for (int num : nums) 15 | { 16 | if (seen.count(num)) 17 | { 18 | seen.erase(num); 19 | } 20 | else 21 | { 22 | seen.insert(num); 23 | } 24 | } 25 | 26 | return *seen.begin(); 27 | } 28 | }; -------------------------------------------------------------------------------- /Week_01/Seminar/TK/single_number/solution_sort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | class Solution 8 | { 9 | public: 10 | int singleNumber(vector &nums) 11 | { 12 | sort(nums.begin(), nums.end()); 13 | 14 | for (int i = 0; i < nums.size(); i += 2) 15 | { 16 | if (i == nums.size() - 1 || nums[i] != nums[i + 1]) 17 | { 18 | return nums[i]; 19 | } 20 | } 21 | 22 | return 0; 23 | } 24 | }; -------------------------------------------------------------------------------- /Week_01/Seminar/TK/single_number/solution_xor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | class Solution 7 | { 8 | public: 9 | int singleNumber(vector &nums) 10 | { 11 | int result = 0; 12 | for (int num : nums) 13 | { 14 | result ^= num; 15 | } 16 | return result; 17 | } 18 | }; -------------------------------------------------------------------------------- /Week_01/Seminar/TK/water_supplies/solution_naive.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() 8 | { 9 | int n; 10 | cin >> n; 11 | 12 | vector heights(n); 13 | for (int i = 0; i < n; i++) 14 | { 15 | cin >> heights[i]; 16 | } 17 | 18 | int maxWater = 0; 19 | 20 | for (int i = 0; i < n; i++) 21 | { 22 | for (int j = i + 1; j < n; j++) 23 | { 24 | int height = min(heights[i], heights[j]); 25 | int width = j - i; 26 | int water = height * width; 27 | maxWater = max(maxWater, water); 28 | } 29 | } 30 | 31 | cout << maxWater; 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /Week_01/Seminar/TK/water_supplies/solution_two_pointers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() 8 | { 9 | int n; 10 | cin >> n; 11 | 12 | vector heights(n); 13 | for (int i = 0; i < n; i++) 14 | { 15 | cin >> heights[i]; 16 | } 17 | 18 | int maxWater = 0; 19 | int left = 0, right = n - 1; 20 | 21 | while (left < right) 22 | { 23 | int height = min(heights[left], heights[right]); 24 | int width = right - left; 25 | int water = height * width; 26 | maxWater = max(maxWater, water); 27 | 28 | if (heights[left] < heights[right]) 29 | { 30 | left++; 31 | } 32 | else 33 | { 34 | right--; 35 | } 36 | } 37 | 38 | cout << maxWater; 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /Week_02/Practicum/Contains Duplicate.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool containsDuplicate(vector& nums) { 4 | sort(nums.begin(), nums.end()); 5 | 6 | for (int i = 1; i < nums.size(); i++) { 7 | // Check if the current number is the same as the previous one 8 | if (nums[i] == nums[i - 1]) { 9 | return true; 10 | } 11 | } 12 | 13 | // If no duplicates are found in the entire array 14 | return false; 15 | } 16 | }; -------------------------------------------------------------------------------- /Week_02/Practicum/Majority Element II.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector majorityElement(vector& nums) { 4 | // Sort the input array to bring duplicates together 5 | sort(nums.begin(), nums.end()); 6 | 7 | int size = nums.size(); 8 | int target = size / 3; 9 | vector result; 10 | 11 | for (int i = 0; i < size - target; i++) { 12 | // Check if the element occurs more than 'target' times 13 | if (nums[i] == nums[i + target]) { 14 | // Add the element to the result if it's not already added 15 | if (result.empty() || result.back() != nums[i]) { 16 | result.push_back(nums[i]); 17 | } 18 | // Skip to the next element after the sequence 19 | i += target; 20 | } 21 | } 22 | 23 | return result; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /Week_02/Practicum/Maximum Ice Cream Bars.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int maxIceCream(vector& costs, int coins) { 4 | int count = 0; 5 | 6 | sort(costs.begin(), costs.end()); 7 | 8 | for (int i = 0; i < costs.size(); i++) { 9 | coins -= costs[i]; 10 | if (coins < 0) { 11 | break; 12 | } 13 | count++; 14 | } 15 | return count; 16 | } 17 | }; -------------------------------------------------------------------------------- /Week_02/Practicum/Python/Contains Duplicate II.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | class Solution: 3 | def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool: 4 | nums = [(num, i) for i, num in enumerate(nums)] 5 | 6 | nums.sort() 7 | 8 | for i in range(len(nums) - 1): 9 | if nums[i][0] == nums[i + 1][0] and nums[i + 1][1] - nums[i][1] <= k: 10 | return True 11 | 12 | return False -------------------------------------------------------------------------------- /Week_02/Practicum/Python/Contains Duplicate.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def containsDuplicate(self, nums: List[int]) -> bool: 3 | nums.sort() # nlogn 4 | 5 | for i in range(len(nums) - 1): # n 6 | if nums[i] == nums[i + 1]: 7 | return True 8 | 9 | return False -------------------------------------------------------------------------------- /Week_02/Practicum/Python/Majority Element II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def majorityElement(self, nums: List[int]) -> List[int]: 3 | nums.sort() 4 | output = [] 5 | print(nums) 6 | target = len(nums) // 3 7 | for i in range(len(nums) - target): 8 | if nums[i] == nums[i + target] and nums[i] not in output: 9 | output.append(nums[i]) 10 | 11 | return output -------------------------------------------------------------------------------- /Week_02/Practicum/Python/Maximum Ice Cream Bars.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxIceCream(self, costs: List[int], coins: int) -> int: 3 | count_lst = [0 for _ in range(int(1e5) + 1)] 4 | 5 | total_ice_creams = 0 6 | 7 | for cost in costs: 8 | count_lst[cost] += 1 9 | 10 | for num, num_count in enumerate(count_lst): 11 | if num_count == 0: 12 | continue 13 | 14 | target = coins // num 15 | 16 | if num_count > target: 17 | total_ice_creams += target 18 | break 19 | 20 | total_ice_creams += num_count 21 | coins -= num_count * num 22 | 23 | return total_ice_creams -------------------------------------------------------------------------------- /Week_02/Practicum/Python/Merge Intervals.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def merge(self, intervals: List[List[int]]) -> List[List[int]]: 3 | intervals.sort(key=lambda x: x[0]) 4 | n = len(intervals) 5 | output = [intervals[0]] 6 | for i in range(1, n): 7 | if intervals[i][0] <= output[-1][1]: 8 | output[-1][1] = max(output[-1][1],intervals[i][1]) 9 | else: 10 | output.append(intervals[i]) 11 | return output -------------------------------------------------------------------------------- /Week_02/Practicum/Python/Merge Sorted Array.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None: 3 | """ 4 | Do not return anything, modify nums1 in-place instead. 5 | """ 6 | n1_idx = m - 1 7 | n2_idx = n - 1 8 | r_idx = m + n - 1 9 | 10 | while n2_idx >= 0: 11 | if n1_idx >= 0 and nums1[n1_idx] > nums2[n2_idx]: 12 | nums1[r_idx] = nums1[n1_idx] 13 | n1_idx -= 1 14 | else: 15 | nums1[r_idx] = nums2[n2_idx] 16 | n2_idx -= 1 17 | 18 | r_idx -= 1 -------------------------------------------------------------------------------- /Week_02/Seminar/GT/Solutions/ContainsDuplicate.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool containsDuplicate(vector& nums) { 4 | sort(nums.begin(), nums.end()); // why not counting sort? 5 | for(size_t i = 1; i < nums.size(); i++) { 6 | if(nums[i] == nums[i - 1]){ 7 | return true; 8 | } 9 | } 10 | 11 | return false; 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /Week_02/Seminar/GT/Solutions/FindTheDifference.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | char findTheDifference(string s, string t) { 4 | int counter[256]{0}; 5 | for(auto& ch: s) { 6 | counter[ch]++; 7 | } 8 | 9 | for(size_t i = 0; i < t.size(); i++) { 10 | counter[t[i]]--; 11 | if(counter[t[i]] == -1) { 12 | return t[i]; 13 | } 14 | } 15 | return -1; 16 | } 17 | }; -------------------------------------------------------------------------------- /Week_02/Seminar/GT/Solutions/IntersectionOfTwoArrays2.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector intersect(vector& nums1, vector& nums2) { 4 | sort(nums1.begin(), nums1.end()); 5 | sort(nums2.begin(), nums2.end()); 6 | vector result; 7 | 8 | int i = 0, j = 0; 9 | while(i < nums1.size() && j < nums2.size()) { 10 | if(nums1[i] < nums2[j]) { 11 | i++; 12 | } 13 | else if(nums1[i] > nums2[j]) { 14 | j++; 15 | } 16 | else { 17 | result.push_back(nums1[i]); 18 | i++; 19 | j++; 20 | } 21 | } 22 | 23 | return result; 24 | } 25 | }; -------------------------------------------------------------------------------- /Week_02/Seminar/GT/Solutions/Maximum-Product-Of-Three-Elements.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int maximumProduct(vector& nums) { 4 | std::sort(nums.begin(), nums.end()); 5 | 6 | size_t n = nums.size(); 7 | int v1 = nums[0] * nums[1] * nums[n - 1]; 8 | int v2 = nums[n - 3] * nums[n - 2] * nums[n - 1]; 9 | return max(v1, v2); 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /Week_02/Seminar/GT/Solutions/MergeIntervals.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int eraseOverlapIntervals(vector>& intervals) { 4 | sort(intervals.begin(), intervals.end(), [](const vector& lhs, const vector& rhs) { 5 | if(lhs[1] == rhs[1]) { 6 | return lhs[0] < rhs[0]; 7 | } 8 | return lhs[1] < rhs[1]; 9 | }); 10 | 11 | int result = 0; 12 | int end = intervals[0][1]; 13 | for(size_t i = 1; i < intervals.size(); i++) { 14 | if(end > intervals[i][0]) { 15 | result++; 16 | } 17 | else { 18 | end = intervals[i][1]; 19 | } 20 | } 21 | 22 | return result; 23 | } 24 | }; -------------------------------------------------------------------------------- /Week_02/Seminar/GT/Solutions/MergeSortedArrays.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | void merge(vector& nums1, int m, vector& nums2, int n) { 4 | vector nums1Copy = nums1; 5 | nums1.reserve(m + n); 6 | int i = 0, j = 0; 7 | while(i < m && j < n) { 8 | if(nums1Copy[i] < nums2[j]) { 9 | nums1[i + j] = nums1Copy[i]; 10 | i++; 11 | } 12 | else { 13 | nums1[i + j] = nums2[j]; 14 | j++; 15 | } 16 | } 17 | 18 | while(i < m) { 19 | nums1[i + j] = nums1Copy[i]; 20 | i++; 21 | } 22 | while(j < n) { 23 | nums1[i + j] = nums2[j]; 24 | j++; 25 | } 26 | } 27 | }; -------------------------------------------------------------------------------- /Week_02/Seminar/GT/Solutions/NonOverlappingIntervals.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int eraseOverlapIntervals(vector>& intervals) { 4 | sort(intervals.begin(), intervals.end(), [](const vector& lhs, const vector& rhs) { 5 | if(lhs[1] == rhs[1]) { // actually this additional check is not needed 6 | return lhs[0] < rhs[0]; 7 | } 8 | return lhs[1] < rhs[1]; 9 | }); 10 | 11 | int result = 0; 12 | int end = intervals[0][1]; 13 | for(size_t i = 1; i < intervals.size(); i++) { 14 | if(end > intervals[i][0]) { 15 | result++; 16 | } 17 | else { 18 | end = intervals[i][1]; 19 | } 20 | } 21 | 22 | return result; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /Week_02/Seminar/GT/Solutions/SortCharactersByFrequency.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | string frequencySort(string s) { 4 | int counter[256]{}; 5 | for(auto ch: s) { 6 | counter[ch]++; 7 | } 8 | 9 | vector> container; 10 | for(size_t i = 0; i < 256; i++) { 11 | if(counter[i] != 0) { 12 | container.push_back(make_pair((char)i, counter[i])); 13 | } 14 | } 15 | sort(container.begin(), container.end(), [](auto& lhs, auto& rhs){ 16 | return lhs.second > rhs.second; 17 | }); 18 | 19 | string result; 20 | result.reserve(s.size()); 21 | for(auto& kvp: container) { 22 | for(size_t i = 0; i < kvp.second; i++) { 23 | result += kvp.first; 24 | } 25 | } 26 | 27 | return result; 28 | } 29 | }; -------------------------------------------------------------------------------- /Week_02/Seminar/GT/naive/insertion.cpp: -------------------------------------------------------------------------------- 1 | template 2 | void naiveInsertionSort(T* arr, int len) 3 | { 4 | for (int i = 1; i < len; i++) 5 | { 6 | int elIndex = i; 7 | while (elIndex > 0 && arr[elIndex] < arr[elIndex - 1]) 8 | { 9 | std::swap(arr[elIndex], arr[elIndex - 1]); 10 | elIndex--; 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /Week_02/Seminar/TK/contains_duplicate/solution_map.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Solution 5 | { 6 | public: 7 | bool containsDuplicate(std::vector &nums) 8 | { 9 | std::unordered_map m; 10 | for (int num : nums) 11 | { 12 | if (m.find(num) != m.end()) 13 | { 14 | return true; 15 | } 16 | m[num] = 1; 17 | } 18 | return false; 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /Week_02/Seminar/TK/contains_duplicate/solution_set.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Solution 5 | { 6 | public: 7 | bool containsDuplicate(std::vector &nums) 8 | { 9 | std::unordered_set s(nums.begin(), nums.end()); 10 | return s.size() != nums.size(); 11 | } 12 | }; -------------------------------------------------------------------------------- /Week_02/Seminar/TK/contains_duplicate/solution_sort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Solution 5 | { 6 | public: 7 | bool containsDuplicate(std::vector &nums) 8 | { 9 | std::sort(nums.begin(), nums.end()); 10 | 11 | for (int i = 1; i < nums.size(); i++) 12 | { 13 | if (nums[i] == nums[i - 1]) 14 | { 15 | return true; 16 | } 17 | } 18 | 19 | return false; 20 | } 21 | }; -------------------------------------------------------------------------------- /Week_02/Seminar/TK/find_the_difference/solution_counting.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class Solution 4 | { 5 | public: 6 | char findTheDifference(std::string s, std::string t) 7 | { 8 | const int M = 'z' - 'a' + 1; 9 | short counts[M]{}; 10 | 11 | for (short i = 0; i < s.size(); i++) 12 | { 13 | counts[s[i] - 'a']++; 14 | } 15 | 16 | for (short i = 0; i < t.size(); i++) 17 | { 18 | counts[t[i] - 'a']--; 19 | } 20 | 21 | for (short i = 0; i < M; i++) 22 | { 23 | if (counts[i] < 0) 24 | { 25 | return 'a' + i; 26 | } 27 | } 28 | 29 | return '0'; 30 | } 31 | }; -------------------------------------------------------------------------------- /Week_02/Seminar/TK/find_the_difference/solution_sort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Solution 5 | { 6 | public: 7 | char findTheDifference(std::string s, std::string t) 8 | { 9 | std::sort(s.begin(), s.end()); 10 | std::sort(t.begin(), t.end()); 11 | 12 | int N = s.size(); 13 | 14 | for (int i = 0; i < N; i++) 15 | { 16 | if (s[i] != t[i]) 17 | { 18 | return t[i]; 19 | } 20 | } 21 | return t[N]; 22 | } 23 | }; -------------------------------------------------------------------------------- /Week_02/Seminar/TK/first_missing_positive/solution.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | class Solution 6 | { 7 | public: 8 | int firstMissingPositive(vector &nums) 9 | { 10 | int n = nums.size(); 11 | 12 | for (int i = 0; i < n; ++i) 13 | { 14 | while (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) 15 | { 16 | swap(nums[i], nums[nums[i] - 1]); 17 | } 18 | } 19 | 20 | for (int i = 0; i < n; ++i) 21 | { 22 | if (nums[i] != i + 1) 23 | { 24 | return i + 1; 25 | } 26 | } 27 | 28 | return n + 1; 29 | } 30 | }; -------------------------------------------------------------------------------- /Week_02/Seminar/TK/merge_sorted_arrays/solution_inplace.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void merge(std::vector &nums1, int m, std::vector &nums2, int n) 4 | { 5 | int i = m - 1; 6 | int j = n - 1; 7 | int k = m + n - 1; 8 | 9 | while (i >= 0 && j >= 0) 10 | { 11 | if (nums1[i] > nums2[j]) 12 | { 13 | nums1[k] = nums1[i]; 14 | i--; 15 | } 16 | else 17 | { 18 | nums1[k] = nums2[j]; 19 | j--; 20 | } 21 | k--; 22 | } 23 | 24 | // If nums2 has remaining elements, copy them into nums1 25 | // We do not need this for i, because they will already be in place 26 | while (j >= 0) 27 | { 28 | nums1[k] = nums2[j]; 29 | k--; 30 | j--; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Week_03/Practicum/PythonAdditional/Find the Difference.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findTheDifference(self, s: str, t: str) -> str: 3 | c1, c2 = [0 for _ in range(26)], [0 for _ in range(26)] 4 | 5 | for c in s: 6 | c1[ord(c) - ord('a')] += 1 7 | 8 | for c in t: 9 | c2[ord(c) - ord('a')] += 1 10 | 11 | for c in range(26): 12 | if c1[c] != c2[c]: 13 | return chr(ord('a') + c) -------------------------------------------------------------------------------- /Week_03/Practicum/PythonAdditional/Find the Index.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def strStr(self, haystack: str, needle: str) -> int: 3 | for i in range(len(haystack) - len(needle) + 1): 4 | if haystack[i : i + len(needle)] == needle: 5 | return i 6 | 7 | return -1 -------------------------------------------------------------------------------- /Week_03/Practicum/PythonAdditional/Merge Strings Alternately.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def mergeAlternately(self, word1: str, word2: str) -> str: 3 | lst = [] 4 | for i in range(min(len(word1), len(word2))): 5 | lst.append(word1[i]) 6 | lst.append(word2[i]) 7 | 8 | if len(word1) > len(word2): 9 | lst.append(word1[len(word2) : ]) 10 | else: 11 | lst.append(word2[len(word1) : ]) 12 | 13 | return "".join(lst) -------------------------------------------------------------------------------- /Week_03/Practicum/PythonAdditional/Repeated Substring Pattern.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def repeatedSubstringPattern(self, s: str) -> bool: 3 | for num in range(1, (len(s) // 2) + 1): 4 | if len(s) % num != 0: 5 | continue 6 | 7 | subset_s = s[0 : num] 8 | num_found = 0 9 | for i in range(0, len(s), num): 10 | if s[i : i + num] == subset_s: 11 | num_found += 1 12 | else: 13 | break 14 | 15 | if num_found == len(s) / num: 16 | return True 17 | 18 | return False -------------------------------------------------------------------------------- /Week_03/Practicum/PythonAdditional/Sign of the Product of an Array.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def arraySign(self, nums: List[int]) -> int: 3 | res = 1 4 | for num in nums: 5 | if num == 0: 6 | return 0 7 | 8 | res *= (num // abs(num)) 9 | 10 | return res -------------------------------------------------------------------------------- /Week_03/Practicum/PythonAdditional/Tasks.md: -------------------------------------------------------------------------------- 1 | # Задачи 2 | 3 | - [All Tasks](https://leetcode.com/studyplan/programming-skills/) 4 | -------------------------------------------------------------------------------- /Week_03/Practicum/PythonAdditional/Valid Anagram.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isAnagram(self, s: str, t: str) -> bool: 3 | c1, c2 = [0 for _ in range(26)], [0 for _ in range(26)] 4 | 5 | for c in s: 6 | c1[ord(c) - ord('a')] += 1 7 | 8 | for c in t: 9 | c2[ord(c) - ord('a')] += 1 10 | 11 | for c in range(26): 12 | if c1[c] != c2[c]: 13 | return False 14 | 15 | return True -------------------------------------------------------------------------------- /Week_03/Practicum/Quiz.md: -------------------------------------------------------------------------------- 1 | ### Test 1 2 | 3 | - [Quiz](https://quizizz.com/join/quiz/615f5ed8909580001d4cea85/start) 4 | -------------------------------------------------------------------------------- /Week_03/Seminar/Solutions/BinarySearch.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int search(vector& nums, int target) { 4 | int left = 0; 5 | int right = nums.size() - 1; 6 | while(left <= right) { 7 | int mid = left + (right - left) / 2; 8 | if(nums[mid] == target) { 9 | return mid; 10 | } 11 | else if(nums[mid] > target) { 12 | right = mid - 1; 13 | } 14 | else { 15 | left = mid + 1; 16 | } 17 | } 18 | 19 | return -1; 20 | } 21 | }; -------------------------------------------------------------------------------- /Week_03/Seminar/Solutions/FirstBadVersion.cpp: -------------------------------------------------------------------------------- 1 | // The API isBadVersion is defined for you. 2 | // bool isBadVersion(int version); 3 | 4 | class Solution { 5 | public: 6 | int firstBadVersion(int n) { 7 | int left = 0; 8 | int right = n; 9 | // you can have additional result variable, but the left index does the same job 10 | while(left <= right) { 11 | int mid = left + (right - left) / 2; 12 | if(isBadVersion(mid)) { 13 | right = mid - 1; 14 | } 15 | else { 16 | left = mid + 1; 17 | } 18 | } 19 | 20 | return left; 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /Week_03/Seminar/Solutions/PeekIndexInMountainArray/Binary.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int peakIndexInMountainArray(vector& arr) { 4 | int l = 1; 5 | int r = arr.size() - 2; 6 | 7 | while(l <= r) { 8 | int mid = l + (r - l) / 2; 9 | 10 | if(arr[mid] > arr[mid - 1] && arr[mid] > arr[mid + 1]) { 11 | return mid; 12 | } 13 | else if(arr[mid] > arr[mid - 1]) { 14 | l = mid + 1; 15 | } 16 | else { 17 | r = mid - 1; 18 | } 19 | 20 | } 21 | 22 | return -1; 23 | } 24 | }; -------------------------------------------------------------------------------- /Week_03/Seminar/Solutions/PeekIndexInMountainArray/Ternary.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int peakIndexInMountainArray(vector& arr) { 4 | int l = 0; 5 | int r = arr.size() - 1; 6 | 7 | while(l < r) { 8 | int mid1 = l + (r - l) / 3; 9 | int mid2 = r - (r - l) / 3; 10 | 11 | if(arr[mid1] < arr[mid2]) { 12 | l = mid1 + 1; 13 | } 14 | else { 15 | r = mid2 - 1; 16 | } 17 | } 18 | 19 | return l; 20 | } 21 | }; -------------------------------------------------------------------------------- /Week_03/Seminar/Solutions/SafeSort/StdSort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | bool comparator_concat(const string &left, const string &right) 9 | { 10 | return left + right > right + left; 11 | } 12 | 13 | int main() 14 | { 15 | int N; 16 | cin >> N; 17 | 18 | vector arr(N); 19 | for (int i = 0; i < N; ++i) 20 | { 21 | cin >> arr[i]; 22 | } 23 | 24 | // If the array has only zeros, the result is 0 25 | if (count(arr.begin(), arr.end(), "0") == N) 26 | { 27 | cout << 0 << endl; 28 | return 0; 29 | } 30 | 31 | // Else sort the vector by which concatenation is bigger 32 | sort(arr.begin(), arr.end(), comparator_concat); 33 | 34 | for (const string &s : arr) 35 | { 36 | cout << s; 37 | } 38 | 39 | cout << endl; 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /Week_03/Seminar/Solutions/Search2DMatrix/JumpSearch.cpp: -------------------------------------------------------------------------------- 1 | // Jump search on last column 2 | // Then linear in the row 3 | 4 | #include 5 | 6 | class Solution 7 | { 8 | public: 9 | bool searchMatrix(std::vector> &matrix, int target) 10 | { 11 | int N = matrix.size(); 12 | int M = matrix[0].size(); 13 | 14 | int i = 0; 15 | while (i < N && target > matrix[i][M - 1]) 16 | { 17 | i++; 18 | } 19 | 20 | if (i == N) 21 | { 22 | return false; 23 | } 24 | 25 | for (int j = 0; j < M; j++) 26 | { 27 | if (matrix[i][j] == target) 28 | { 29 | return true; 30 | } 31 | } 32 | 33 | return false; 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /Week_03/Seminar/Solutions/SearchInsertPosition.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int searchInsert(vector& nums, int target) { 4 | int left = 0; 5 | int right = nums.size() - 1; 6 | 7 | while(left <= right) { 8 | int mid = left + (right - left) / 2; 9 | if(nums[mid] >= target) { 10 | right = mid - 1; 11 | } 12 | else { 13 | left = mid + 1; 14 | } 15 | } 16 | 17 | return left; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /Week_04/Practicum/Middle of the Linked List.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * struct ListNode { 4 | * int val; 5 | * ListNode *next; 6 | * ListNode() : val(0), next(nullptr) {} 7 | * ListNode(int x) : val(x), next(nullptr) {} 8 | * ListNode(int x, ListNode *next) : val(x), next(next) {} 9 | * }; 10 | */ 11 | class Solution { 12 | public: 13 | ListNode* middleNode(ListNode* head) { 14 | ListNode* slow = head; 15 | ListNode* fast = head; 16 | 17 | while (fast && fast->next) { 18 | slow = slow->next; 19 | fast = fast->next->next; 20 | } 21 | 22 | return slow; 23 | } 24 | }; -------------------------------------------------------------------------------- /Week_04/Practicum/PythonAdditional/Arranging Coins.py: -------------------------------------------------------------------------------- 1 | def f(rows, coins): 2 | return coins >= int((1 + rows) * rows / 2) 3 | 4 | def bs(left, right, n): 5 | ans = 0 6 | while left <= right: 7 | mid = (left + right) // 2 8 | if f(mid, n): 9 | ans = mid 10 | left = mid + 1 11 | else: 12 | right = mid - 1 13 | 14 | return ans 15 | 16 | class Solution: 17 | def arrangeCoins(self, n: int) -> int: 18 | return bs(0, n, n) -------------------------------------------------------------------------------- /Week_04/Practicum/PythonAdditional/Binary Search.py: -------------------------------------------------------------------------------- 1 | def binary_search(nums, target): 2 | left, right = 0, len(nums) - 1 3 | 4 | while left <= right: 5 | mid = (left + right) // 2 6 | 7 | if nums[mid] == target: 8 | return mid 9 | 10 | if nums[mid] > target: 11 | right = mid - 1 12 | else: 13 | left = mid + 1 14 | 15 | return -1 16 | 17 | 18 | class Solution: 19 | def search(self, nums: List[int], target: int) -> int: 20 | return binary_search(nums, target) -------------------------------------------------------------------------------- /Week_04/Practicum/PythonAdditional/Find Right Interval.py: -------------------------------------------------------------------------------- 1 | def binary(intervals, end_i): 2 | ans = -1 3 | left, right = 0, len(intervals) - 1 4 | while left <= right: 5 | mid = (left + right) // 2 6 | if intervals[mid][0] >= end_i: 7 | ans = intervals[mid][2] 8 | right = mid - 1 9 | else: 10 | left = mid + 1 11 | 12 | return ans 13 | 14 | class Solution: 15 | def findRightInterval(self, intervals: List[List[int]]) -> List[int]: 16 | ans = [-1 for _ in intervals] 17 | intervals = [(start, end, i) for i, (start, end) in enumerate(intervals)] 18 | intervals.sort(key=lambda x: x[0]) 19 | 20 | # What is the complexity here? 21 | for interval in intervals: 22 | ans[interval[2]] = binary(intervals, interval[1]) 23 | 24 | return ans -------------------------------------------------------------------------------- /Week_04/Practicum/PythonAdditional/Find Smallest Letter_1.py: -------------------------------------------------------------------------------- 1 | def binary_search(chars, target): 2 | left, right = 0, len(chars) - 1 3 | 4 | while left <= right: 5 | mid = (left + right) // 2 6 | 7 | if chars[mid] > target: 8 | right = mid - 1 9 | else: 10 | left = mid + 1 11 | 12 | return mid 13 | 14 | 15 | class Solution: 16 | def nextGreatestLetter(self, letters: List[str], target: str) -> str: 17 | idx = binary_search(letters, target) 18 | if letters[idx] == target or letters[idx] < target: 19 | return letters[(idx + 1) % len(letters)] 20 | return letters[idx] -------------------------------------------------------------------------------- /Week_04/Practicum/PythonAdditional/Find Smallest Letter_2.py: -------------------------------------------------------------------------------- 1 | import bisect 2 | 3 | class Solution: 4 | def nextGreatestLetter(self, letters: List[str], target: str) -> str: 5 | idx = bisect.bisect_right(letters, target) 6 | letters.append(letters[0]) 7 | return letters[idx] -------------------------------------------------------------------------------- /Week_04/Practicum/PythonAdditional/First Bad Version.py: -------------------------------------------------------------------------------- 1 | # The isBadVersion API is already defined for you. 2 | # def isBadVersion(version: int) -> bool: 3 | 4 | class Solution: 5 | def binary_search(self, left, right): 6 | while left <= right: 7 | mid = (left + right) // 2 8 | 9 | if isBadVersion(mid): 10 | right = mid - 1 11 | else: 12 | left = mid + 1 13 | 14 | return left 15 | 16 | def firstBadVersion(self, n: int) -> int: 17 | return self.binary_search(0, n) -------------------------------------------------------------------------------- /Week_04/Practicum/PythonAdditional/Search Insert Position_1.py: -------------------------------------------------------------------------------- 1 | def binary_search(nums, target): 2 | left, right = 0, len(nums) - 1 3 | 4 | while left <= right: 5 | mid = (left + right) // 2 6 | 7 | if nums[mid] == target: 8 | return mid 9 | 10 | if nums[mid] > target: 11 | right = mid - 1 12 | else: 13 | left = mid + 1 14 | 15 | return left 16 | 17 | class Solution: 18 | def searchInsert(self, nums: List[int], target: int) -> int: 19 | return binary_search(nums, target) 20 | -------------------------------------------------------------------------------- /Week_04/Practicum/PythonAdditional/Search Insert Position_2.py: -------------------------------------------------------------------------------- 1 | import bisect 2 | 3 | class Solution: 4 | def searchInsert(self, nums: List[int], target: int) -> int: 5 | return bisect.bisect_left(nums, target) -------------------------------------------------------------------------------- /Week_04/Practicum/Tasks.md: -------------------------------------------------------------------------------- 1 | # Задачи 2 | 3 | - [Remove Linked List Elements](https://leetcode.com/problems/remove-linked-list-elements/description/) - VERY EASY 4 | - [Merge Two Sorted Lists](https://leetcode.com/problems/merge-two-sorted-lists/description/) - EASY 5 | - [Merge k Sorted Lists](https://leetcode.com/problems/merge-k-sorted-lists/description/) - MEDIUM 6 | - [Reverse Linked List II](https://leetcode.com/problems/reverse-linked-list-ii/) - MEDIUM 7 | - [Flatten a Multilevel Doubly Linked List](https://leetcode.com/problems/flatten-a-multilevel-doubly-linked-list/description/) - HARD 8 | - [Middle of the Linked List](https://leetcode.com/problems/middle-of-the-linked-list/description/) - EASY 9 | - [Insertion Sort List](https://leetcode.com/problems/insertion-sort-list/description/) - MEDIUM 10 | -------------------------------------------------------------------------------- /Week_04/Seminar/Python/delete-duplicate-value-nodes-from-a-sorted-linked-list.py: -------------------------------------------------------------------------------- 1 | # 2 | # For your reference: 3 | # 4 | # SinglyLinkedListNode: 5 | # int data 6 | # SinglyLinkedListNode next 7 | # 8 | 9 | def removeDuplicates(llist): 10 | node = llist 11 | 12 | while node is not None: 13 | new_next = node.next 14 | 15 | while new_next is not None and new_next.data == node.data: 16 | new_next = new_next.next 17 | 18 | node.next = new_next 19 | node = new_next 20 | 21 | return llist 22 | -------------------------------------------------------------------------------- /Week_04/Seminar/Python/reverse-linked-list.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, val=0, next=None): 4 | # self.val = val 5 | # self.next = next 6 | 7 | class Solution: 8 | def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: 9 | curr = head 10 | prev = None 11 | 12 | while curr is not None: 13 | forward = curr.next 14 | curr.next = prev 15 | prev = curr 16 | curr = forward 17 | 18 | return prev 19 | -------------------------------------------------------------------------------- /Week_04/Seminar/Solutions/Bonus/LinkedListCycle2.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * struct ListNode { 4 | * int val; 5 | * ListNode *next; 6 | * ListNode(int x) : val(x), next(NULL) {} 7 | * }; 8 | */ 9 | class Solution { 10 | public: 11 | ListNode *detectCycle(ListNode *head) { 12 | ListNode* slow = head; 13 | ListNode* fast = head; 14 | 15 | while(fast && fast->next) { 16 | fast = fast->next->next; 17 | slow = slow->next; 18 | 19 | if(slow == fast) { 20 | slow = head; 21 | while(slow != fast) { 22 | slow = slow->next; 23 | fast = fast->next; 24 | } 25 | return slow; 26 | } 27 | } 28 | 29 | return nullptr; 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /Week_04/Seminar/Solutions/DeleteNodeInALinkedList.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * struct ListNode { 4 | * int val; 5 | * ListNode *next; 6 | * ListNode(int x) : val(x), next(NULL) {} 7 | * }; 8 | */ 9 | class Solution { 10 | public: 11 | void deleteNode(ListNode* node) { 12 | node->val = node->next->val; 13 | node->next = node->next->next; 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /Week_04/Seminar/Solutions/IntersectionOfTwoLinkedLists/WithoutLength.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * struct ListNode { 4 | * int val; 5 | * ListNode *next; 6 | * ListNode(int x) : val(x), next(NULL) {} 7 | * }; 8 | */ 9 | class Solution { 10 | public: 11 | ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { 12 | ListNode* a = headA; 13 | ListNode* b = headB; 14 | 15 | while (a != b) { 16 | a = a ? a->next : headB; 17 | b = b ? b->next : headA; 18 | } 19 | 20 | return a; 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /Week_04/Seminar/Solutions/LinkedListCycle.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * struct ListNode { 4 | * int val; 5 | * ListNode *next; 6 | * ListNode(int x) : val(x), next(NULL) {} 7 | * }; 8 | */ 9 | class Solution { 10 | public: 11 | bool hasCycle(ListNode *head) { 12 | ListNode* slow = head; 13 | ListNode* fast = head; 14 | while(slow && fast && fast->next) { 15 | slow = slow->next; 16 | fast = fast->next->next; 17 | if(slow == fast) { 18 | return true; 19 | } 20 | } 21 | 22 | return false; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /Week_04/Seminar/Solutions/MergeTwoSortedLists/Recursive.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { 4 | if (!list1) { 5 | return list2; 6 | } 7 | if(!list2) { 8 | return list1; 9 | } 10 | 11 | if (list1->val > list2->val) { 12 | swap(list1, list2); 13 | } 14 | 15 | list1->next = mergeTwoLists(list1->next, list2); 16 | return list1; 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /Week_04/Seminar/Solutions/MiddleOfTheLinkedList.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * struct ListNode { 4 | * int val; 5 | * ListNode *next; 6 | * ListNode() : val(0), next(nullptr) {} 7 | * ListNode(int x) : val(x), next(nullptr) {} 8 | * ListNode(int x, ListNode *next) : val(x), next(next) {} 9 | * }; 10 | */ 11 | class Solution { 12 | public: 13 | ListNode* middleNode(ListNode* head) { 14 | auto slow = head, fast = head; 15 | while(slow && fast && fast->next) { 16 | slow = slow->next; 17 | fast = fast->next->next; 18 | } 19 | return slow; 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /Week_04/Seminar/Solutions/RemoveDuplicatesFromSortedList.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * struct ListNode { 4 | * int val; 5 | * ListNode *next; 6 | * ListNode() : val(0), next(nullptr) {} 7 | * ListNode(int x) : val(x), next(nullptr) {} 8 | * ListNode(int x, ListNode *next) : val(x), next(next) {} 9 | * }; 10 | */ 11 | class Solution { 12 | public: 13 | ListNode* deleteDuplicates(ListNode* head) { 14 | ListNode* iter = head; 15 | while(iter) { 16 | auto curr = iter; 17 | while(iter && iter->val == curr->val) { 18 | iter = iter->next; 19 | } 20 | curr->next = iter; 21 | } 22 | 23 | return head; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /Week_04/Seminar/Solutions/ReverseLinkedList.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * struct ListNode { 4 | * int val; 5 | * ListNode *next; 6 | * ListNode() : val(0), next(nullptr) {} 7 | * ListNode(int x) : val(x), next(nullptr) {} 8 | * ListNode(int x, ListNode *next) : val(x), next(next) {} 9 | * }; 10 | */ 11 | class Solution { 12 | public: 13 | ListNode* reverseList(ListNode* head) { 14 | ListNode* prev = nullptr; 15 | ListNode* curr = head; 16 | while(curr) { 17 | ListNode* next = curr->next; 18 | curr->next = prev; 19 | prev = curr; 20 | curr = next; 21 | } 22 | return prev; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /Week_05/Practicum/Next Greater Element II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def nextGreaterElements(self, nums: List[int]) -> List[int]: 3 | # 1 5 4 3 2 5 1 6 4 | # Keep monotically decrease stack, that way when we reach bigger number than 5 | # the top, we can pop all lesser elements 6 | 7 | ans = [-1 for _ in nums] 8 | 9 | stack = [] 10 | 11 | # We will do 2 passes, since it is circular 12 | for _ in range(2): 13 | for i, num in enumerate(nums): 14 | 15 | while stack and stack[-1][1] < num: 16 | ans[stack[-1][0]] = num 17 | stack.pop() 18 | 19 | stack.append((i, num)) 20 | 21 | return ans 22 | -------------------------------------------------------------------------------- /Week_05/Practicum/PythonAdditional/Convert Binary_1.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, val=0, next=None): 4 | # self.val = val 5 | # self.next = next 6 | class Solution: 7 | def getDecimalValue(self, head: Optional[ListNode]) -> int: 8 | result = 0 9 | lst = [] 10 | while head: 11 | lst.append(head.val) 12 | head = head.next 13 | 14 | for i in range(len(lst)): 15 | 16 | result += lst[i] * (2 ** (len(lst) - 1 - i)) 17 | print(i, result) 18 | 19 | return result 20 | -------------------------------------------------------------------------------- /Week_05/Practicum/PythonAdditional/Convert Binary_2.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, val=0, next=None): 4 | # self.val = val 5 | # self.next = next 6 | class Solution: 7 | def getDecimalValue(self, head: Optional[ListNode]) -> int: 8 | result = 0 9 | 10 | current = head 11 | 12 | while current: 13 | result *= 2 14 | result += current.val 15 | current = current.next 16 | 17 | return result 18 | -------------------------------------------------------------------------------- /Week_05/Practicum/PythonAdditional/Delete Middle.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, val=0, next=None): 4 | # self.val = val 5 | # self.next = next 6 | class Solution: 7 | def deleteMiddle(self, head: Optional[ListNode]) -> Optional[ListNode]: 8 | 9 | if not head or not head.next: 10 | return None 11 | 12 | size = 0 13 | current = head 14 | while current: 15 | size += 1 16 | current = current.next 17 | 18 | current = head 19 | for _ in range((size // 2) - 1): 20 | current = current.next 21 | 22 | current.next = current.next.next 23 | 24 | return head -------------------------------------------------------------------------------- /Week_05/Practicum/PythonAdditional/Double a Number.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, val=0, next=None): 4 | # self.val = val 5 | # self.next = next 6 | 7 | 8 | def double(current): 9 | if not current: 10 | return 0 11 | next_carry = double(current.next) 12 | new_val = (current.val * 2) + next_carry 13 | carry = new_val // 10 14 | current.val = new_val % 10 15 | return carry 16 | 17 | class Solution: 18 | def doubleIt(self, head: Optional[ListNode]) -> Optional[ListNode]: 19 | carry = double(head) 20 | if carry: 21 | new_head = ListNode(1, head) 22 | return new_head 23 | return head -------------------------------------------------------------------------------- /Week_05/Practicum/PythonAdditional/Middle of the Linked List.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, val=0, next=None): 4 | # self.val = val 5 | # self.next = next 6 | class Solution: 7 | def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]: 8 | if not head or not head.next: 9 | return head 10 | fast = head 11 | slow = head 12 | while fast and fast.next: 13 | fast = fast.next.next 14 | slow = slow.next 15 | 16 | return slow -------------------------------------------------------------------------------- /Week_05/Practicum/PythonAdditional/Remove Duplicates from Sorted List.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, val=0, next=None): 4 | # self.val = val 5 | # self.next = next 6 | class Solution: 7 | def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: 8 | if not head or not head.next: 9 | return head 10 | 11 | curr = head.next 12 | prev = head 13 | 14 | while curr: 15 | if prev.val == curr.val: 16 | prev.next = curr.next 17 | else: 18 | prev = prev.next 19 | curr = curr.next 20 | 21 | return head -------------------------------------------------------------------------------- /Week_05/Practicum/PythonAdditional/Remove Linked List Elements.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, val=0, next=None): 4 | # self.val = val 5 | # self.next = next 6 | class Solution: 7 | def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]: 8 | 9 | while head is not None and head.val == val: 10 | head = head.next 11 | 12 | if head is None: 13 | return None 14 | 15 | prev = head 16 | current = head.next 17 | 18 | while current is not None: 19 | if current.val == val: 20 | prev.next = current.next 21 | else: 22 | prev = current 23 | 24 | current = current.next 25 | 26 | return head -------------------------------------------------------------------------------- /Week_05/Practicum/PythonAdditional/Reverse Linked List.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, val=0, next=None): 4 | # self.val = val 5 | # self.next = next 6 | 7 | def reverse(prev, curr): 8 | if curr.next is None: 9 | curr.next = prev 10 | return curr 11 | 12 | head = reverse(curr, curr.next) 13 | curr.next = prev 14 | 15 | return head 16 | 17 | class Solution: 18 | def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: 19 | if not head: 20 | return None 21 | 22 | return reverse(None, head) -------------------------------------------------------------------------------- /Week_05/Practicum/PythonAdditional/Tasks.md: -------------------------------------------------------------------------------- 1 | # Задачи 2 | 3 | - [Convert Binary](https://leetcode.com/problems/convert-binary-number-in-a-linked-list-to-integer/description/) - EASY 4 | - [Middle of the Linked List](https://leetcode.com/problems/middle-of-the-linked-list/) - EASY 5 | - [Delete Middle](https://leetcode.com/problems/delete-the-middle-node-of-a-linked-list/description/) - EASY 6 | - [Remove Duplicates from Sorted List](https://leetcode.com/problems/remove-duplicates-from-sorted-list/description/) - EASY 7 | - [Remove Linked List Elements](https://leetcode.com/problems/remove-linked-list-elements/description/) - EASY 8 | - [Reverse Linked List](https://leetcode.com/problems/reverse-linked-list/description/) - MEDIUM 9 | - [Double a Number](https://leetcode.com/problems/double-a-number-represented-as-a-linked-list/description/) - MEDIUM 10 | - [Odd Even Linked List](https://leetcode.com/problems/odd-even-linked-list/description/) - MEDIUM -------------------------------------------------------------------------------- /Week_05/Practicum/Removing Stars From a String.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | string removeStars(string s) { 4 | std::deque deque; 5 | 6 | for (char c: s) { 7 | if (c == '*') { 8 | deque.pop_back(); 9 | } else { 10 | deque.push_back(c); 11 | } 12 | } 13 | 14 | std::string result; 15 | result.reserve(deque.size()); 16 | while (deque.size()) { 17 | result += deque.front(); 18 | deque.pop_front(); 19 | } 20 | 21 | return result; 22 | } 23 | }; -------------------------------------------------------------------------------- /Week_05/Practicum/Removing Stars From a String.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def removeStars(self, s: str) -> str: 3 | stack = [] 4 | 5 | for c in s: 6 | if c == '*': 7 | stack.pop() 8 | else: 9 | stack.append(c) 10 | 11 | return ''.join(stack) -------------------------------------------------------------------------------- /Week_05/Practicum/Shortest Unsorted Continuous Subarray.cpp: -------------------------------------------------------------------------------- 1 | // Виж README.md за описание на решението. 2 | class Solution { 3 | public: 4 | int findUnsortedSubarray(vector& nums) { 5 | std::stack min, max; // can be done without stacks, just two ints :D 6 | max.push(INT_MIN); 7 | min.push(INT_MAX); 8 | int n = nums.size(), min_idx = 0, max_idx = 0; 9 | 10 | for (int k = 0; k < n; ++k) { 11 | if (nums[k] < max.top()) { 12 | max_idx = k; 13 | } else { 14 | max.push(nums[k]); 15 | } 16 | 17 | if (nums[n - 1 - k] > min.top()) { 18 | min_idx = n - 1 - k; 19 | } else { 20 | min.push(nums[n - 1 - k]); 21 | } 22 | } 23 | 24 | return max_idx > min_idx ? max_idx - min_idx + 1 : 0; 25 | } 26 | }; -------------------------------------------------------------------------------- /Week_05/Practicum/Shortest Unsorted Continuous Subarray.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findUnsortedSubarray(self, nums: List[int]) -> int: 3 | low, high = len(nums) - 1, 0 4 | 5 | # monotonically increasing stack 6 | stack = [] 7 | for i, num in enumerate(nums): 8 | while stack and stack[-1][1] > num: 9 | ind, last = stack.pop() 10 | low = min(low, ind) 11 | 12 | stack.append((i, num)) 13 | 14 | # monotonically decreasing stack 15 | stack = [] 16 | for i, num in enumerate(reversed(nums)): 17 | while stack and stack[-1][1] < num: 18 | ind, last = stack.pop() 19 | high = max(high, ind) 20 | 21 | stack.append((len(nums) - 1 - i, num)) 22 | 23 | # low >= high means array is already sorted 24 | return 0 if low >= high else high - low + 1 -------------------------------------------------------------------------------- /Week_05/Practicum/Sliding Window Maximum.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector maxSlidingWindow(vector& nums, int k) { 4 | deque q; 5 | vector res; 6 | 7 | for (int i = 0; i < k; i++) { 8 | while(!q.empty() && nums[q.back()] <= nums[i]) { 9 | q.pop_back(); 10 | } 11 | q.push_back(i); 12 | } 13 | 14 | res.push_back(nums[q.front()]); 15 | 16 | for (int i = k; i < nums.size(); i++) { 17 | if (q.front() <= i - k) { 18 | q.pop_front(); 19 | } 20 | 21 | while(!q.empty() && nums[q.back()] <= nums[i]) { 22 | q.pop_back(); 23 | } 24 | q.push_back(i); 25 | 26 | res.push_back(nums[q.front()]); 27 | } 28 | return res; 29 | } 30 | }; -------------------------------------------------------------------------------- /Week_05/Practicum/Sliding Window Maximum.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | 3 | class Solution: 4 | def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]: 5 | ans = [] 6 | dq = deque() 7 | 8 | for i in range(len(nums)): 9 | # Remove all numbers in the back, which are less than the incoming 10 | # We keep it decreasing that way, so that the front is always the answer 11 | while dq and dq[-1] < nums[i]: 12 | dq.pop() 13 | 14 | dq.append(nums[i]) 15 | 16 | # We are removing the max 17 | if i >= k and dq[0] == nums[i - k]: 18 | dq.popleft() 19 | 20 | if i >= k - 1: 21 | ans.append(dq[0]) 22 | 23 | return ans 24 | 25 | -------------------------------------------------------------------------------- /Week_05/Practicum/Valid Parentheses.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Solution { 5 | public: 6 | bool isValid(string s) { 7 | stack open; 8 | 9 | for (char ch : s) { 10 | if (ch == '(' || ch == '{' || ch == '[') { 11 | open.push(ch); 12 | } 13 | else { 14 | if (open.empty()) 15 | return false; 16 | 17 | if ((open.top() == '(' && ch == ')') || 18 | (open.top() == '{' && ch == '}') || 19 | (open.top() == '[' && ch == ']') 20 | ) { 21 | open.pop(); 22 | continue; 23 | } 24 | return false; 25 | } 26 | } 27 | 28 | return open.empty(); 29 | } 30 | 31 | }; -------------------------------------------------------------------------------- /Week_05/Practicum/Valid Parentheses.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isValid(self, s: str) -> bool: 3 | stack = [] 4 | 5 | opening = '([{' 6 | closing = ')]}' 7 | 8 | for c in s: 9 | if c in opening: 10 | stack.append(c) 11 | elif c in closing: 12 | if len(stack) == 0 or closing.index(c) != opening.index(stack[-1]): 13 | return False 14 | else: 15 | stack.pop() 16 | 17 | return True if not len(stack) else False 18 | -------------------------------------------------------------------------------- /Week_05/Practicum/media/blocks-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_05/Practicum/media/blocks-1.png -------------------------------------------------------------------------------- /Week_05/Practicum/media/blocks-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_05/Practicum/media/blocks-2.png -------------------------------------------------------------------------------- /Week_05/Practicum/media/blocks-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_05/Practicum/media/blocks-3.png -------------------------------------------------------------------------------- /Week_05/Seminar/Implementations/Deque/DequeList.hpp: -------------------------------------------------------------------------------- 1 | template 2 | class Deque { 3 | private: 4 | std::list list; 5 | public: 6 | void push_back(const T& value) { 7 | list.push_back(value); 8 | } 9 | void push_front(const T& value) { 10 | list.push_front(value); 11 | } 12 | T& front() { 13 | return list.front(); 14 | } 15 | T& back() { 16 | return list.back(); 17 | } 18 | void pop_front() { 19 | list.pop_front(); 20 | } 21 | void pop_back() { 22 | list.pop_back(); 23 | } 24 | int size() const { 25 | return list.size(); 26 | } 27 | bool empty() const { 28 | return list.empty(); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /Week_05/Seminar/Python/backspace-string-compare-with-eq.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/problems/backspace-string-compare 2 | 3 | from collections import deque 4 | 5 | class Solution: 6 | def backspaceCompare(self, s: str, t: str) -> bool: 7 | s_stack = deque() 8 | for c in s: 9 | if c != "#": 10 | s_stack.appendleft(c) 11 | elif len(s_stack) > 0: 12 | s_stack.popleft() 13 | t_stack = deque() 14 | for c in t: 15 | if c != "#": 16 | t_stack.appendleft(c) 17 | elif len(t_stack) > 0: 18 | t_stack.popleft() 19 | return s_stack == t_stack 20 | -------------------------------------------------------------------------------- /Week_05/Seminar/Python/baseball-game-with-list.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/problems/baseball-game 2 | 3 | class Solution: 4 | def calPoints(self, operations: List[str]) -> int: 5 | scores = [] 6 | for op in operations: 7 | if op == "+": 8 | scores.append(scores[-1] + scores[-2]) 9 | elif op == "D": 10 | scores.append(scores[-1] * 2) 11 | elif op == "C": 12 | scores.pop() 13 | else: 14 | scores.append(int(op)) 15 | return sum(scores) 16 | -------------------------------------------------------------------------------- /Week_05/Seminar/Python/number-of-recent-calls.py: -------------------------------------------------------------------------------- 1 | # https://leetcode.com/problems/number-of-recent-calls 2 | 3 | from collections import deque 4 | 5 | class RecentCounter: 6 | 7 | def __init__(self): 8 | self.queue = deque() 9 | 10 | def ping(self, t: int) -> int: 11 | self.queue.append(t) 12 | while self.queue[0] < t-3000: 13 | self.queue.popleft() 14 | return len(self.queue) 15 | 16 | 17 | # Your RecentCounter object will be instantiated and called as such: 18 | # obj = RecentCounter() 19 | # param_1 = obj.ping(t) 20 | -------------------------------------------------------------------------------- /Week_05/Seminar/PythonAdditional/multidimensional_arrays.py: -------------------------------------------------------------------------------- 1 | one_d_array = [1, 2, 3] 2 | 3 | print(f"one_d_array[0] = {one_d_array[0]}") 4 | 5 | two_d_array = [ 6 | [1, 2, 3], 7 | [4, 5, 6], 8 | ] 9 | 10 | print(f"two_d_array[0][1] = {two_d_array[0][1]}") 11 | 12 | three_d_array = [ 13 | [ 14 | [1, 2], 15 | [3, 4], 16 | [5, 6], 17 | ], 18 | ] 19 | -------------------------------------------------------------------------------- /Week_05/Seminar/PythonAdditional/multidimensional_arrays_1.py: -------------------------------------------------------------------------------- 1 | # https://github.com/telinc1/Introduction-To-Programming-Problems/blob/master/resources/tasks/multidimensional_arrays.md 2 | # Task 1 3 | 4 | def input_matrix_with_comprehension(): 5 | return [int(x) for x in input().split(" ")] 6 | 7 | def input_matrix_with_map(): 8 | return list(map(int, input().split(" "))) 9 | 10 | # rows, columns = [int(x) for x in input().split(" ")] 11 | rows, columns = map(int, input().split(" ")) 12 | 13 | matrix = [] 14 | 15 | for i in range(rows): 16 | row = list(map(int, input().split(" "))) 17 | matrix.append(row) 18 | 19 | # print(matrix) 20 | 21 | for row in matrix: 22 | # print(row, min(row)) 23 | print(min(row)) 24 | -------------------------------------------------------------------------------- /Week_05/Seminar/PythonAdditional/multidimensional_arrays_2.py: -------------------------------------------------------------------------------- 1 | # https://github.com/telinc1/Introduction-To-Programming-Problems/blob/master/resources/tasks/multidimensional_arrays.md 2 | # Task 2 3 | 4 | rows, columns = map(int, input().split(" ")) 5 | 6 | matrix = [] 7 | 8 | for i in range(rows): 9 | row = list(map(int, input().split(" "))) 10 | matrix.append(row) 11 | 12 | for row in matrix: 13 | for num in row: 14 | counter = 0 15 | if num < 0: 16 | counter += 1 17 | 18 | print(counter) 19 | -------------------------------------------------------------------------------- /Week_05/Seminar/Solutions/MonotonicStack/DailyTemperatures.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector dailyTemperatures(vector& temperatures) { 4 | vector result(temperatures.size(), 0); 5 | 6 | // contains indexes of elements in decreasing order 7 | stack ms; // ms - monotonic stack 8 | for(size_t i = 0; i < temperatures.size(); i++) { 9 | // pop all indexes of elements which are lower than the new temperature 10 | while(!ms.empty() && temperatures[ms.top()] < temperatures[i]) { 11 | // for each popped index write in the result 12 | result[ms.top()] = i - ms.top(); 13 | ms.pop(); 14 | } 15 | 16 | ms.push(i); 17 | } 18 | 19 | return result; 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /Week_05/Seminar/Solutions/QueueAndStack/MaximumNestingDepthoftheParentheses.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int maxDepth(string s) { 4 | int i = 0; 5 | int max = 0; 6 | for(auto ch: s) { 7 | if(ch == '(') { 8 | i++; 9 | if(i > max) { 10 | max = i; 11 | } 12 | } 13 | else if(ch == ')') { 14 | i--; 15 | } 16 | } 17 | 18 | return max; 19 | } 20 | }; -------------------------------------------------------------------------------- /Week_05/Seminar/Solutions/QueueAndStack/NumberOfRecentCalls.cpp: -------------------------------------------------------------------------------- 1 | class RecentCounter { 2 | public: 3 | queue container; 4 | 5 | int ping(int t) { 6 | while(!container.empty() && container.front() < t - 3000) { 7 | container.pop(); 8 | } 9 | container.push(t); 10 | 11 | return container.size(); 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /Week_05/Seminar/Solutions/QueueAndStack/RemoveAllAdjacentDuplicatesInString.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | string removeDuplicates(string s) { 4 | // used as stack 5 | string result; 6 | 7 | for(auto ch: s) { 8 | if(result.size() == 0) { 9 | result.push_back(ch); 10 | continue; 11 | } 12 | 13 | if(result.back() == ch) { 14 | result.pop_back(); 15 | } 16 | else { 17 | result.push_back(ch); 18 | } 19 | } 20 | 21 | return result; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /Week_05/Seminar/Solutions/QueueAndStack/ValidParentheses.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool isOpening(char ch) { 4 | return ch == '(' || ch == '{' || ch == '['; 5 | } 6 | bool isReversed(char l, char r) { 7 | return (l == '(' && r == ')') 8 | || (l == '{' && r == '}') 9 | || (l == '[' && r == ']'); 10 | } 11 | bool isValid(string s) { 12 | stack container; 13 | for(auto ch: s) { 14 | if(isOpening(ch)) { 15 | container.push(ch); 16 | } 17 | else { 18 | if(container.empty() || !isReversed(container.top(), ch)) { 19 | return false; 20 | } 21 | 22 | container.pop(); 23 | } 24 | } 25 | 26 | return container.size() == 0; 27 | } 28 | }; -------------------------------------------------------------------------------- /Week_05/Seminar/Solutions/SlidingWindow/MaximumAverageSubarray_array.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | double findMaxAverage(vector& nums, int k) { 4 | double sum = 0; 5 | for(size_t i = 0; i < k; i++) { 6 | sum += nums[i]; 7 | } 8 | 9 | double currentSum = sum; 10 | for(size_t i = k; i < nums.size(); i++) { 11 | currentSum = (currentSum - nums[i - k] + nums[i]); 12 | if(sum < currentSum) { 13 | sum = currentSum; 14 | } 15 | } 16 | 17 | return sum / k; 18 | } 19 | }; -------------------------------------------------------------------------------- /Week_05/Seminar/Solutions/SlidingWindow/MaximumAverageSubarray_queue.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | double findMaxAverage(vector& nums, int k) { 4 | queue q; 5 | double sum = 0; 6 | for(size_t i = 0; i < k; i++) { 7 | q.push(nums[i]); 8 | sum += nums[i]; 9 | } 10 | 11 | // find max sum and divide by k for the result 12 | double currentSum = sum; 13 | for(size_t i = k; i < nums.size(); i++) { 14 | currentSum = (currentSum - q.front() + nums[i]); 15 | q.pop(); 16 | q.push(nums[i]); 17 | if(currentSum > sum) { 18 | sum = currentSum; 19 | } 20 | } 21 | 22 | return sum / k; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /Week_06/Practicum/Binary Tree Level Order Traversal.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector> levelOrder(TreeNode* root) { 4 | if (!root) { 5 | return {}; 6 | } 7 | 8 | std::vector> levelOrder; 9 | std::queue q; 10 | q.push(root); 11 | 12 | while (q.size()) { 13 | std::vector level(q.size()); 14 | for (int i = 0; i < level.size(); ++i) { 15 | TreeNode* node = q.front(); q.pop(); 16 | level[i] = node->val; 17 | 18 | if (node->left) { 19 | q.push(node->left); 20 | } 21 | if (node->right) { 22 | q.push(node->right); 23 | } 24 | } 25 | 26 | levelOrder.push_back(level); 27 | } 28 | 29 | return levelOrder; 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /Week_06/Practicum/Binary Tree Level Order Traversal.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | 8 | def bfs(root): 9 | q = deque([root]) 10 | 11 | ans = [] 12 | 13 | while q: 14 | # Each iteration here holds exactly one level of the tree 15 | ans.append([node.val for node in q]) 16 | for _ in range(len(q)): 17 | current = q.popleft() 18 | 19 | if current.left: 20 | q.append(current.left) 21 | if current.right: 22 | q.append(current.right) 23 | 24 | return ans 25 | 26 | class Solution: 27 | def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]: 28 | return bfs(root) if root else [] -------------------------------------------------------------------------------- /Week_06/Practicum/Binary Tree Preorder Traversal.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | void dfs(TreeNode* node, vector& traversal) { 4 | if (!node) { 5 | return; 6 | } 7 | 8 | traversal.push_back(node->val); 9 | dfs(node->left, traversal); 10 | dfs(node->right, traversal); 11 | } 12 | 13 | vector preorderTraversal(TreeNode* root) { 14 | vector traversal; 15 | dfs(root, traversal); 16 | return traversal; 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /Week_06/Practicum/Binary Tree Preorder Traversal.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | 8 | def dfs(node): 9 | if node is None: 10 | return [] 11 | 12 | return [node.val] + dfs(node.left) + dfs(node.right) 13 | 14 | class Solution: 15 | def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]: 16 | return dfs(root) -------------------------------------------------------------------------------- /Week_06/Practicum/Binary Tree Right Side View.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | 8 | def bfs(root): 9 | q = deque([root]) 10 | 11 | ans = [] 12 | 13 | while q: 14 | ans.append(q[-1].val) 15 | for _ in range(len(q)): 16 | current = q.popleft() 17 | 18 | if current.left: 19 | q.append(current.left) 20 | if current.right: 21 | q.append(current.right) 22 | 23 | return ans 24 | 25 | class Solution: 26 | def rightSideView(self, root: Optional[TreeNode]) -> List[int]: 27 | return bfs(root) if root else [] -------------------------------------------------------------------------------- /Week_06/Practicum/Contains Duplicate III.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool containsNearbyAlmostDuplicate(vector& nums, int indexDiff, int valueDiff) { 4 | deque window; 5 | multiset values; 6 | 7 | for(int i = 0; i < nums.size(); i++){ 8 | int cur = nums[i]; 9 | window.push_back(cur); 10 | 11 | if(window.size() > indexDiff + 1){ 12 | values.erase(window.front()); 13 | window.pop_front(); 14 | } 15 | 16 | auto find = values.upper_bound(cur); 17 | 18 | if((find != values.end() && abs(cur - *find) <= valueDiff) || 19 | (find != values.begin() && abs(cur - (*prev(find))) <= valueDiff)){ 20 | return true; 21 | } 22 | 23 | values.insert(cur); 24 | } 25 | 26 | return false; 27 | } 28 | }; -------------------------------------------------------------------------------- /Week_06/Practicum/Maximum Depth of Binary Tree.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | int dfs(TreeNode* node) { 3 | if (!node) { 4 | return 0; 5 | } 6 | 7 | return 1 + std::max(dfs(node->left), dfs(node->right)); 8 | } 9 | 10 | public: 11 | int maxDepth(TreeNode* root) { 12 | return dfs(root); 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /Week_06/Practicum/Maximum Depth of Binary Tree.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | 8 | def dfs(node, depth): 9 | if node is None: 10 | return depth 11 | 12 | return max(dfs(node.left, depth + 1), dfs(node.right, depth + 1)) 13 | 14 | class Solution: 15 | def maxDepth(self, root: Optional[TreeNode]) -> int: 16 | return dfs(root, 0) -------------------------------------------------------------------------------- /Week_06/Practicum/Maximum Depth of N-ary Tree.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | int dfs(Node* root) { 3 | if (!root) { 4 | return 0; 5 | } 6 | 7 | int depth = 0; 8 | for (auto* child: root->children) { 9 | depth = std::max(depth, dfs(child)); 10 | } 11 | 12 | return depth + 1; 13 | } 14 | 15 | public: 16 | int maxDepth(Node* root) { 17 | return dfs(root); 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /Week_06/Practicum/media/avl-double-rotation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_06/Practicum/media/avl-double-rotation.png -------------------------------------------------------------------------------- /Week_06/Practicum/media/avl-simple-rotation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_06/Practicum/media/avl-simple-rotation.png -------------------------------------------------------------------------------- /Week_06/Practicum/media/red-black-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_06/Practicum/media/red-black-tree.png -------------------------------------------------------------------------------- /Week_06/Practicum/media/unbalanced-avl-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_06/Practicum/media/unbalanced-avl-tree.png -------------------------------------------------------------------------------- /Week_06/Seminar/Solutions/Bonus/BSTToGreaterTree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 8 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 9 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 10 | * }; 11 | */ 12 | class Solution { 13 | void inorderReversed(TreeNode* root, int& sum) { 14 | if(!root) { 15 | return; 16 | } 17 | 18 | inorderReversed(root->right, sum); 19 | sum += root->val; 20 | root->val = sum; 21 | inorderReversed(root->left, sum); 22 | } 23 | public: 24 | TreeNode* convertBST(TreeNode* root) { 25 | int sum = 0; 26 | inorderReversed(root, sum); 27 | return root; 28 | } 29 | }; -------------------------------------------------------------------------------- /Week_06/Seminar/Solutions/Fundamentals/InsertIntoBST/Recusive.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 8 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 9 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 10 | * }; 11 | */ 12 | class Solution { 13 | public: 14 | TreeNode* insertIntoBST(TreeNode* root, int val) { 15 | if(!root) { 16 | return new TreeNode(val); 17 | } 18 | 19 | if(root->val > val) { 20 | root->left = insertIntoBST(root->left, val); 21 | } 22 | else { 23 | root->right = insertIntoBST(root->right, val); 24 | } 25 | 26 | return root; 27 | } 28 | }; -------------------------------------------------------------------------------- /Week_06/Seminar/Solutions/Fundamentals/MaxDepthOfBinaryTree/Recursive.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 8 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 9 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 10 | * }; 11 | */ 12 | class Solution { 13 | public: 14 | int maxDepth(TreeNode* root) { 15 | if(!root) { 16 | return 0; 17 | } 18 | return 1 + max(maxDepth(root->left), maxDepth(root->right)); 19 | } 20 | }; -------------------------------------------------------------------------------- /Week_06/Seminar/Solutions/Fundamentals/SearchInBinaryTree/Iterative.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 8 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 9 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 10 | * }; 11 | */ 12 | class Solution { 13 | public: 14 | TreeNode* searchBST(TreeNode* root, int val) { 15 | while(root && root->val != val) { 16 | if(root->val > val) { 17 | root = root->left; 18 | } 19 | else { 20 | root = root->right; 21 | } 22 | } 23 | 24 | return root; 25 | } 26 | }; -------------------------------------------------------------------------------- /Week_06/Seminar/Solutions/Fundamentals/SearchInBinaryTree/Recursive.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 8 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 9 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 10 | * }; 11 | */ 12 | class Solution { 13 | public: 14 | TreeNode* searchBST(TreeNode* root, int val) { 15 | if(!root || root->val == val) { 16 | return root; 17 | } 18 | 19 | return (root->val > val) ? searchBST(root->left, val) : searchBST(root->right, val); 20 | } 21 | }; -------------------------------------------------------------------------------- /Week_06/Seminar/Solutions/Other/SameTree/Dfs.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 8 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 9 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 10 | * }; 11 | */ 12 | class Solution { 13 | public: 14 | bool isSameTree(TreeNode* p, TreeNode* q) { 15 | if(!p && !q) { 16 | return true; 17 | } 18 | if(!p || !q) { 19 | return false; 20 | } 21 | 22 | return p->val == q->val && isSameTree(p->left, q->left) && isSameTree(p->right, q->right); 23 | } 24 | }; -------------------------------------------------------------------------------- /Week_06/Seminar/Solutions/Other/SymetricTree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * struct TreeNode { 4 | * int val; 5 | * TreeNode *left; 6 | * TreeNode *right; 7 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} 8 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 9 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 10 | * }; 11 | */ 12 | class Solution { 13 | bool areSymetric(TreeNode* t1, TreeNode* t2) { 14 | if(!t1 && !t2) { 15 | return true; 16 | } 17 | if(!t1 || !t2) { 18 | return false; 19 | } 20 | 21 | return t1->val == t2->val && areSymetric(t1->left, t2->right) && areSymetric(t1->right, t2->left); 22 | } 23 | public: 24 | bool isSymmetric(TreeNode* root) { 25 | return areSymetric(root->left, root->right); 26 | } 27 | }; -------------------------------------------------------------------------------- /Week_07/Practicum/Climbing Stairs.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def climbStairs(self, n: int) -> int: 3 | # In the array we will keep the number of times we can climb a given stair 4 | # the first and second can be climbed once. 5 | dp = [1, 1] 6 | 7 | for i in range(2, n + 1): 8 | # Stair i, can be climbed the number of times you can climb stair (i - 1) + stair (i - 2) 9 | dp.append(dp[i - 1] + dp[i - 2]) 10 | 11 | return dp[n] -------------------------------------------------------------------------------- /Week_07/Practicum/Longest Increasing Subsequence.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def lengthOfLIS(self, nums) -> int: 3 | dp = [] 4 | for i in range(len(nums)): 5 | # for each i we will give an answer what is the length of the LIS that ends with 6 | # nums[i]. The base case is 1, each number can make a subsequence of length 1. 7 | dp.append(1) 8 | for j in range(i): 9 | if nums[j] < nums[i]: 10 | # If a number before nums[i] is lower than nums[i], then we can 11 | # make a longer increasing subsequence by 1 over the one we can make 12 | # ending with nums[j] 13 | dp[i] = max(dp[i], dp[j] + 1) 14 | 15 | 16 | return max(dp) 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Week_07/Practicum/Min Cost Climbing Stairs.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def minCostClimbingStairs(self, cost: List[int]) -> int: 3 | dp = [cost[0], cost[1]] 4 | 5 | for i in range(2, len(cost)): 6 | dp.append(min(dp[i - 1], dp[i - 2]) + cost[i]) 7 | 8 | return min(dp[len(cost) - 1], dp[len(cost) - 2]) -------------------------------------------------------------------------------- /Week_07/Practicum/PythonAdditional/Average of Levels in Binary Tree.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | 8 | def bfs(root): 9 | q = deque([root]) 10 | ans = [] 11 | 12 | while q: 13 | length = len(q) 14 | ans.append(mean([node.val for node in q])) 15 | for _ in range(length): 16 | current = q.popleft() 17 | 18 | if current.left: 19 | q.append(current.left) 20 | if current.right: 21 | q.append(current.right) 22 | 23 | return ans 24 | 25 | 26 | class Solution: 27 | def averageOfLevels(self, root: Optional[TreeNode]) -> List[float]: 28 | return bfs(root) -------------------------------------------------------------------------------- /Week_07/Practicum/PythonAdditional/Deepest Leaves Sum.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | 8 | def bfs(root): 9 | q = deque([root]) 10 | 11 | 12 | while q: 13 | length = len(q) 14 | 15 | ans = [node.val for node in q] 16 | for _ in range(length): 17 | current = q.popleft() 18 | 19 | if current.left: 20 | q.append(current.left) 21 | if current.right: 22 | q.append(current.right) 23 | 24 | return sum(ans) 25 | 26 | class Solution: 27 | def deepestLeavesSum(self, root: Optional[TreeNode]) -> int: 28 | return bfs(root) -------------------------------------------------------------------------------- /Week_07/Practicum/PythonAdditional/Invert Binary Tree.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]: 9 | 10 | if root is None: 11 | return None 12 | 13 | root.left, root.right = self.invertTree(root.right), self.invertTree(root.left) 14 | 15 | return root -------------------------------------------------------------------------------- /Week_07/Practicum/PythonAdditional/Minimum Distance Between BST Nodes.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | 8 | prev = -2 ** 31 9 | min_ = 2 ** 31 10 | 11 | def dfs(node): 12 | if node is None: 13 | return 14 | 15 | global prev 16 | global min_ 17 | 18 | dfs(node.left) 19 | min_ = min(min_, node.val - prev) 20 | prev = node.val 21 | dfs(node.right) 22 | 23 | 24 | class Solution: 25 | def minDiffInBST(self, root: Optional[TreeNode]) -> int: 26 | global min_ 27 | global prev 28 | prev = -2 ** 31 29 | min_ = 2 ** 31 30 | 31 | dfs(root) 32 | 33 | return min_ -------------------------------------------------------------------------------- /Week_07/Practicum/PythonAdditional/Sum of Left Leaves.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | 8 | def dfs(node, is_left): 9 | if node is None: 10 | return 0 11 | 12 | if node.left is None and node.right is None and is_left: 13 | return node.val 14 | 15 | return dfs(node.left, True) + dfs(node.right, False) 16 | 17 | class Solution: 18 | def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int: 19 | if root is None: 20 | return 0 21 | 22 | return dfs(root, False) 23 | 24 | -------------------------------------------------------------------------------- /Week_07/Practicum/PythonAdditional/Tasks.md: -------------------------------------------------------------------------------- 1 | # Задачи 2 | 3 | - https://leetcode.com/problems/sum-of-left-leaves/description/ 4 | - https://leetcode.com/problems/invert-binary-tree/description/ 5 | - https://leetcode.com/problems/merge-two-binary-trees/description/ 6 | - https://leetcode.com/problems/employee-importance/description/ 7 | - https://leetcode.com/problems/average-of-levels-in-binary-tree/ 8 | - https://leetcode.com/problems/deepest-leaves-sum/ 9 | - https://leetcode.com/problems/maximum-level-sum-of-a-binary-tree/ 10 | - https://leetcode.com/problems/minimum-distance-between-bst-nodes/description/ -------------------------------------------------------------------------------- /Week_07/Practicum/Tasks.md: -------------------------------------------------------------------------------- 1 | # Задачи 2 | 3 | - https://leetcode.com/problems/climbing-stairs/ - EASY 4 | - https://leetcode.com/problems/min-cost-climbing-stairs/description/ - EASY 5 | - https://leetcode.com/problems/unique-paths/description/ - EASY 6 | - https://leetcode.com/problems/unique-paths-ii/ - MEDIUM 7 | - https://leetcode.com/problems/unique-paths-iii/description/ - MEDIUM 8 | - https://leetcode.com/problems/guess-number-higher-or-lower-ii/description/ - MEDIUM 9 | - https://leetcode.com/problems/longest-increasing-subsequence/description/ - HARD -------------------------------------------------------------------------------- /Week_07/Practicum/Unique Paths II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int: 3 | m = len(obstacleGrid) 4 | n = len(obstacleGrid[0]) 5 | 6 | dp = [ 7 | [0 for _ in range(n)] for _ in range(m) 8 | ] 9 | 10 | for i in range(m): 11 | if obstacleGrid[i][0] == 1: 12 | break 13 | dp[i][0] = 1 14 | 15 | for i in range(n): 16 | if obstacleGrid[0][i] == 1: 17 | break 18 | dp[0][i] = 1 19 | 20 | for i in range(1, m): 21 | for j in range(1, n): 22 | if obstacleGrid[i][j] == 1: 23 | continue 24 | dp[i][j] = dp[i - 1][j] + dp[i][j - 1] 25 | 26 | return dp[-1][-1] -------------------------------------------------------------------------------- /Week_07/Practicum/Unique Paths.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def uniquePaths(self, m: int, n: int) -> int: 3 | dp = [ 4 | [0 for _ in range(n)] for _ in range(m) 5 | ] 6 | 7 | # Initialize empty matrix 8 | # [[0, 0, 0] 9 | # [0, 0, 0] 10 | # [0, 0, 0]] 11 | 12 | for i in range(m): 13 | dp[i][0] = 1 14 | 15 | for i in range(n): 16 | dp[0][i] = 1 17 | 18 | # [[1, 1, 1] 19 | # [1, 0, 0] 20 | # [1, 0, 0]] 21 | 22 | 23 | # Fill in the remaining zeros 24 | for i in range(1, m): 25 | for j in range(1, n): 26 | dp[i][j] = dp[i - 1][j] + dp[i][j - 1] 27 | 28 | return dp[-1][-1] -------------------------------------------------------------------------------- /Week_07/Seminar/Solutions/Lab/Fibonacci/BottomUpApproach.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int fib(int n) { 4 | if (n == 0 || n == 1) { 5 | return n; 6 | } 7 | 8 | long long prevPrev = 0, prev = 1, curr; 9 | for (size_t i = 2; i <= n; i++) { 10 | curr = prevPrev + prev; 11 | prevPrev = prev; 12 | prev = curr; 13 | } 14 | return curr; 15 | } 16 | }; -------------------------------------------------------------------------------- /Week_07/Seminar/Solutions/Lab/Fibonacci/TopDownApproach.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int fib(int n) { 4 | if(n == 1 || n == 0) { 5 | return n; 6 | } 7 | 8 | static int dp[31]{}; 9 | if(dp[n] == 0) { 10 | dp[n] = fib(n - 1) + fib(n - 2); 11 | } 12 | 13 | return dp[n]; 14 | } 15 | }; -------------------------------------------------------------------------------- /Week_07/Seminar/Solutions/Lab/HouseRobber/ConstantMemory.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int rob(vector& nums) { 4 | if(nums.size() == 0) { 5 | return 0; 6 | } 7 | 8 | if(nums.size() == 1) { 9 | return nums[0]; 10 | } 11 | 12 | int first = nums[0]; 13 | int second = max(nums[0], nums[1]); 14 | 15 | for(size_t i = 2; i < nums.size(); i++) { 16 | int temp = second; 17 | second = max(second, first + nums[i]); 18 | first = temp; 19 | } 20 | 21 | return second; 22 | } 23 | }; -------------------------------------------------------------------------------- /Week_07/Seminar/Solutions/Lab/HouseRobber/DpArray.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int rob(vector& nums) { 4 | if(nums.size() == 1) { 5 | return nums[0]; 6 | } 7 | 8 | vector maxDP(nums.size(), 0); 9 | 10 | maxDP[0] = nums[0]; 11 | maxDP[1] = max(nums[0], nums[1]); 12 | 13 | for(size_t i = 2; i < nums.size(); i++) { 14 | maxDP[i] = max(maxDP[i - 1], nums[i] + maxDP[i - 2]); 15 | } 16 | 17 | return maxDP[maxDP.size() - 1]; 18 | } 19 | }; -------------------------------------------------------------------------------- /Week_07/Seminar/Solutions/Lab/LCS/Solution.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int longestCommonSubsequence(string text1, string text2) { 4 | // one extra row and cols for empty string 5 | // https://www.geeksforgeeks.org/longest-common-subsequence-dp-4/ 6 | vector> dp(text1.size() + 1, vector(text2.size() + 1, 0)); 7 | 8 | for(size_t i = 0; i < text1.size(); i++) { 9 | for(size_t j = 0; j < text2.size(); j++) { 10 | if(text1[i] == text2[j]) { 11 | dp[i + 1][j + 1] = dp[i][j] + 1; 12 | } 13 | else { 14 | dp[i + 1][j + 1] = max(dp[i][j + 1], dp[i + 1][j]); 15 | } 16 | } 17 | } 18 | 19 | return dp[text1.size()][text2.size()]; 20 | } 21 | }; -------------------------------------------------------------------------------- /Week_07/Seminar/Solutions/Lab/UniquePaths2/OnlyOneRow.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int uniquePathsWithObstacles(vector>& obstacleGrid) { 4 | int m = obstacleGrid.size(); 5 | int n = obstacleGrid[0].size(); 6 | vector dp(n, 0); 7 | 8 | for(int i = 0; i < n; i++) { 9 | if(obstacleGrid[0][i] == 1) { 10 | break; 11 | } 12 | dp[i] = 1; 13 | } 14 | 15 | for(int i = 1; i < m; i++) { 16 | if(obstacleGrid[i][0] == 1) { 17 | dp[0] = 0; 18 | } 19 | for(int j = 1; j < n; j++) { 20 | if(obstacleGrid[i][j] == 1) { 21 | dp[j] = 0; 22 | continue; 23 | } 24 | dp[j] += dp[j - 1]; 25 | } 26 | } 27 | 28 | return dp[n - 1]; 29 | } 30 | }; -------------------------------------------------------------------------------- /Week_07/Seminar/Solutions/Lecture/CoinChecker/Solution.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int coinChange(vector& coins, int amount) { 4 | vector dp(amount + 1, INT_MAX); 5 | dp[0] = 0; 6 | 7 | // i is current value 8 | for(int i = 1; i <= amount; i++) { 9 | for (int coin : coins) { 10 | if (i >= coin && dp[i - coin] != INT_MAX) { 11 | dp[i] = min(dp[i], dp[i - coin] + 1); 12 | } 13 | } 14 | } 15 | 16 | return dp[amount] == INT_MAX ? -1 : dp[amount]; 17 | } 18 | }; -------------------------------------------------------------------------------- /Week_07/Seminar/Solutions/Lecture/LIS/Solution.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int lengthOfLIS(vector& nums) { 4 | vector dp(nums.size()); 5 | 6 | for(size_t i = 0; i < nums.size(); i++) { 7 | dp[i] = 1; 8 | for(size_t j = 0; j < i; j++) { 9 | if(nums[j] < nums[i]) { 10 | dp[i] = max(dp[i], 1 + dp[j]); 11 | } 12 | } 13 | } 14 | 15 | return *max_element(dp.begin(), dp.end()); 16 | } 17 | }; -------------------------------------------------------------------------------- /Week_07/Seminar/Solutions/Lecture/MinimumPathSum/UsingTheInputAsDP.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int minPathSum(vector>& grid) { 4 | int m = grid.size(); 5 | int n = grid[0].size(); 6 | 7 | // sum first col 8 | for(int i = 1; i < m; i++) { 9 | grid[i][0] += grid[i - 1][0]; 10 | } 11 | // sum first row 12 | for(int i = 1; i < n; i++) { 13 | grid[0][i] += grid[0][i - 1]; 14 | } 15 | 16 | for(int i = 1; i < m; i++) { 17 | for(int j = 1; j < n; j++) { 18 | // dp[i][j] = grid[i][j] + min(dp[i - 1][j], dp[i][j - 1]) 19 | grid[i][j] += min(grid[i - 1][j], grid[i][j - 1]); 20 | } 21 | } 22 | 23 | return grid[m - 1][n - 1]; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /Week_07/Seminar/Solutions/Other/ClimbingStairs/Solution.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int climbStairs(int n) { 4 | if(n == 1 || n == 2) { 5 | return n; 6 | } 7 | 8 | static int dp[46]{}; 9 | if(dp[n] == 0) { 10 | dp[n] = climbStairs(n - 2) + climbStairs(n - 1); 11 | } 12 | 13 | return dp[n]; 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /Week_07/Seminar/Solutions/Other/JumpGame/Solution.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool canJump(vector& nums) { 4 | int maxReach = 0; 5 | for(int i = 0; i < nums.size(); i++) { 6 | if(maxReach < i) { 7 | return false; 8 | } 9 | maxReach = max(maxReach, i + nums[i]); 10 | } 11 | return true; 12 | } 13 | }; -------------------------------------------------------------------------------- /Week_07/Seminar/Solutions/Other/MinCostClimbingStairs/Solutions.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int minCostClimbingStairs(vector& cost) { 4 | vector dp(cost.size() + 1, 0); 5 | for(size_t i = 2; i < dp.size(); i++) { 6 | dp[i] = min(dp[i - 2] + cost[i - 2], dp[i - 1] + cost[i - 1]); 7 | } 8 | 9 | return dp.back(); 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /Week_08/Practicum/Distribute Candies.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int distributeCandies(vector& candyType) { 4 | unordered_map candies; 5 | for (int candy : candyType) { 6 | candies[candy]++; 7 | } 8 | 9 | return min(candyType.size() / 2, candies.size()); 10 | } 11 | }; -------------------------------------------------------------------------------- /Week_08/Practicum/Distribute Candies.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def distributeCandies(self, candyType: List[int]) -> int: 3 | set_unique_candies = set(candyType) 4 | 5 | return min(len(set_unique_candies), len(candyType) // 2) -------------------------------------------------------------------------------- /Week_08/Practicum/Find Occurrences of an Element in an Array.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def occurrencesOfElement(self, nums: List[int], queries: List[int], x: int) -> List[int]: 3 | d = dict() 4 | counter = 1 5 | for i, num in enumerate(nums): 6 | if num == x: 7 | d[counter] = i 8 | counter += 1 9 | 10 | ans = [] 11 | 12 | for query in queries: 13 | if query in d.keys(): 14 | ans.append(d[query]) 15 | else: 16 | ans.append(-1) 17 | 18 | return ans -------------------------------------------------------------------------------- /Week_08/Practicum/Find Unique Binary String.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findDifferentBinaryString(self, nums: List[str]) -> str: 3 | n = len(nums[0]) 4 | nums = set(nums) 5 | for i in range(2 ** n): 6 | if format(i, f"0{n}b") not in nums: 7 | return format(i, f"0{n}b") -------------------------------------------------------------------------------- /Week_08/Practicum/Maximum Erasure Value.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maximumUniqueSubarray(self, nums: List[int]) -> int: 3 | ans = [] 4 | current_sum = 0 5 | q = deque() 6 | s = set() 7 | 8 | for num in nums: 9 | if num in s: 10 | while q and q[0] != num: 11 | current_sum -= q[0] 12 | s.remove(q[0]) 13 | q.popleft() 14 | current_sum -= num 15 | s.remove(num) 16 | q.popleft() 17 | 18 | q.append(num) 19 | current_sum += num 20 | s.add(num) 21 | ans.append(current_sum) 22 | 23 | return max(ans) -------------------------------------------------------------------------------- /Week_08/Practicum/Shortest Impossible Sequence of Rolls.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def shortestSequence(self, rolls: List[int], k: int) -> int: 3 | s = set() 4 | ans = 0 5 | 6 | for roll in rolls: 7 | s.add(roll) 8 | if len(s) == k: 9 | s = set() 10 | ans += 1 11 | 12 | return ans + 1 -------------------------------------------------------------------------------- /Week_08/Practicum/Two Sum.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector twoSum(vector& nums, int target) { 4 | std::unordered_map values; // value -> index 5 | for (int i = 0; i < nums.size(); ++i) { 6 | if (values.count(target - nums[i])) { 7 | return { values[target - nums[i]], i}; 8 | } 9 | values[nums[i]] = i; 10 | } 11 | 12 | return {}; 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /Week_08/Practicum/Two Sum.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def twoSum(self, nums: List[int], target: int) -> List[int]: 3 | d = dict() 4 | 5 | for i, num in enumerate(nums): 6 | d[num] = i 7 | 8 | for i, num in enumerate(nums): 9 | if target - num in d.keys() and i != d[target - num]: 10 | return [i, d[target - num]] 11 | -------------------------------------------------------------------------------- /Week_08/Seminar/Examples/HashMapWithCustomStructAsKey.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct MyStruct { 6 | int a; 7 | int b; 8 | 9 | bool operator==(const MyStruct& other) const { 10 | return a == other.a && b == other.b; 11 | } 12 | }; 13 | 14 | struct MyStructHash { 15 | size_t operator()(const MyStruct& s) const { 16 | return std::hash()(s.a) ^ std::hash()(s.b); 17 | } 18 | }; 19 | 20 | int main() { 21 | // hashmap requires calculating hashcodes and equal operator 22 | std::unordered_map myMap; 23 | 24 | MyStruct s1{ 1, 2 }; 25 | myMap[s1] = 3; 26 | 27 | for(auto& kvp: myMap) { 28 | std::cout << kvp.first.a << " " << kvp.first.b << " " << kvp.second << std::endl; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Week_08/Seminar/Examples/MultiMapExample.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | std::multimap mymap; 7 | 8 | mymap.insert(std::pair(1, 10)); 9 | mymap.insert(std::pair(2, 20)); 10 | mymap.insert(std::pair(1, 30)); 11 | 12 | std::cout << "mymap contains:\n"; 13 | for(auto& kvp: mymap) { 14 | std::cout << kvp.first << " => " << kvp.second << '\n'; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Week_08/Seminar/HelpingExplanations.md: -------------------------------------------------------------------------------- 1 | # Допълнително readme с драсканици 2 | 3 | ## Balance 4 | 5 | https://docs.google.com/presentation/d/1XmkBoGKyNagmE8YJnY47NOB0dYE-M6AkWnt7zg9NJfM/edit#slide=id.g49904bba26_1_40 6 | 7 | ![image](https://github.com/user-attachments/assets/5a182ed8-0b34-485c-961f-b72c36c98b1b) 8 | 9 | 10 | # Откъде идват наименованията 11 | ![image](https://github.com/user-attachments/assets/108d4495-b46f-40c5-afa5-8a499d78be04) 12 | 13 | ![image](https://github.com/user-attachments/assets/4f68cb45-ce8f-403f-a415-a745bc72293f) 14 | 15 | 16 | ### Справяне с колизии с Separate chaining 17 | ![image](https://github.com/user-attachments/assets/f1d4084b-b697-49d6-aa72-48b750ede800) 18 | 19 | 20 | ### Справяне с колизии с Linear probing 21 | ![image](https://github.com/user-attachments/assets/47b5b0b7-bc5c-4122-a5a4-6d4b751481b0) 22 | -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/0-1_subarray/SumZero.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int findMaxLength(vector& nums) { 4 | // key - sum 5 | // val - first occurence of that sum 6 | unordered_map c; 7 | c[0] = -1; // sum was zero before the start of traversal 8 | int sum = 0; 9 | int maxLength = 0; 10 | for(int i = 0; i < nums.size(); i++) { 11 | sum += (nums[i] == 1 ? 1 : -1); 12 | auto iter = c.find(sum); 13 | if(iter != c.end()) { 14 | maxLength = max(maxLength, i - iter->second); 15 | } 16 | else { 17 | c[sum] = i; 18 | } 19 | } 20 | return maxLength; 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/0-1_subarray/solution_sum_zero.py: -------------------------------------------------------------------------------- 1 | N = int(input()) 2 | arr = list(map(int, input().split())) 3 | 4 | # Converting all zeros to -1 5 | arr = [el if el == 1 else -1 for el in arr] 6 | 7 | # Finding the longest subarray with sum k = 0 8 | current_sum = 0 9 | longest = 0 10 | 11 | d = {} 12 | d[0] = 0 13 | 14 | for i, el in enumerate(arr): 15 | current_sum += el 16 | 17 | if current_sum in d: 18 | length = i - d[current_sum] 19 | longest = max(length, longest) 20 | else: 21 | d[current_sum] = i 22 | 23 | print(longest) -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/contains_duplicate_ii/solution_dict.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool: 3 | d = {} 4 | for index, number in enumerate(nums): 5 | if number in d and d[number] >= index - k: 6 | return True 7 | 8 | d[number] = index 9 | 10 | return False 11 | -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/contains_duplicate_ii/solution_set.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool: 3 | if k == 0: 4 | return False 5 | 6 | s = set() 7 | left = 0 8 | 9 | for right in range(len(nums)): 10 | if nums[right] in s: 11 | return True 12 | 13 | if right >= k: 14 | s.remove(nums[left]) 15 | left += 1 16 | 17 | s.add(nums[right]) 18 | 19 | return False 20 | -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/contains_duplicate_ii/solution_unordered_map.cpp: -------------------------------------------------------------------------------- 1 | class Solution 2 | { 3 | public: 4 | bool containsNearbyDuplicate(vector &nums, int k) 5 | { 6 | unordered_map m; 7 | 8 | for (int i = 0; i < nums.size(); i++) 9 | { 10 | if (m.count(nums[i]) > 0 && m[nums[i]] >= i - k) 11 | { 12 | return true; 13 | } 14 | m[nums[i]] = i; 15 | } 16 | return false; 17 | } 18 | }; -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/count_number_of_bad_pairs/solution_dict.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def countBadPairs(self, nums: List[int]) -> int: 3 | N = len(nums) 4 | all_pairs = N * (N - 1) // 2 5 | good_pairs = 0 6 | 7 | d = {} 8 | 9 | for i, num in enumerate(nums): 10 | target = num - i 11 | if target in d: 12 | good_pairs += d[target] 13 | d[target] += 1 14 | else: 15 | d[target] = 1 16 | 17 | return all_pairs - good_pairs 18 | -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/count_number_of_bad_pairs/solution_unordered_map.cpp: -------------------------------------------------------------------------------- 1 | class Solution 2 | { 3 | public: 4 | long long countBadPairs(vector &nums) 5 | { 6 | long long N, allPairs, goodPairs; 7 | 8 | N = nums.size(); 9 | allPairs = (N * (N - 1)) / 2; 10 | goodPairs = 0; 11 | 12 | unordered_map m; 13 | 14 | for (size_t i = 0; i < N; i++) 15 | { 16 | int target = nums[i] - i; 17 | 18 | if (m.count(target)) 19 | { 20 | goodPairs += m[target]; 21 | } 22 | m[target] += 1; // default is 0 23 | } 24 | 25 | return allPairs - goodPairs; 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/group_anagrams/solution_counting.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def get_hash(self, word): 3 | counts = [0] * 26 4 | 5 | for ch in word: 6 | counts[ord(ch) - ord('a')] += 1 7 | 8 | return tuple(counts) 9 | 10 | def groupAnagrams(self, strs: List[str]) -> List[List[str]]: 11 | d = defaultdict(list) 12 | 13 | for word in strs: 14 | word_hash = self.get_hash(word) 15 | 16 | d[word_hash].append(word) 17 | 18 | return d.values() 19 | -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/group_anagrams/solution_sort.cpp: -------------------------------------------------------------------------------- 1 | class Solution 2 | { 3 | public: 4 | vector> groupAnagrams(vector &strs) 5 | { 6 | unordered_map> mp; 7 | 8 | for (auto x : strs) 9 | { 10 | string word = x; 11 | sort(word.begin(), word.end()); // Can be more efficient! How? 12 | mp[word].push_back(x); 13 | } 14 | 15 | vector> ans; 16 | for (auto x : mp) 17 | { 18 | ans.push_back(x.second); 19 | } 20 | return ans; 21 | } 22 | }; -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/group_anagrams/solution_sort.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | class Solution: 4 | def groupAnagrams(self, strs: List[str]) -> List[List[str]]: 5 | d = defaultdict(list) 6 | 7 | for word in strs: 8 | word_hash = ''.join(sorted(word)) 9 | 10 | d[word_hash].append(word) 11 | 12 | return d.values() 13 | -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/k-diff_pairs_in_an_array/solution_hashmap.cpp: -------------------------------------------------------------------------------- 1 | class Solution 2 | { 3 | public: 4 | int findPairs(std::vector &nums, int k) 5 | { 6 | std::map m; 7 | int count = 0; 8 | 9 | for (size_t i = 0; i < nums.size(); ++i) 10 | { 11 | m[nums[i]]++; 12 | } 13 | 14 | // Try using `auto`, or `for(auto it: m)*` 15 | for (auto it = m.begin(); it != m.end(); ++it) 16 | { 17 | if (k == 0) 18 | { 19 | if (it->second > 1) 20 | { 21 | count++; 22 | } 23 | } 24 | else 25 | { 26 | if (m.count(it->first + k)) 27 | { 28 | count++; 29 | } 30 | } 31 | } 32 | 33 | return count; 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/k-diff_pairs_in_an_array/solution_sets.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findPairs(self, nums: List[int], k: int) -> int: 3 | seen = set() 4 | smaller = set() 5 | 6 | for el in nums: 7 | if el + k in seen: 8 | smaller.add(el) 9 | 10 | if el - k in seen: 11 | smaller.add(el - k) 12 | 13 | seen.add(el) 14 | 15 | return len(smaller) -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/k-diff_pairs_in_an_array/solution_two_hashmaps.cpp: -------------------------------------------------------------------------------- 1 | class Solution 2 | { 3 | public: 4 | int findPairs(vector &nums, int k) 5 | { 6 | unordered_map first, seen; 7 | 8 | for (int num : nums) 9 | { 10 | if (seen[num - k]) 11 | { 12 | first[num - k] = true; 13 | } 14 | if (seen[num + k]) 15 | { 16 | first[num] = true; 17 | } 18 | 19 | seen[num] = true; 20 | } 21 | 22 | return first.size(); 23 | } 24 | }; -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/k-diff_pairs_in_an_array/solution_two_sets.cpp: -------------------------------------------------------------------------------- 1 | using namespace std; 2 | 3 | class Solution 4 | { 5 | public: 6 | int findPairs(vector &nums, int k) 7 | { 8 | unordered_set seen; 9 | set> results; // Can not use unordered_set with pair 10 | 11 | for (int el : nums) 12 | { 13 | if (seen.count(el - k)) 14 | { 15 | results.insert({el - k, el}); 16 | } 17 | if (seen.count(el + k)) 18 | { 19 | results.insert({el, el + k}); 20 | } 21 | seen.insert(el); 22 | } 23 | 24 | return results.size(); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/longest_consecutive_sequence/solution_set.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def longestConsecutive(self, nums: List[int]) -> int: 3 | s = set(nums) 4 | max_count = 0 5 | 6 | for el in nums: 7 | if el - 1 in s: 8 | continue 9 | 10 | current = el + 1 11 | total = 1 12 | 13 | while current in s: 14 | # s.remove(current) --> improves the speed 15 | total += 1 16 | current += 1 17 | 18 | max_count = max(total, max_count) 19 | 20 | return max_count 21 | -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/longest_consecutive_sequence/solution_set_pop.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def longestConsecutive(self, nums: List[int]) -> int: 3 | s = set(nums) 4 | max_length = 0 5 | 6 | while s: 7 | low = high = s.pop() 8 | 9 | while low - 1 in s or high + 1 in s: 10 | if low - 1 in s: 11 | s.remove(low - 1) 12 | low -= 1 13 | 14 | if high + 1 in s: 15 | s.remove(high + 1) 16 | high += 1 17 | 18 | max_length = max(high - low + 1, max_length) 19 | 20 | return max_length -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/longest_consecutive_sequence/solution_sort.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def longestConsecutive(self, nums: List[int]) -> int: 3 | if not nums: 4 | return 0 5 | 6 | nums.sort() 7 | max_count = count = 1 8 | 9 | for i in range(len(nums) - 1): 10 | if nums[i] == nums[i + 1]: 11 | continue 12 | 13 | if nums[i] + 1 == nums[i + 1]: 14 | count += 1 15 | max_count = max(count, max_count) 16 | else: 17 | count = 1 18 | 19 | return max_count 20 | -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/longest_substring_without_repeating_chars/unordered_map.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int lengthOfLongestSubstring(string s) { 4 | // key - character 5 | // value - last seen index 6 | unordered_map c; 7 | 8 | int maxSize = 0; 9 | int currentStart = 0; 10 | for(size_t i = 0; i < s.size(); i++) { 11 | auto iter = c.find(s[i]); 12 | // you should check if the last seen index is before the start! 13 | if(iter != c.end() && iter->second >= currentStart) { 14 | currentStart = iter->second + 1; 15 | } 16 | 17 | c[s[i]] = i; 18 | if(i - currentStart + 1 > maxSize) { 19 | maxSize = i - currentStart + 1; 20 | } 21 | } 22 | return maxSize; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/repeated_dna_sequences/solution_counting.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | class Solution: 3 | def findRepeatedDnaSequences(self, s: str) -> List[str]: 4 | counts = defaultdict(int) 5 | 6 | for i in range(len(s) - 9): 7 | counts[s[i:i+10]] += 1 8 | 9 | return [k for k, v in counts.items() if v > 1] -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/repeated_dna_sequences/solution_set.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findRepeatedDnaSequences(self, s: str) -> List[str]: 3 | results = set() 4 | 5 | for i in range(len(s) - 9): 6 | if s[i:i+10] in s[i+1:]: 7 | results.add(s[i:i+10]) 8 | 9 | return list(results) -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/repeated_dna_sequences/two_set_solution.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector findRepeatedDnaSequences(string s) { 4 | if (s.size() < 10) 5 | return {}; 6 | 7 | set res; 8 | set set; 9 | 10 | set.insert(s.substr(0, 10)); 11 | 12 | for (int i = 1; i <= s.size() - 10; i++) { 13 | string cur = s.substr(i, 10); 14 | if (set.count(cur)) { 15 | res.insert(cur); 16 | } 17 | set.insert(cur); 18 | } 19 | 20 | vector result; 21 | for (auto& el : res) { 22 | result.push_back(el); 23 | } 24 | 25 | return result; 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/subarray_sum_equals_k/solution_dict.py: -------------------------------------------------------------------------------- 1 | """ 2 | Example [3, 4, 7, -2, 2, 1, 4, 2] and k=7 3 | 4 | Sums [0] + [3, 7, 14, 12, 14, 15, 19, 21] 5 | Searches [-4, *0, *7, 5, *7, 8, *12, **14] 6 | 7 | Solutions [3, 4], [7], [7, -2, 2], [2, 1, 4], [-2, 2, 1, 4, 2], [1, 4, 2] 8 | """ 9 | from collections import defaultdict 10 | 11 | class Solution: 12 | def subarraySum(self, nums: List[int], k: int) -> int: 13 | current_sum = 0 14 | count = 0 15 | 16 | d = defaultdict(int) 17 | d[0] = 1 18 | 19 | for el in nums: 20 | current_sum += el 21 | count += d[current_sum - k] 22 | d[current_sum] += 1 23 | 24 | return count -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/subarray_sum_equals_k/solution_unordered_map.cpp: -------------------------------------------------------------------------------- 1 | class Solution 2 | { 3 | public: 4 | int subarraySum(vector &nums, int k) 5 | { 6 | // Current subarray sum from start -> how many times can be achieved 7 | unordered_map m; // try comparing with map (execution time will be higher) 8 | m[0] = 1; 9 | 10 | int totalCount = 0; 11 | int currentSum = 0; 12 | 13 | for (int el : nums) 14 | { 15 | currentSum += el; 16 | 17 | totalCount += m[currentSum - k]; 18 | m[currentSum] += 1; 19 | } 20 | return totalCount; 21 | } 22 | }; -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/volleyball_friends/solution_set.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Works with set as well 5 | std::unordered_set s; 6 | 7 | int main() 8 | { 9 | 10 | std::ios::sync_with_stdio(false); 11 | std::cin.tie(NULL); 12 | 13 | int num, N; 14 | std::cin >> num >> N; 15 | 16 | s.insert(num); 17 | 18 | int numNext; 19 | while (N-- > 0) 20 | { 21 | std::cin >> num >> numNext; 22 | if (s.count(num) == 1) 23 | { 24 | s.insert(numNext); 25 | } 26 | } 27 | std::cout << s.size(); 28 | 29 | return 0; 30 | } -------------------------------------------------------------------------------- /Week_08/Seminar/Solutions/volleyball_friends/solution_set.py: -------------------------------------------------------------------------------- 1 | m = int(input()) 2 | N = int(input()) 3 | 4 | s = set([m]) 5 | 6 | for _ in range(N): 7 | x, y = map(int, input().split()) 8 | 9 | if x in s: 10 | s.add(y) 11 | 12 | print(len(s)) -------------------------------------------------------------------------------- /Week_09/Practicum/Kth Largest Element in a Stream.cpp: -------------------------------------------------------------------------------- 1 | class KthLargest { 2 | public: 3 | priority_queue, greater> pq; 4 | int k; 5 | KthLargest(int k, vector& nums) : k(k) { 6 | 7 | for (int num : nums) { 8 | pq.push(num); 9 | } 10 | 11 | while(pq.size() > k) { 12 | pq.pop(); 13 | } 14 | } 15 | 16 | int add(int val) { 17 | pq.push(val); 18 | if (pq.size() > k) 19 | pq.pop(); 20 | return pq.top(); 21 | } 22 | }; 23 | 24 | /** 25 | * Your KthLargest object will be instantiated and called as such: 26 | * KthLargest* obj = new KthLargest(k, nums); 27 | * int param_1 = obj->add(val); 28 | */ -------------------------------------------------------------------------------- /Week_09/Practicum/Kth Largest Element in a Stream.py: -------------------------------------------------------------------------------- 1 | import heapq 2 | 3 | class KthLargest: 4 | 5 | def __init__(self, k: int, nums: List[int]): 6 | self.k = k 7 | self.nums = nums 8 | heapq.heapify(self.nums) 9 | while len(self.nums) > k: 10 | heapq.heappop(self.nums) 11 | 12 | 13 | def add(self, val: int) -> int: 14 | heapq.heappush(self.nums, val) 15 | while len(self.nums) > self.k: 16 | heapq.heappop(self.nums) 17 | 18 | return self.nums[0] 19 | 20 | 21 | # Your KthLargest object will be instantiated and called as such: 22 | # obj = KthLargest(k, nums) 23 | # param_1 = obj.add(val) -------------------------------------------------------------------------------- /Week_09/Practicum/Merge k Sorted Lists.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_09/Practicum/Merge k Sorted Lists.cpp -------------------------------------------------------------------------------- /Week_09/Practicum/PythonAdditional/Remove Stones to Minimize the Total.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def minStoneSum(self, piles: List[int], k: int) -> int: 3 | piles = [-pile for pile in piles] 4 | heapq.heapify(piles) 5 | 6 | for _ in range(k): 7 | largest = -heapq.heappop(piles) 8 | largest = largest - math.floor(largest / 2) 9 | heapq.heappush(piles, -largest) 10 | 11 | return -sum(piles) -------------------------------------------------------------------------------- /Week_09/Practicum/PythonAdditional/Seat Reservation Manager.py: -------------------------------------------------------------------------------- 1 | import heapq 2 | 3 | class SeatManager: 4 | 5 | def __init__(self, n: int): 6 | self.seats = [seat for seat in range(1, n + 1)] 7 | # heapq.heapify(self.seats) 8 | 9 | def reserve(self) -> int: 10 | smallest = heapq.heappop(self.seats) 11 | return smallest 12 | 13 | def unreserve(self, seatNumber: int) -> None: 14 | heapq.heappush(self.seats, seatNumber) 15 | 16 | 17 | # Your SeatManager object will be instantiated and called as such: 18 | # obj = SeatManager(n) 19 | # param_1 = obj.reserve() 20 | # obj.unreserve(seatNumber) -------------------------------------------------------------------------------- /Week_09/Practicum/PythonAdditional/Tasks.md: -------------------------------------------------------------------------------- 1 | # Задачи 2 | 3 | - [Seat Reservation Manager](https://leetcode.com/problems/seat-reservation-manager/submissions/1476945178/) - Easy 4 | - [Remove Stones to Minimize the Total](https://leetcode.com/problems/remove-stones-to-minimize-the-total/description/) - Easy 5 | -------------------------------------------------------------------------------- /Week_09/Practicum/Relative Ranks.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findRelativeRanks(self, score: List[int]) -> List[str]: 3 | N = len(score) 4 | 5 | # Create a heap of pairs (score, index) 6 | heap = [] 7 | for index, score in enumerate(score): 8 | heapq.heappush(heap, (-score, index)) 9 | 10 | # Assign ranks to athletes 11 | rank = [0] * N 12 | place = 1 13 | while heap: 14 | original_index = heapq.heappop(heap)[1] 15 | if place == 1: 16 | rank[original_index] = "Gold Medal" 17 | elif place == 2: 18 | rank[original_index] = "Silver Medal" 19 | elif place == 3: 20 | rank[original_index] = "Bronze Medal" 21 | else: 22 | rank[original_index] = str(place) 23 | place += 1 24 | 25 | return rank -------------------------------------------------------------------------------- /Week_09/Practicum/The Number of the Smallest Unoccupied Chair.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def smallestChair(self, times: List[List[int]], targetFriend: int) -> int: 3 | times = [time + [i] for i, time in enumerate(times)] 4 | times.sort(key=lambda x: x[0]) 5 | print(times) 6 | 7 | chairs = [i for i in range(len(times))] 8 | print(chairs) 9 | leaving = [] 10 | 11 | for time in times: 12 | current_time, leaving_time, idx = time 13 | while leaving and leaving[0][0] <= current_time: 14 | _, free_chair = heapq.heappop(leaving) 15 | heapq.heappush(chairs, free_chair) 16 | 17 | occupied_chair = heapq.heappop(chairs) 18 | 19 | if idx == targetFriend: 20 | return occupied_chair 21 | 22 | heapq.heappush(leaving, (leaving_time, occupied_chair)) 23 | 24 | return 1 -------------------------------------------------------------------------------- /Week_09/Seminar/Solutions/banitsa_shop/solution_heapq.py: -------------------------------------------------------------------------------- 1 | from heapq import heappush, heappop 2 | 3 | N = int(input()) 4 | 5 | tasks = [] # by start, duration, index 6 | for i in range(N): 7 | start, duration = map(int, input().split()) 8 | 9 | heappush(tasks, (start, duration, i)) 10 | 11 | waiting = [] # by duration and index 12 | 13 | # Add the earliest task 14 | time = tasks[0][0] 15 | heappush(waiting, heappop(tasks)[1::]) 16 | 17 | while waiting: 18 | duration, index = heappop(waiting) 19 | time += duration 20 | 21 | print(index, end=' ') 22 | 23 | # Add the tasks that can be started while the one is being done 24 | while tasks and tasks[0][0] <= time: 25 | heappush(waiting, heappop(tasks)[1::]) 26 | 27 | # If there are no tasks waiting fast forward the time 28 | if not waiting and tasks: 29 | time = tasks[0][0] 30 | heappush(waiting, heappop(tasks)[1::]) 31 | -------------------------------------------------------------------------------- /Week_09/Seminar/Solutions/find_the_running_median/bad_solution_median.py: -------------------------------------------------------------------------------- 1 | from statistics import median 2 | 3 | arr = [] 4 | for i in range(int(input())): 5 | arr.append(int(input())) 6 | print("{:.1f}".format(median(arr))) 7 | -------------------------------------------------------------------------------- /Week_09/Seminar/Solutions/jesse_and_cookies/solution_heapq.py: -------------------------------------------------------------------------------- 1 | import heapq 2 | 3 | N, K = map(int, input().split()) 4 | h = list(map(int, input().split())) 5 | 6 | heapq.heapify(h) 7 | 8 | operations = 0 9 | 10 | while h and h[0] < K: 11 | if len(h) == 1: 12 | operations = -1 13 | break 14 | 15 | x, y = heapq.heappop(h), heapq.heappop(h) 16 | heapq.heappush(h, x + 2*y) 17 | operations += 1 18 | 19 | print(operations) 20 | -------------------------------------------------------------------------------- /Week_09/Seminar/Solutions/jesse_and_cookies/solution_pq.py: -------------------------------------------------------------------------------- 1 | from queue import PriorityQueue 2 | 3 | N, K = map(int, input().split()) 4 | 5 | pq = PriorityQueue() 6 | for el in map(int, input().split()): 7 | pq.put(el) 8 | 9 | operations = 0 10 | 11 | while not pq.empty() and pq.queue[0] < K: 12 | if pq.qsize() == 1: 13 | operations = -1 14 | break 15 | 16 | x, y = pq.get(), pq.get() 17 | pq.put(x + 2*y) 18 | operations += 1 19 | 20 | print(operations) 21 | -------------------------------------------------------------------------------- /Week_09/Seminar/Solutions/k_closests_points_to_origin/priority_queue.cpp: -------------------------------------------------------------------------------- 1 | struct Comparator { 2 | bool operator()(const vector& lhs, const vector& rhs) const { 3 | return lhs[0] * lhs[0] + lhs[1] * lhs[1] > rhs[0] * rhs[0] + rhs[1] * rhs[1]; 4 | } 5 | }; 6 | class Solution { 7 | public: 8 | vector> kClosest(vector>& points, int k) { 9 | priority_queue, vector>, Comparator> pq(points.begin(), points.end()); 10 | 11 | vector> result; 12 | for(int _ = 0; _ < k; _++) { 13 | result.push_back(pq.top()); 14 | pq.pop(); 15 | } 16 | 17 | return result; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /Week_09/Seminar/Solutions/kth_largest_element/solution_heapq.py: -------------------------------------------------------------------------------- 1 | import heapq 2 | 3 | class Solution: 4 | def findKthLargest(self, nums: List[int], k: int) -> int: 5 | heapq.heapify(nums) 6 | p = len(nums) - k 7 | 8 | for _ in range(p): 9 | heapq.heappop(nums) 10 | 11 | return nums[0] -------------------------------------------------------------------------------- /Week_09/Seminar/Solutions/kth_largest_element/solution_heapq_negative.py: -------------------------------------------------------------------------------- 1 | import heapq 2 | 3 | class Solution: 4 | def findKthLargest(self, nums: List[int], k: int) -> int: 5 | max_heap = [-num for num in nums] 6 | heapq.heapify(max_heap) 7 | 8 | for _ in range(k-1): 9 | heapq.heappop(max_heap) 10 | 11 | return -max_heap[0] 12 | -------------------------------------------------------------------------------- /Week_09/Seminar/Solutions/kth_largest_element/solution_make_heap.cpp: -------------------------------------------------------------------------------- 1 | #include // for heap 2 | #include 3 | 4 | using namespace std; 5 | class Solution 6 | { 7 | public: 8 | int findKthLargest(vector &nums, int k) 9 | { 10 | std::make_heap(nums.begin(), nums.end()); 11 | 12 | for (int i = 1; i < k; i++) 13 | { 14 | std::pop_heap(nums.begin(), nums.end()); 15 | nums.pop_back(); // the element is not deleted only moved to the end of the vector 16 | } 17 | 18 | return nums.front(); 19 | } 20 | }; -------------------------------------------------------------------------------- /Week_09/Seminar/Solutions/kth_largest_element/solution_pq.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | class Solution 6 | { 7 | public: 8 | int findKthLargest(vector &nums, int k) 9 | { 10 | std::priority_queue pq; 11 | 12 | for (int el : nums) 13 | { 14 | pq.push(el); 15 | } 16 | 17 | for (int i = 1; i < k; i++) 18 | { 19 | pq.pop(); 20 | } 21 | 22 | return pq.top(); 23 | } 24 | }; -------------------------------------------------------------------------------- /Week_09/Seminar/Solutions/kth_largest_element/solution_pq.py: -------------------------------------------------------------------------------- 1 | from queue import PriorityQueue 2 | 3 | class Solution: 4 | def findKthLargest(self, nums: List[int], k: int) -> int: 5 | pq = PriorityQueue() 6 | 7 | for num in nums: 8 | pq.put(num) 9 | 10 | p = len(nums) - k 11 | 12 | for _ in range(p): 13 | pq.get() 14 | 15 | return pq.queue[0] 16 | -------------------------------------------------------------------------------- /Week_09/Seminar/Solutions/kth_largest_element/solution_pq_negative.py: -------------------------------------------------------------------------------- 1 | from queue import PriorityQueue 2 | 3 | class Solution: 4 | def findKthLargest(self, nums: List[int], k: int) -> int: 5 | pq = PriorityQueue() 6 | for num in nums: 7 | pq.put(-num) 8 | 9 | for _ in range(k-1): 10 | pq.get() 11 | 12 | return -pq.queue[0] 13 | -------------------------------------------------------------------------------- /Week_09/Seminar/Solutions/kth_largest_element/solution_sort.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findKthLargest(self, nums: List[int], k: int) -> int: 3 | return sorted(nums)[-k] -------------------------------------------------------------------------------- /Week_09/Seminar/Solutions/last_stone_weight/priority_queue.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int lastStoneWeight(vector& stones) { 4 | priority_queue pq(stones.begin(), stones.end()); 5 | 6 | while(pq.size() > 1) { 7 | int left = pq.top(); 8 | pq.pop(); 9 | int right = pq.top(); 10 | pq.pop(); 11 | if(left != right) { 12 | pq.push(left - right); 13 | } 14 | } 15 | 16 | return pq.size() == 1 ? pq.top() : 0; 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /Week_09/Seminar/Solutions/maximal_score_after_k_operations/solution_heapq_negative.py: -------------------------------------------------------------------------------- 1 | """Keep the largest in Max Heap by adding the numbers as negative""" 2 | import heapq 3 | 4 | class Solution: 5 | def maxKelements(self, nums: List[int], k: int) -> int: 6 | max_heap = [-num for num in nums] 7 | heapq.heapify(max_heap) 8 | 9 | score = 0 10 | for _ in range(k): 11 | num = -heapq.heappop(max_heap) 12 | score += num 13 | 14 | heapq.heappush(max_heap, -ceil(num / 3)) 15 | 16 | return score -------------------------------------------------------------------------------- /Week_09/Seminar/Solutions/maximal_score_after_k_operations/solution_heapq_order.py: -------------------------------------------------------------------------------- 1 | """Defining a new comparison method""" 2 | import heapq 3 | 4 | class MaxElement(): 5 | def __init__(self, value): 6 | self.value = value 7 | 8 | def __lt__(self, other): 9 | return self.value > other.value 10 | 11 | class Solution: 12 | def maxKelements(self, nums: List[int], k: int) -> int: 13 | max_heap = [MaxElement(num) for num in nums] 14 | heapq.heapify(max_heap) 15 | 16 | score = 0 17 | for _ in range(k): 18 | num = heapq.heappop(max_heap).value 19 | score += num 20 | 21 | heapq.heappush(max_heap, MaxElement(ceil(num / 3))) 22 | 23 | return score -------------------------------------------------------------------------------- /Week_09/Seminar/Solutions/maximal_score_after_k_operations/solution_make_heap.cpp: -------------------------------------------------------------------------------- 1 | #include // for heap 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | class Solution 8 | { 9 | public: 10 | long long maxKelements(vector &nums, int k) 11 | { 12 | std::make_heap(nums.begin(), nums.end()); 13 | 14 | long long current, total = 0; 15 | while (k--) 16 | { 17 | current = nums.front(); 18 | total += current; 19 | 20 | std::pop_heap(nums.begin(), nums.end()); 21 | 22 | current = ceil(current / 3.0); 23 | nums[nums.size() - 1] = current; 24 | 25 | std::push_heap(nums.begin(), nums.end()); 26 | } 27 | return total; 28 | } 29 | }; -------------------------------------------------------------------------------- /Week_09/Seminar/Solutions/maximal_score_after_k_operations/solution_pq_negative.py: -------------------------------------------------------------------------------- 1 | """Keep the largest in Max Heap by adding the numbers as negative""" 2 | from queue import PriorityQueue 3 | 4 | class Solution: 5 | def maxKelements(self, nums: List[int], k: int) -> int: 6 | pq = PriorityQueue() 7 | for num in nums: 8 | pq.put(-num) 9 | 10 | score = 0 11 | for _ in range(k): 12 | num = -pq.get() 13 | score += num 14 | 15 | pq.put(-ceil(num / 3)) 16 | 17 | return score -------------------------------------------------------------------------------- /Week_09/Seminar/Solutions/maximal_score_after_k_operations/solution_pq_order.py: -------------------------------------------------------------------------------- 1 | """Defining a new comparison method""" 2 | from queue import PriorityQueue 3 | 4 | class MaxElement(): 5 | def __init__(self, value): 6 | self.value = value 7 | 8 | def __lt__(self, other): 9 | return self.value > other.value 10 | 11 | class Solution: 12 | def maxKelements(self, nums: List[int], k: int) -> int: 13 | pq = PriorityQueue() 14 | for num in nums: 15 | pq.put(MaxElement(num)) 16 | 17 | score = 0 18 | for _ in range(k): 19 | max_element = pq.get() 20 | score += max_element.value 21 | 22 | new_value = ceil(max_element.value / 3) 23 | 24 | pq.put(MaxElement(new_value)) 25 | 26 | return score -------------------------------------------------------------------------------- /Week_09/Seminar/Solutions/task_scheduler/solution.cpp: -------------------------------------------------------------------------------- 1 | struct Task{ 2 | char c; 3 | int minTime; 4 | bool operator<(const Task& rhs) const { 5 | return minTime > rhs.minTime; 6 | } 7 | }; 8 | class Solution { 9 | public: 10 | int leastInterval(vector& tasks, int n) { 11 | priority_queue pq; 12 | int minTimes[26]{0}; 13 | for(auto task: tasks) { 14 | pq.push({task, minTimes[task - 'A']}); 15 | minTimes[task - 'A'] += (n + 1); 16 | } 17 | 18 | int currentTime = 0; 19 | while(!pq.empty()) { 20 | if(currentTime < pq.top().minTime) { 21 | currentTime = pq.top().minTime; 22 | } 23 | 24 | pq.pop(); 25 | currentTime++; 26 | } 27 | 28 | return currentTime; 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /Week_10/Practicum/Find Center of Star Graph.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int findCenter(vector>& edges) { 4 | unordered_map visited; 5 | 6 | for (auto& e : edges) { 7 | if (visited.count(e[0]) != 0) 8 | return e[0]; 9 | if (visited.count(e[1]) != 0) 10 | return e[1]; 11 | visited[e[0]] = true; 12 | visited[e[1]] = true; 13 | } 14 | 15 | return -1; 16 | } 17 | }; -------------------------------------------------------------------------------- /Week_10/Practicum/Find Center of Star Graph.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findCenter(self, edges: List[List[int]]) -> int: 3 | in_degree = defaultdict(int) 4 | 5 | for edge in edges: 6 | in_degree[edge[0]] += 1 7 | in_degree[edge[1]] += 1 8 | 9 | if in_degree[edge[0]] > 1: 10 | return edge[0] 11 | if in_degree[edge[1]] > 1: 12 | return edge[1] -------------------------------------------------------------------------------- /Week_10/Practicum/Find Champion II.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int findChampion(int n, vector>& edges) { 4 | vector> graph(n); 5 | vector indegree(n, 0); 6 | 7 | for (auto &e : edges) { 8 | graph[e[0]].push_back(e[1]); 9 | indegree[e[1]]++; 10 | } 11 | 12 | int champion = -1; 13 | 14 | for (int i = 0; i < n; i++) { 15 | if (indegree[i] == 0) { 16 | if (champion == -1) { 17 | champion = i; 18 | } else { 19 | return -1; 20 | } 21 | } 22 | } 23 | 24 | return champion; 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /Week_10/Practicum/Find Champion II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findChampion(self, n: int, edges: List[List[int]]) -> int: 3 | in_count = [0 for _ in range(n)] 4 | 5 | for edge in edges: 6 | in_count[edge[1]] += 1 7 | 8 | champions = [k for k, v in enumerate(in_count) if v == 0] 9 | 10 | return champions[0] if len(champions) == 1 else -1 -------------------------------------------------------------------------------- /Week_10/Practicum/Find The Town Judge.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findJudge(self, n: int, trust: List[List[int]]) -> int: 3 | in_degree = defaultdict(int) 4 | out_degree = defaultdict(int) 5 | 6 | for edge in trust: 7 | out_degree[edge[0]] += 1 8 | in_degree[edge[1]] += 1 9 | 10 | 11 | for i in range(1, n + 1): 12 | if in_degree[i] == n - 1 and out_degree[i] == 0: 13 | return i 14 | 15 | return -1 -------------------------------------------------------------------------------- /Week_10/Practicum/Find if Path Exists in Graph.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | bool validPath(int n, vector>& edges, int source, int destination) { 4 | vector> graph(n); 5 | for (auto& edge : edges) { 6 | graph[edge[0]].push_back(edge[1]); 7 | graph[edge[1]].push_back(edge[0]); 8 | } 9 | 10 | vector visited(n, false); 11 | queue q; 12 | q.push(source); 13 | visited[source] = true; 14 | 15 | while (!q.empty()) { 16 | int curr = q.front(); q.pop(); 17 | if (curr == destination) return true; 18 | for (auto &nbr : graph[curr]) { 19 | if (!visited[nbr]) { 20 | visited[nbr] = true; 21 | q.push(nbr); 22 | } 23 | } 24 | } 25 | 26 | return false; 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /Week_10/Practicum/Find if Path Exists in Graph.py: -------------------------------------------------------------------------------- 1 | def dfs(graph, visited, current, target): 2 | if current not in visited or visited[current]: 3 | return 4 | 5 | if current == target: 6 | return True 7 | 8 | visited[current] = True 9 | 10 | for node in graph[current]: 11 | if dfs(graph, visited, node, target): 12 | return True 13 | 14 | return False 15 | 16 | 17 | class Solution: 18 | def validPath(self, n: int, edges: List[List[int]], source: int, destination: int) -> bool: 19 | if source == destination: 20 | return True 21 | 22 | graph = defaultdict(list) 23 | for edge in edges: 24 | graph[edge[0]].append(edge[1]) 25 | graph[edge[1]].append(edge[0]) 26 | 27 | visited = {node: False for node in graph.keys()} 28 | 29 | return dfs(graph, visited, source, destination) -------------------------------------------------------------------------------- /Week_10/Practicum/Find the Town Judge.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int findJudge(int n, vector>& trust) { 4 | vector trusts(n, 0); 5 | vector trustHim(n, 0); 6 | 7 | for (auto& t : trust) { 8 | trusts[t[0] - 1]++; 9 | trustHim[t[1] - 1]++; 10 | } 11 | 12 | for (int i = 0; i < n; i++) { 13 | if (trusts[i] == 0 && trustHim[i] == (n - 1)) 14 | return i + 1; 15 | } 16 | 17 | return -1; 18 | } 19 | }; -------------------------------------------------------------------------------- /Week_10/Practicum/Keys and Rooms.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | void dfs(vector>& rooms, int curr, vector& visited) { 4 | visited[curr] = true; 5 | for (auto& r : rooms[curr]) { 6 | if (!visited[r]) { 7 | dfs(rooms, r, visited); 8 | } 9 | } 10 | } 11 | 12 | bool canVisitAllRooms(vector>& rooms) { 13 | vector visited(rooms.size(), false); 14 | 15 | dfs(rooms, 0, visited); 16 | 17 | for (bool v : visited) { 18 | if (!v) { 19 | return false; 20 | } 21 | } 22 | 23 | return true; 24 | } 25 | }; -------------------------------------------------------------------------------- /Week_10/Practicum/Keys and Rooms.py: -------------------------------------------------------------------------------- 1 | def dfs(rooms, visited, current): 2 | if visited[current]: 3 | return 4 | 5 | visited[current] = True 6 | 7 | for neighb in rooms[current]: 8 | dfs(rooms, visited, neighb) 9 | 10 | 11 | class Solution: 12 | def canVisitAllRooms(self, rooms: List[List[int]]) -> bool: 13 | visited = [False for _ in rooms] 14 | 15 | dfs(rooms, visited, 0) 16 | 17 | return sum(visited) == len(rooms) 18 | 19 | -------------------------------------------------------------------------------- /Week_10/Practicum/Number of Provinces.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | void dfs(vector>& isConnected, int curr, vector& visited) { 4 | visited[curr] = true; 5 | 6 | for (int j = 0; j < isConnected.size(); j++) { 7 | if (isConnected[curr][j] == 1 && !visited[j]) { 8 | dfs(isConnected, j, visited); 9 | } 10 | } 11 | } 12 | 13 | int findCircleNum(vector>& isConnected) { 14 | int n = isConnected.size(); 15 | int counter = 0; 16 | 17 | vector visited(n, false); 18 | 19 | for (int i = 0; i < n; i++) { 20 | if (!visited[i]) { 21 | counter++; 22 | dfs(isConnected, i, visited); 23 | } 24 | } 25 | return counter; 26 | } 27 | }; -------------------------------------------------------------------------------- /Week_10/Practicum/Number of Provinces.py: -------------------------------------------------------------------------------- 1 | def dfs(isConnected, visited, current): 2 | if current not in visited or visited[current]: 3 | return 4 | 5 | visited[current] = True 6 | 7 | for node in range(len(isConnected[current])): 8 | if isConnected[current][node]: 9 | dfs(isConnected, visited, node) 10 | 11 | 12 | class Solution: 13 | def findCircleNum(self, isConnected: List[List[int]]) -> int: 14 | visited = {node: False for node in range(len(isConnected))} 15 | 16 | total = 0 17 | 18 | for node in range(len(isConnected)): 19 | if not visited[node]: 20 | total += 1 21 | dfs(isConnected, visited, node) 22 | 23 | return total -------------------------------------------------------------------------------- /Week_10/Practicum/Tasks.md: -------------------------------------------------------------------------------- 1 | # Задачи 2 | 3 | - [Find Center of Star Graph](https://leetcode.com/problems/find-center-of-star-graph/) 4 | - [Find the Town Judge](https://leetcode.com/problems/find-the-town-judge/) 5 | - [Find if Path Exists in Graph](https://leetcode.com/problems/find-if-path-exists-in-graph/) 6 | - [Keys and Rooms](https://leetcode.com/problems/keys-and-rooms/) 7 | - [Number of Provinces](https://leetcode.com/problems/number-of-provinces/) 8 | - [Count the Number of Complete Components](https://leetcode.com/problems/count-the-number-of-complete-components/) 9 | - [Remove Methods From Project](https://leetcode.com/problems/remove-methods-from-project/) 10 | - [Find Champion II](https://leetcode.com/problems/find-champion-ii/) 11 | - [Course Schedule II](https://leetcode.com/problems/course-schedule-ii/) 12 | -------------------------------------------------------------------------------- /Week_10/Seminar/Examples/dfs.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | void dfs(int current, unordered_set &visited, unordered_map> &graph) 7 | { 8 | cout << current << " "; 9 | visited.insert(current); 10 | 11 | for (int neighbor : graph[current]) 12 | { 13 | if (!visited.count(neighbor)) 14 | { 15 | dfs(neighbor, visited, graph); 16 | } 17 | } 18 | } 19 | 20 | int main() 21 | { 22 | unordered_map> graph = { 23 | {0, {1, 2, 3}}, 24 | {1, {0, 2, 4}}, 25 | {2, {0, 1}}, 26 | {3, {0, 5}}, 27 | {4, {1, 5}}, 28 | {5, {3, 4, 6}}, 29 | {6, {5}}}; 30 | 31 | unordered_set visited; 32 | dfs(0, visited, graph); // 0 3 5 6 4 1 2 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /Week_10/Seminar/Solutions/all_paths_from_source_to_target/solutions_dfs.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | vector> result; 3 | void dfs(int current, vector& path, vector>& graph) { 4 | path.push_back(current); 5 | if(current == graph.size() - 1) { 6 | result.push_back(path); 7 | path.pop_back(); 8 | return; 9 | } 10 | 11 | for(auto& neighbour: graph[current]) { 12 | dfs(neighbour, path, graph); 13 | } 14 | 15 | path.pop_back(); 16 | } 17 | public: 18 | vector> allPathsSourceTarget(vector>& graph) { 19 | vector path; 20 | dfs(0, path, graph); 21 | return result; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /Week_10/Seminar/Solutions/clone_graph/solution_umap.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | // pointer value is a number => can be hashed 3 | unordered_map indexToNode; 4 | public: 5 | Node* cloneGraph(Node* node) { 6 | if(!node) { 7 | return node; 8 | } 9 | 10 | auto iter = indexToNode.find(node); 11 | if(iter != indexToNode.end()) { 12 | return iter->second; 13 | } 14 | 15 | Node* newNode = new Node(node->val); 16 | indexToNode[node] = newNode; 17 | 18 | for(auto neighbour: node->neighbors) { 19 | newNode->neighbors.push_back(cloneGraph(neighbour)); 20 | } 21 | 22 | return newNode; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /Week_10/Seminar/Solutions/find_the_celebrity/brute_force.cpp: -------------------------------------------------------------------------------- 1 | // check all possible 2 | 3 | class Solution { 4 | public: 5 | int findCelebrity(int n) { 6 | for(int i = 0; i < n; i++) { 7 | if(isCelebrity(i,n)) { 8 | return i; 9 | } 10 | } 11 | 12 | return -1; 13 | } 14 | 15 | bool isCelebrity(int current, int n) { 16 | for(int i = 0; i < n; i++) { 17 | if(i != current && (!knows(i, current) || knows(current, i))) { 18 | return false; 19 | } 20 | } 21 | 22 | return true; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /Week_10/Seminar/Solutions/find_the_town_judge/in_and_out_degree.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int findJudge(int n, vector>& trust) { 4 | if(trust.size() < n - 1) { 5 | return -1; 6 | } 7 | vector indegree(n + 1, 0); 8 | vector outdegree(n + 1, 0); 9 | for(auto& relation: trust) { 10 | outdegree[relation[0]]++; 11 | indegree[relation[1]]++; 12 | } 13 | 14 | for(size_t i = 1; i <= n; i++) { 15 | if(indegree[i] == n - 1 && outdegree[i] == 0) { 16 | return i; 17 | } 18 | } 19 | 20 | return -1; 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /Week_10/Seminar/Solutions/find_the_town_judge/potential_array.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int findJudge(int n, vector>& trust) { 4 | if(trust.size() < n - 1) { 5 | return -1; 6 | } 7 | vector potential(n + 1, 0); 8 | for(auto& relation: trust) { 9 | potential[relation[0]]--; 10 | potential[relation[1]]++; 11 | } 12 | 13 | for(size_t i = 1; i <= n; i++) { 14 | if(potential[i] == n - 1) { 15 | return i; 16 | } 17 | } 18 | 19 | return -1; 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /Week_10/Seminar/media/directed_graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_10/Seminar/media/directed_graph.png -------------------------------------------------------------------------------- /Week_10/Seminar/media/graph_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_10/Seminar/media/graph_example.png -------------------------------------------------------------------------------- /Week_10/Seminar/media/graph_for_traversing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_10/Seminar/media/graph_for_traversing.png -------------------------------------------------------------------------------- /Week_10/Seminar/media/undirected_graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_10/Seminar/media/undirected_graph.png -------------------------------------------------------------------------------- /Week_11/Practicum/Tasks.md: -------------------------------------------------------------------------------- 1 | # Задачи 2 | 3 | - https://leetcode.com/problems/get-watched-videos-by-your-friends/description/ - MEDIUM 4 | - https://www.hackerrank.com/contests/sda-hw-11-2021/challenges/shortest-paths-2 - MEDIUM 5 | - https://leetcode.com/problems/path-with-maximum-probability/description/ - MEDIUM 6 | - https://www.hackerrank.com/contests/sda-hw-11-2021/challenges/discos - MEDIUM 7 | - https://leetcode.com/problems/reachable-nodes-in-subdivided-graph/description - MEDIUM 8 | - https://leetcode.com/problems/second-minimum-time-to-reach-destination/description/ - MEDIUM 9 | - https://leetcode.com/problems/minimum-cost-of-a-path-with-special-roads/description/ - HARD 10 | -------------------------------------------------------------------------------- /Week_11/Seminar/Solutions/cheapest_flights_within_k_stops/solution_bellman-ford.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int findCheapestPrice(int n, vector>& flights, int src, int dst, int k) { 4 | vector distances(n, INT_MAX); 5 | distances[src] = 0; 6 | for(int i = 0; i <= k; i++) { 7 | // to make sure that every column is update only with data from last round + new edge 8 | vector nextRow(distances); 9 | for(auto& edge: flights) { 10 | if(distances[edge[0]] != INT_MAX) { 11 | nextRow[edge[1]] = min(nextRow[edge[1]], distances[edge[0]] + edge[2]); 12 | } 13 | } 14 | 15 | distances = std::move(nextRow); 16 | } 17 | 18 | if(distances[dst] == INT_MAX) { 19 | return -1; 20 | } 21 | 22 | return distances[dst]; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /Week_11/Seminar/Solutions/long_long/solution_bellman_ford_adjacency_list.py: -------------------------------------------------------------------------------- 1 | INF = float('-infinity') 2 | 3 | def bellman_ford(start, V, graph): 4 | distances = [INF] * (V + 1) 5 | distances[start] = 0 6 | 7 | for _ in range(V - 1): 8 | for v in range(1, V + 1): 9 | for child, weight in graph[v]: 10 | distances[child] = max(distances[child], distances[v] + weight) 11 | 12 | return distances 13 | 14 | 15 | N, M, S, F = map(int, input().split()) 16 | graph = {v: set() for v in range(1, N + 1)} 17 | 18 | for _ in range(M): 19 | x, y, w = map(int, input().split()) 20 | graph[x].add((y, w)) 21 | 22 | distances = bellman_ford(S, N, graph) 23 | answer = distances[F] if distances[F] != INF else -1 24 | print(answer) -------------------------------------------------------------------------------- /Week_11/Seminar/Solutions/long_long/solution_bellman_ford_max.py: -------------------------------------------------------------------------------- 1 | INF = float('-infinity') 2 | 3 | def bellman_ford(start, V, E, graph): 4 | distances = [INF] * (V + 1) 5 | distances[start] = 0 6 | 7 | for _ in range(V - 1): 8 | for x, y, w in graph: # O(E) 9 | distances[y] = max(distances[y], distances[x] + w) 10 | 11 | return distances 12 | 13 | N, M, S, F = map(int, input().split()) 14 | graph = [tuple(map(int, input().split())) for _ in range(M)] 15 | 16 | distances = bellman_ford(S, N, M, graph) 17 | answer = distances[F] if distances[F] != INF else -1 18 | print(answer) -------------------------------------------------------------------------------- /Week_11/Seminar/media/dijkstra_negative_edge_graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_11/Seminar/media/dijkstra_negative_edge_graph.png -------------------------------------------------------------------------------- /Week_11/Seminar/media/dijkstra_undirected_graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_11/Seminar/media/dijkstra_undirected_graph.png -------------------------------------------------------------------------------- /Week_12/Practicum/Find if Path Exists in Graph.py: -------------------------------------------------------------------------------- 1 | def find(x, parents): 2 | if parents[x] == x: 3 | return x 4 | 5 | furthest_parent = find(parents[x], parents) 6 | parents[x] = furthest_parent 7 | 8 | return furthest_parent 9 | 10 | def union(x, y, parents): 11 | x_root = find(x, parents) 12 | y_root = find(y, parents) 13 | 14 | if x_root != y_root: 15 | parents[x_root] = y_root 16 | return 1 17 | 18 | return 0 19 | 20 | class Solution: 21 | def validPath(self, n: int, edges: List[List[int]], source: int, destination: int) -> bool: 22 | parents = [i for i in range(n)] 23 | for edge in edges: 24 | union(edge[0], edge[1], parents) 25 | 26 | return find(source, parents) == find(destination, parents) -------------------------------------------------------------------------------- /Week_12/Practicum/Tasks.md: -------------------------------------------------------------------------------- 1 | # Задачи 2 | 3 | - https://leetcode.com/problems/find-if-path-exists-in-graph/ - EASY 4 | - https://www.hackerrank.com/contests/sda-homework-12/challenges/challenge-2801 - MEDIUM 5 | - https://www.hackerrank.com/contests/practice-9-sda/challenges/kruskalmstrsub - MEDIUM 6 | - https://leetcode.com/problems/min-cost-to-connect-all-points/description/ - MEDIUM 7 | - https://www.hackerrank.com/contests/sda-homework-12/challenges/challenge-2799 - MEDIUM 8 | - https://www.hackerrank.com/contests/june-world-codesprint/challenges/johnland/problem - HARD 9 | -------------------------------------------------------------------------------- /Week_12/Seminar/Solutions/kruskals_really_special_subtree/solution_kruskal_worst.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.setrecursionlimit(100_000) 3 | 4 | def find(x, parents): 5 | if parents[x] == x: 6 | return x 7 | 8 | return find(parents[x], parents) 9 | 10 | def union(x, y, parents): 11 | x_root = find(x, parents) 12 | y_root = find(y, parents) 13 | 14 | parents[x_root] = y_root 15 | 16 | def kruskal(V, edges): 17 | edges.sort(key=lambda x: x[2]) 18 | parents = [i for i in range(V + 1)] 19 | mst_weight = 0 20 | 21 | for x, y, w in edges: 22 | if find(x, parents) != find(y, parents): 23 | mst_weight += w 24 | union(x, y, parents) 25 | 26 | return mst_weight 27 | 28 | N, M = map(int, input().split()) 29 | edges = [tuple(map(int, input().split())) for _ in range(M)] 30 | 31 | mst_weight = kruskal(N, edges) 32 | print(mst_weight) -------------------------------------------------------------------------------- /Week_12/Seminar/UnionFind/UnionFind.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class UnionFind { 4 | private: 5 | std::vector parentsContainer; 6 | std::vector sizes; 7 | 8 | size_t getParent(size_t vertex); 9 | public: 10 | UnionFind(size_t vertices); 11 | 12 | bool areInOneSet(size_t first, size_t second); 13 | void unionVertices(size_t first, size_t second); 14 | }; 15 | -------------------------------------------------------------------------------- /Week_12/Seminar/media/kruskals_algorithm_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_12/Seminar/media/kruskals_algorithm_example.png -------------------------------------------------------------------------------- /Week_12/Seminar/media/minimum_spanning_trees.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_12/Seminar/media/minimum_spanning_trees.png -------------------------------------------------------------------------------- /Week_12/Seminar/media/mst_vs_dijkstra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_12/Seminar/media/mst_vs_dijkstra.png -------------------------------------------------------------------------------- /Week_12/Seminar/media/prims_algorithm_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_12/Seminar/media/prims_algorithm_example.png -------------------------------------------------------------------------------- /Week_12/Seminar/media/spanning_trees.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_12/Seminar/media/spanning_trees.png -------------------------------------------------------------------------------- /Week_12/Seminar/media/weighted_graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_12/Seminar/media/weighted_graph.png -------------------------------------------------------------------------------- /Week_13/Practicum/04. Stack & Queue/max_sliding_window.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector maxSlidingWindow(vector& nums, int k) { 4 | 5 | deque dq; 6 | vector res; 7 | 8 | for (int i = 0; i < nums.size(); i++) 9 | { 10 | while (!dq.empty() && nums[i] >= nums[dq.back()]) 11 | { 12 | dq.pop_back(); 13 | } 14 | 15 | dq.push_back(i); 16 | if (dq.front() <= i - k) 17 | { 18 | dq.pop_front(); 19 | } 20 | 21 | if (i >= k - 1) 22 | { 23 | res.push_back(nums[dq.front()]); 24 | } 25 | } 26 | 27 | return res; 28 | } 29 | }; -------------------------------------------------------------------------------- /Week_13/Practicum/07. Hash/anagram.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | 5 | int main() { 6 | 7 | int q; 8 | cin >> q; 9 | while (q--) 10 | { 11 | unordered_map f, s; 12 | int m, n; 13 | cin >> m >> n; 14 | 15 | while (m--) 16 | { 17 | string word; 18 | cin >> word; 19 | f[word]++; 20 | } 21 | 22 | while (n--) 23 | { 24 | string word; 25 | cin >> word; 26 | s[word]++; 27 | } 28 | 29 | bool isAnagram = true; 30 | for (auto& p : s) 31 | { 32 | if (p.second > f[p.first]) 33 | { 34 | isAnagram = false; 35 | break; 36 | } 37 | } 38 | 39 | cout << (isAnagram ? "Yes" : "No") << endl; 40 | } 41 | 42 | return 0; 43 | } -------------------------------------------------------------------------------- /Week_13/Practicum/07. Hash/dundee_the_crocodile.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | 5 | int main() { 6 | 7 | map mp; 8 | string word; 9 | 10 | while (cin >> word) 11 | { 12 | mp[word]++; 13 | } 14 | 15 | for (auto& p : mp) 16 | { 17 | if (p.second == 1) 18 | { 19 | cout << p.first << endl; 20 | } 21 | } 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /Week_13/Practicum/07. Hash/roman.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | string intToRoman(int num) { 4 | 5 | map romanDict = { 6 | {1000, "M"}, 7 | {900, "CM"}, 8 | {500, "D"}, 9 | {400, "CD"}, 10 | {100, "C"}, 11 | {90, "XC"}, 12 | {50, "L"}, 13 | {40, "XL"}, 14 | {10, "X"}, 15 | {9, "IX"}, 16 | {5, "V"}, 17 | {4, "IV"}, 18 | {1, "I"} 19 | }; 20 | 21 | string res = ""; 22 | for (auto i = romanDict.rbegin(); i != romanDict.rend(); i++) 23 | { 24 | while (num >= i->first) 25 | { 26 | res += i->second; 27 | num -= i->first; 28 | } 29 | } 30 | 31 | return res; 32 | } 33 | }; -------------------------------------------------------------------------------- /Week_13/Practicum/07. Hash/subarray.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | 5 | int main() { 6 | 7 | ios_base::sync_with_stdio(false); 8 | cin.tie(nullptr); 9 | 10 | int n; 11 | cin >> n; 12 | 13 | vector nums(n); 14 | for (int i = 0; i < n; i++) 15 | { 16 | cin >> nums[i]; 17 | } 18 | 19 | unordered_set s; 20 | int maxSize = 0; 21 | int leftMost = 0; 22 | 23 | for (int i = 0; i < n; i++) 24 | { 25 | if (s.count(nums[i])) 26 | { 27 | while (!s.empty() && s.count(nums[i])) 28 | { 29 | s.erase(nums[leftMost++]); 30 | } 31 | } 32 | 33 | s.insert(nums[i]); 34 | maxSize = max(maxSize, (int)s.size()); 35 | } 36 | 37 | cout << maxSize; 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /Week_13/Seminar/Solutions/all_paths_from_source_to_target/cpp_solution_backtracking.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | vector> result; 3 | void dfs(int current, vector& path, vector>& graph) { 4 | path.push_back(current); 5 | if(current == graph.size() - 1) { 6 | result.push_back(path); 7 | path.pop_back(); 8 | return; 9 | } 10 | 11 | for(auto& neighbour: graph[current]) { 12 | dfs(neighbour, path, graph); 13 | } 14 | 15 | path.pop_back(); 16 | } 17 | public: 18 | vector> allPathsSourceTarget(vector>& graph) { 19 | vector path; 20 | dfs(0, path, graph); 21 | return result; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /Week_13/Seminar/Solutions/permutations/cpp_solution_backtracking.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | void _permute(vector& nums, vector>& result, int start) { 4 | if(start == nums.size()) { 5 | result.push_back(nums); 6 | return; 7 | } 8 | for(size_t i = start; i < nums.size(); i++) { 9 | swap(nums[i], nums[start]); 10 | _permute(nums, result, start + 1); 11 | swap(nums[i], nums[start]); 12 | } 13 | } 14 | vector> permute(vector& nums) { 15 | vector> result; 16 | _permute(nums, result, 0); 17 | 18 | return result; 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /Week_13/Seminar/Solutions/permutations/solution_backtracking.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def dfs(self, path, all_paths, nums, used): 3 | if len(path) == len(nums): 4 | all_paths.append(path.copy()) 5 | return all_paths 6 | 7 | for num in nums: 8 | if num in used: 9 | continue 10 | path.append(num) 11 | used.add(num) 12 | 13 | self.dfs(path, all_paths, nums, used) 14 | 15 | path.pop() 16 | used.remove(num) 17 | 18 | return all_paths 19 | 20 | def permute(self, nums: List[int]) -> List[List[int]]: 21 | all_paths = [] 22 | path = [] 23 | used = set() 24 | 25 | return self.dfs(path, all_paths, nums, used) 26 | -------------------------------------------------------------------------------- /Week_13/Seminar/Solutions/permutations/solution_itertools.py: -------------------------------------------------------------------------------- 1 | from itertools import permutations 2 | 3 | class Solution: 4 | def permute(self, nums: List[int]) -> List[List[int]]: 5 | return permutations(nums) -------------------------------------------------------------------------------- /Week_13/Seminar/Solutions/reconstruct_itinerary/solution_euler.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | from heapq import heappop, heappush 3 | 4 | class Solution: 5 | def euler_path(self, current, path, edges): 6 | while edges[current]: 7 | next_vertex = heappop(edges[current]) 8 | self.euler_path(next_vertex, path, edges) 9 | 10 | path.append(current) 11 | return reversed(path) 12 | 13 | def findItinerary(self, tickets: List[List[str]]) -> List[str]: 14 | edges = defaultdict(list) 15 | for start, end in tickets: 16 | heappush(edges[start], end) 17 | 18 | path = [] 19 | return self.euler_path("JFK", path, edges) -------------------------------------------------------------------------------- /Week_13/Seminar/Solutions/reconstruct_itinerary/solution_euler_path.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | vector findItinerary(vector>& tickets) { 4 | unordered_map, greater>> graph; 5 | for(auto& ticket: tickets) { 6 | graph[ticket[0]].push(ticket[1]); 7 | } 8 | 9 | vector result; 10 | stack st; 11 | st.push("JFK"); 12 | while(!st.empty()) { 13 | string current = st.top(); 14 | if(!graph[current].empty()) { 15 | st.push(graph[current].top()); 16 | graph[current].pop(); 17 | } 18 | else { 19 | result.push_back(st.top()); 20 | st.pop(); 21 | } 22 | } 23 | 24 | 25 | reverse(result.begin(), result.end()); 26 | return result; 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /Week_13/Seminar/media/complex_eulerian_path_and_cycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_13/Seminar/media/complex_eulerian_path_and_cycle.png -------------------------------------------------------------------------------- /Week_13/Seminar/media/eulerian_path_famous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_13/Seminar/media/eulerian_path_famous.png -------------------------------------------------------------------------------- /Week_13/Seminar/media/eulerian_path_simple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_13/Seminar/media/eulerian_path_simple.png -------------------------------------------------------------------------------- /Week_13/Seminar/media/hamiltonian_path_and_cycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_13/Seminar/media/hamiltonian_path_and_cycle.png -------------------------------------------------------------------------------- /Week_13/Seminar/media/simple_eulerian_path_and_cycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeogopK/Data_Structures_and_Algorithms_FMI/bf9198e276eeb286cc564f8c6d3e60f2c56e70fb/Week_13/Seminar/media/simple_eulerian_path_and_cycle.png --------------------------------------------------------------------------------