From 17cac9a4dff30880ba3224138d77cd48e389ffff Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Thu, 23 Jan 2025 03:01:58 +0200 Subject: [PATCH] Added erlang --- .../g0101_0200/s0139_word_break/Solution.erl | 42 ++++++++++ .../g0101_0200/s0139_word_break/readme.md | 39 ++++++++++ .../g0101_0200/s0146_lru_cache/LRUCache.erl | 77 +++++++++++++++++++ .../g0101_0200/s0146_lru_cache/readme.md | 48 ++++++++++++ .../g0101_0200/s0148_sort_list/Solution.erl | 29 +++++++ .../g0101_0200/s0148_sort_list/readme.md | 34 ++++++++ .../Solution.erl | 18 +++++ .../s0152_maximum_product_subarray/readme.md | 31 ++++++++ .../Solution.erl | 15 ++++ .../readme.md | 46 +++++++++++ .../g0101_0200/s0155_min_stack/MinStack.erl | 55 +++++++++++++ .../g0101_0200/s0155_min_stack/readme.md | 40 ++++++++++ .../s0169_majority_element/Solution.erl | 15 ++++ .../s0169_majority_element/readme.md | 27 +++++++ .../s0198_house_robber/Solution.erl | 24 ++++++ .../g0101_0200/s0198_house_robber/readme.md | 28 +++++++ .../s0200_number_of_islands/Solution.erl | 41 ++++++++++ .../s0200_number_of_islands/readme.md | 46 +++++++++++ .../s0206_reverse_linked_list/Solution.erl | 15 ++++ .../s0206_reverse_linked_list/readme.md | 34 ++++++++ .../s0207_course_schedule/Solution.erl | 69 +++++++++++++++++ .../s0207_course_schedule/readme.md | 33 ++++++++ .../s0208_implement_trie_prefix_tree/Trie.erl | 61 +++++++++++++++ .../readme.md | 40 ++++++++++ .../Solution.erl | 25 ++++++ .../readme.md | 26 +++++++ .../s0221_maximal_square/Solution.erl | 61 +++++++++++++++ .../g0201_0300/s0221_maximal_square/readme.md | 34 ++++++++ .../s0226_invert_binary_tree/Solution.erl | 15 ++++ .../s0226_invert_binary_tree/readme.md | 32 ++++++++ .../Solution.erl | 42 ++++++++++ .../readme.md | 29 +++++++ .../s0234_palindrome_linked_list/Solution.erl | 20 +++++ .../s0234_palindrome_linked_list/readme.md | 28 +++++++ .../Solution.erl | 17 ++++ .../readme.md | 29 +++++++ .../s0239_sliding_window_maximum/Solution.erl | 33 ++++++++ .../s0239_sliding_window_maximum/readme.md | 43 +++++++++++ .../Solution.erl | 8 ++ .../s0287_find_the_duplicate_number/readme.md | 33 ++++++++ .../Solution.erl | 29 +++++++ .../readme.md | 34 ++++++++ .../g0301_0400/s0322_coin_change/Solution.erl | 53 +++++++++++++ .../g0301_0400/s0322_coin_change/readme.md | 35 +++++++++ .../s0338_counting_bits/Solution.erl | 17 ++++ .../g0301_0400/s0338_counting_bits/readme.md | 41 ++++++++++ .../Solution.erl | 25 ++++++ .../s0347_top_k_frequent_elements/readme.md | 26 +++++++ .../s0394_decode_string/Solution.erl | 58 ++++++++++++++ .../g0301_0400/s0394_decode_string/readme.md | 36 +++++++++ .../Solution.erl | 28 +++++++ .../readme.md | 26 +++++++ .../s0437_path_sum_iii/Solution.erl | 21 +++++ .../g0401_0500/s0437_path_sum_iii/readme.md | 29 +++++++ .../Solution.erl | 47 +++++++++++ .../readme.md | 38 +++++++++ .../g0401_0500/s0494_target_sum/Solution.erl | 36 +++++++++ .../g0401_0500/s0494_target_sum/readme.md | 42 ++++++++++ .../Solution.erl | 25 ++++++ .../s0543_diameter_of_binary_tree/readme.md | 30 ++++++++ .../Solution.erl | 33 ++++++++ .../readme.md | 40 ++++++++++ 62 files changed, 2131 insertions(+) create mode 100644 src/main/erlang/g0101_0200/s0139_word_break/Solution.erl create mode 100644 src/main/erlang/g0101_0200/s0139_word_break/readme.md create mode 100644 src/main/erlang/g0101_0200/s0146_lru_cache/LRUCache.erl create mode 100644 src/main/erlang/g0101_0200/s0146_lru_cache/readme.md create mode 100644 src/main/erlang/g0101_0200/s0148_sort_list/Solution.erl create mode 100644 src/main/erlang/g0101_0200/s0148_sort_list/readme.md create mode 100644 src/main/erlang/g0101_0200/s0152_maximum_product_subarray/Solution.erl create mode 100644 src/main/erlang/g0101_0200/s0152_maximum_product_subarray/readme.md create mode 100644 src/main/erlang/g0101_0200/s0153_find_minimum_in_rotated_sorted_array/Solution.erl create mode 100644 src/main/erlang/g0101_0200/s0153_find_minimum_in_rotated_sorted_array/readme.md create mode 100644 src/main/erlang/g0101_0200/s0155_min_stack/MinStack.erl create mode 100644 src/main/erlang/g0101_0200/s0155_min_stack/readme.md create mode 100644 src/main/erlang/g0101_0200/s0169_majority_element/Solution.erl create mode 100644 src/main/erlang/g0101_0200/s0169_majority_element/readme.md create mode 100644 src/main/erlang/g0101_0200/s0198_house_robber/Solution.erl create mode 100644 src/main/erlang/g0101_0200/s0198_house_robber/readme.md create mode 100644 src/main/erlang/g0101_0200/s0200_number_of_islands/Solution.erl create mode 100644 src/main/erlang/g0101_0200/s0200_number_of_islands/readme.md create mode 100644 src/main/erlang/g0201_0300/s0206_reverse_linked_list/Solution.erl create mode 100644 src/main/erlang/g0201_0300/s0206_reverse_linked_list/readme.md create mode 100644 src/main/erlang/g0201_0300/s0207_course_schedule/Solution.erl create mode 100644 src/main/erlang/g0201_0300/s0207_course_schedule/readme.md create mode 100644 src/main/erlang/g0201_0300/s0208_implement_trie_prefix_tree/Trie.erl create mode 100644 src/main/erlang/g0201_0300/s0208_implement_trie_prefix_tree/readme.md create mode 100644 src/main/erlang/g0201_0300/s0215_kth_largest_element_in_an_array/Solution.erl create mode 100644 src/main/erlang/g0201_0300/s0215_kth_largest_element_in_an_array/readme.md create mode 100644 src/main/erlang/g0201_0300/s0221_maximal_square/Solution.erl create mode 100644 src/main/erlang/g0201_0300/s0221_maximal_square/readme.md create mode 100644 src/main/erlang/g0201_0300/s0226_invert_binary_tree/Solution.erl create mode 100644 src/main/erlang/g0201_0300/s0226_invert_binary_tree/readme.md create mode 100644 src/main/erlang/g0201_0300/s0230_kth_smallest_element_in_a_bst/Solution.erl create mode 100644 src/main/erlang/g0201_0300/s0230_kth_smallest_element_in_a_bst/readme.md create mode 100644 src/main/erlang/g0201_0300/s0234_palindrome_linked_list/Solution.erl create mode 100644 src/main/erlang/g0201_0300/s0234_palindrome_linked_list/readme.md create mode 100644 src/main/erlang/g0201_0300/s0238_product_of_array_except_self/Solution.erl create mode 100644 src/main/erlang/g0201_0300/s0238_product_of_array_except_self/readme.md create mode 100644 src/main/erlang/g0201_0300/s0239_sliding_window_maximum/Solution.erl create mode 100644 src/main/erlang/g0201_0300/s0239_sliding_window_maximum/readme.md create mode 100644 src/main/erlang/g0201_0300/s0287_find_the_duplicate_number/Solution.erl create mode 100644 src/main/erlang/g0201_0300/s0287_find_the_duplicate_number/readme.md create mode 100644 src/main/erlang/g0201_0300/s0300_longest_increasing_subsequence/Solution.erl create mode 100644 src/main/erlang/g0201_0300/s0300_longest_increasing_subsequence/readme.md create mode 100644 src/main/erlang/g0301_0400/s0322_coin_change/Solution.erl create mode 100644 src/main/erlang/g0301_0400/s0322_coin_change/readme.md create mode 100644 src/main/erlang/g0301_0400/s0338_counting_bits/Solution.erl create mode 100644 src/main/erlang/g0301_0400/s0338_counting_bits/readme.md create mode 100644 src/main/erlang/g0301_0400/s0347_top_k_frequent_elements/Solution.erl create mode 100644 src/main/erlang/g0301_0400/s0347_top_k_frequent_elements/readme.md create mode 100644 src/main/erlang/g0301_0400/s0394_decode_string/Solution.erl create mode 100644 src/main/erlang/g0301_0400/s0394_decode_string/readme.md create mode 100644 src/main/erlang/g0401_0500/s0416_partition_equal_subset_sum/Solution.erl create mode 100644 src/main/erlang/g0401_0500/s0416_partition_equal_subset_sum/readme.md create mode 100644 src/main/erlang/g0401_0500/s0437_path_sum_iii/Solution.erl create mode 100644 src/main/erlang/g0401_0500/s0437_path_sum_iii/readme.md create mode 100644 src/main/erlang/g0401_0500/s0438_find_all_anagrams_in_a_string/Solution.erl create mode 100644 src/main/erlang/g0401_0500/s0438_find_all_anagrams_in_a_string/readme.md create mode 100644 src/main/erlang/g0401_0500/s0494_target_sum/Solution.erl create mode 100644 src/main/erlang/g0401_0500/s0494_target_sum/readme.md create mode 100644 src/main/erlang/g0501_0600/s0543_diameter_of_binary_tree/Solution.erl create mode 100644 src/main/erlang/g0501_0600/s0543_diameter_of_binary_tree/readme.md create mode 100644 src/main/erlang/g1101_1200/s1143_longest_common_subsequence/Solution.erl create mode 100644 src/main/erlang/g1101_1200/s1143_longest_common_subsequence/readme.md diff --git a/src/main/erlang/g0101_0200/s0139_word_break/Solution.erl b/src/main/erlang/g0101_0200/s0139_word_break/Solution.erl new file mode 100644 index 0000000..c160ec0 --- /dev/null +++ b/src/main/erlang/g0101_0200/s0139_word_break/Solution.erl @@ -0,0 +1,42 @@ +% #Medium #Top_100_Liked_Questions #Top_Interview_Questions #String #Hash_Table +% #Dynamic_Programming #Trie #Memoization #Algorithm_II_Day_15_Dynamic_Programming +% #Dynamic_Programming_I_Day_9 #Udemy_Dynamic_Programming #Big_O_Time_O(M+max*N)_Space_O(M+N+max) +% #2025_01_18_Time_1_(100.00%)_Space_60.03_(100.00%) + +-spec word_break(S :: unicode:unicode_binary(), WordDict :: [unicode:unicode_binary()]) -> boolean(). +word_break(S, WordDict) -> + % Initialize ETS table for memoization + ets:new(memo, [set, named_table]), + % Process word dict to include sizes + Words = [{Word, byte_size(Word)} || Word <- WordDict], + % Get result + Result = breakable(S, Words), + % Clean up + ets:delete(memo), + Result. + +-spec breakable(binary(), [{binary(), integer()}]) -> boolean(). +breakable(<<>>, _Words) -> + true; +breakable(S, Words) -> + case ets:lookup(memo, S) of + [{_, Result}] -> + Result; + [] -> + Result = try_words(S, Words, Words), + ets:insert(memo, {S, Result}), + Result + end. + +try_words(_S, [], _AllWords) -> + false; +try_words(S, [{Word, Len} | Rest], AllWords) -> + case S of + <> when Prefix =:= Word -> + case breakable(Remaining, AllWords) of + true -> true; + false -> try_words(S, Rest, AllWords) + end; + _ -> + try_words(S, Rest, AllWords) + end. diff --git a/src/main/erlang/g0101_0200/s0139_word_break/readme.md b/src/main/erlang/g0101_0200/s0139_word_break/readme.md new file mode 100644 index 0000000..ca9ce20 --- /dev/null +++ b/src/main/erlang/g0101_0200/s0139_word_break/readme.md @@ -0,0 +1,39 @@ +139\. Word Break + +Medium + +Given a string `s` and a dictionary of strings `wordDict`, return `true` if `s` can be segmented into a space-separated sequence of one or more dictionary words. + +**Note** that the same word in the dictionary may be reused multiple times in the segmentation. + +**Example 1:** + +**Input:** s = "leetcode", wordDict = ["leet","code"] + +**Output:** true + +**Explanation:** Return true because "leetcode" can be segmented as "leet code". + +**Example 2:** + +**Input:** s = "applepenapple", wordDict = ["apple","pen"] + +**Output:** true + +**Explanation:** Return true because "applepenapple" can be segmented as "apple pen apple". + +Note that you are allowed to reuse a dictionary word. + +**Example 3:** + +**Input:** s = "catsandog", wordDict = ["cats","dog","sand","and","cat"] + +**Output:** false + +**Constraints:** + +* `1 <= s.length <= 300` +* `1 <= wordDict.length <= 1000` +* `1 <= wordDict[i].length <= 20` +* `s` and `wordDict[i]` consist of only lowercase English letters. +* All the strings of `wordDict` are **unique**. diff --git a/src/main/erlang/g0101_0200/s0146_lru_cache/LRUCache.erl b/src/main/erlang/g0101_0200/s0146_lru_cache/LRUCache.erl new file mode 100644 index 0000000..d9b84f1 --- /dev/null +++ b/src/main/erlang/g0101_0200/s0146_lru_cache/LRUCache.erl @@ -0,0 +1,77 @@ +% #Medium #Top_100_Liked_Questions #Top_Interview_Questions #Hash_Table #Design #Linked_List +% #Doubly_Linked_List #Udemy_Linked_List #Big_O_Time_O(1)_Space_O(capacity) +% #2025_01_18_Time_312_(100.00%)_Space_273.78_(100.00%) + +%% Persistent Term Keys +-define(CAPACITY_KEY, {lru_cache, capacity}). +-define(CACHE_TABLE, lru_cache_cache_table). +-define(TTL_TABLE, lru_cache_ttl_table). + +%% API Specifications +-spec lru_cache_init_(Capacity :: integer()) -> ok. +lru_cache_init_(Capacity) -> + persistent_term:put(?CAPACITY_KEY, Capacity), + case ets:info(?CACHE_TABLE) of + undefined -> + ets:new(?CACHE_TABLE, [set, public, named_table]), + ets:new(?TTL_TABLE, [ordered_set, public, named_table]); + _ -> + ets:delete_all_objects(?CACHE_TABLE), + ets:delete_all_objects(?TTL_TABLE) + end, + ok. + +-spec lru_cache_get(Key :: integer()) -> integer(). +lru_cache_get(Key) -> + case extract(Key) of + {Key, Value} -> + insert(Key, Value), + Value; + -1 -> + -1 + end. + +-spec lru_cache_put(Key :: integer(), Value :: integer()) -> ok. +lru_cache_put(Key, Value) -> + _ = extract(Key), + insert(Key, Value), + evict(), + ok. + +%% Internal Functions +extract(Key) -> + case ets:lookup(?CACHE_TABLE, Key) of + [{Key, Uniq, Value}] -> + ets:delete(?TTL_TABLE, Uniq), + {Key, Value}; + [] -> + -1 + end. + +insert(Key, Value) -> + Uniq = unique_integer(), + ets:insert(?CACHE_TABLE, {Key, Uniq, Value}), + ets:insert(?TTL_TABLE, {Uniq, Key}). + +evict() -> + Capacity = persistent_term:get(?CAPACITY_KEY), + CurrentSize = ets:info(?CACHE_TABLE, size), + if + CurrentSize > Capacity -> + Uniq = ets:first(?TTL_TABLE), + [{_, Key}] = ets:lookup(?TTL_TABLE, Uniq), + ets:delete(?TTL_TABLE, Uniq), + ets:delete(?CACHE_TABLE, Key); + true -> + ok + end. + +unique_integer() -> + erlang:unique_integer([monotonic]). + +%% Your functions will be called as such: +%% lru_cache_init_(Capacity), +%% Param_1 = lru_cache_get(Key), +%% lru_cache_put(Key, Value), + +%% lru_cache_init_ will be called before every test case, in which you can do some necessary initializations. diff --git a/src/main/erlang/g0101_0200/s0146_lru_cache/readme.md b/src/main/erlang/g0101_0200/s0146_lru_cache/readme.md new file mode 100644 index 0000000..56cb023 --- /dev/null +++ b/src/main/erlang/g0101_0200/s0146_lru_cache/readme.md @@ -0,0 +1,48 @@ +146\. LRU Cache + +Medium + +Design a data structure that follows the constraints of a **[Least Recently Used (LRU) cache](https://en.wikipedia.org/wiki/Cache_replacement_policies#LRU)**. + +Implement the `LRUCache` class: + +* `LRUCache(int capacity)` Initialize the LRU cache with **positive** size `capacity`. +* `int get(int key)` Return the value of the `key` if the key exists, otherwise return `-1`. +* `void put(int key, int value)` Update the value of the `key` if the `key` exists. Otherwise, add the `key-value` pair to the cache. If the number of keys exceeds the `capacity` from this operation, **evict** the least recently used key. + +The functions `get` and `put` must each run in `O(1)` average time complexity. + +**Example 1:** + +**Input** ["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"] [[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]] + +**Output:** [null, null, null, 1, null, -1, null, -1, 3, 4] + +**Explanation:** + +LRUCache lRUCache = new LRUCache(2); + +lRUCache.put(1, 1); // cache is {1=1} + +lRUCache.put(2, 2); // cache is {1=1, 2=2} + +lRUCache.get(1); // return 1 + +lRUCache.put(3, 3); // LRU key was 2, evicts key 2, cache is {1=1, 3=3} + +lRUCache.get(2); // returns -1 (not found) + +lRUCache.put(4, 4); // LRU key was 1, evicts key 1, cache is {4=4, 3=3} + +lRUCache.get(1); // return -1 (not found) + +lRUCache.get(3); // return 3 + +lRUCache.get(4); // return 4 + +**Constraints:** + +* `1 <= capacity <= 3000` +* 0 <= key <= 104 +* 0 <= value <= 105 +* At most 2 * 105 calls will be made to `get` and `put`. diff --git a/src/main/erlang/g0101_0200/s0148_sort_list/Solution.erl b/src/main/erlang/g0101_0200/s0148_sort_list/Solution.erl new file mode 100644 index 0000000..b39c199 --- /dev/null +++ b/src/main/erlang/g0101_0200/s0148_sort_list/Solution.erl @@ -0,0 +1,29 @@ +% #Medium #Top_100_Liked_Questions #Top_Interview_Questions #Sorting #Two_Pointers #Linked_List +% #Divide_and_Conquer #Merge_Sort #Level_2_Day_4_Linked_List #Big_O_Time_O(log(N))_Space_O(log(N)) +% #2025_01_18_Time_43_(100.00%)_Space_102.77_(100.00%) + +%% Definition for singly-linked list. +%% +%% -record(list_node, {val = 0 :: integer(), +%% next = null :: 'null' | #list_node{}}). + +%% @spec sort_list(Head :: #list_node{} | null) -> #list_node{} | null. +-spec sort_list(Head :: #list_node{} | null) -> #list_node{} | null. +sort_list(Head) -> + List = node_to_list(Head, []), + SortedList = lists:sort(fun(X, Y) -> X > Y end, List), + list_to_node(SortedList, null). + +%% Converts a linked list to an Erlang list. +-spec node_to_list(Node :: #list_node{} | null, Acc :: [integer()]) -> [integer()]. +node_to_list(null, Acc) -> + Acc; +node_to_list(#list_node{val = Val, next = Next}, Acc) -> + node_to_list(Next, [Val | Acc]). + +%% Converts an Erlang list to a linked list. +-spec list_to_node(List :: [integer()], Node :: #list_node{} | null) -> #list_node{} | null. +list_to_node([], Node) -> + Node; +list_to_node([H | T], Node) -> + list_to_node(T, #list_node{val = H, next = Node}). diff --git a/src/main/erlang/g0101_0200/s0148_sort_list/readme.md b/src/main/erlang/g0101_0200/s0148_sort_list/readme.md new file mode 100644 index 0000000..15fed8c --- /dev/null +++ b/src/main/erlang/g0101_0200/s0148_sort_list/readme.md @@ -0,0 +1,34 @@ +148\. Sort List + +Medium + +Given the `head` of a linked list, return _the list after sorting it in **ascending order**_. + +**Example 1:** + +![](https://assets.leetcode.com/uploads/2020/09/14/sort_list_1.jpg) + +**Input:** head = [4,2,1,3] + +**Output:** [1,2,3,4] + +**Example 2:** + +![](https://assets.leetcode.com/uploads/2020/09/14/sort_list_2.jpg) + +**Input:** head = [-1,5,3,4,0] + +**Output:** [-1,0,3,4,5] + +**Example 3:** + +**Input:** head = [] + +**Output:** [] + +**Constraints:** + +* The number of nodes in the list is in the range [0, 5 * 104]. +* -105 <= Node.val <= 105 + +**Follow up:** Can you sort the linked list in `O(n logn)` time and `O(1)` memory (i.e. constant space)? diff --git a/src/main/erlang/g0101_0200/s0152_maximum_product_subarray/Solution.erl b/src/main/erlang/g0101_0200/s0152_maximum_product_subarray/Solution.erl new file mode 100644 index 0000000..0f45751 --- /dev/null +++ b/src/main/erlang/g0101_0200/s0152_maximum_product_subarray/Solution.erl @@ -0,0 +1,18 @@ +% #Medium #Top_100_Liked_Questions #Top_Interview_Questions #Array #Dynamic_Programming +% #Dynamic_Programming_I_Day_6 #Level_2_Day_13_Dynamic_Programming #Udemy_Dynamic_Programming +% #Big_O_Time_O(N)_Space_O(1) #2025_01_18_Time_0_(100.00%)_Space_63.79_(100.00%) + +-spec max_product(Nums :: [integer()]) -> integer(). +max_product(Nums) -> + max_product(Nums, 1, 1, -(1 bsl 31)). + +-spec max_product(Nums :: [integer()], integer(), integer(), integer()) -> integer(). +max_product([], _, _, MaxProduct) -> + MaxProduct; +max_product([H|T], MaxCurrent, MinCurrent, MaxProduct) -> + % The new maximum and minimum products are derived by comparing + % the current number, its product with the maximum so far, and its product with the minimum so far + NewMaxCurrent = max(max(H, H * MaxCurrent), H * MinCurrent), + NewMinCurrent = min(min(H, H * MaxCurrent), H * MinCurrent), + NewMaxProduct = max(MaxProduct, NewMaxCurrent), + max_product(T, NewMaxCurrent, NewMinCurrent, NewMaxProduct). diff --git a/src/main/erlang/g0101_0200/s0152_maximum_product_subarray/readme.md b/src/main/erlang/g0101_0200/s0152_maximum_product_subarray/readme.md new file mode 100644 index 0000000..3a21f70 --- /dev/null +++ b/src/main/erlang/g0101_0200/s0152_maximum_product_subarray/readme.md @@ -0,0 +1,31 @@ +152\. Maximum Product Subarray + +Medium + +Given an integer array `nums`, find a contiguous non-empty subarray within the array that has the largest product, and return _the product_. + +The test cases are generated so that the answer will fit in a **32-bit** integer. + +A **subarray** is a contiguous subsequence of the array. + +**Example 1:** + +**Input:** nums = [2,3,-2,4] + +**Output:** 6 + +**Explanation:** [2,3] has the largest product 6. + +**Example 2:** + +**Input:** nums = [-2,0,-1] + +**Output:** 0 + +**Explanation:** The result cannot be 2, because [-2,-1] is not a subarray. + +**Constraints:** + +* 1 <= nums.length <= 2 * 104 +* `-10 <= nums[i] <= 10` +* The product of any prefix or suffix of `nums` is **guaranteed** to fit in a **32-bit** integer. diff --git a/src/main/erlang/g0101_0200/s0153_find_minimum_in_rotated_sorted_array/Solution.erl b/src/main/erlang/g0101_0200/s0153_find_minimum_in_rotated_sorted_array/Solution.erl new file mode 100644 index 0000000..f4e2c96 --- /dev/null +++ b/src/main/erlang/g0101_0200/s0153_find_minimum_in_rotated_sorted_array/Solution.erl @@ -0,0 +1,15 @@ +% #Medium #Top_100_Liked_Questions #Array #Binary_Search #Algorithm_II_Day_2_Binary_Search +% #Binary_Search_I_Day_12 #Udemy_Binary_Search #Big_O_Time_O(log_N)_Space_O(log_N) +% #2025_01_18_Time_0_(100.00%)_Space_60.97_(100.00%) + +-spec find_min(Nums :: [integer()]) -> integer(). +find_min([N]) -> + N; +find_min(Nums) -> + Count = length(Nums), + Mid = Count div 2, + Left = lists:sublist(Nums, Mid), + Right = lists:nthtail(Mid, Nums), + MinLeft = find_min(Left), + MinRight = find_min(Right), + erlang:min(MinLeft, MinRight). diff --git a/src/main/erlang/g0101_0200/s0153_find_minimum_in_rotated_sorted_array/readme.md b/src/main/erlang/g0101_0200/s0153_find_minimum_in_rotated_sorted_array/readme.md new file mode 100644 index 0000000..5ca40e0 --- /dev/null +++ b/src/main/erlang/g0101_0200/s0153_find_minimum_in_rotated_sorted_array/readme.md @@ -0,0 +1,46 @@ +153\. Find Minimum in Rotated Sorted Array + +Medium + +Suppose an array of length `n` sorted in ascending order is **rotated** between `1` and `n` times. For example, the array `nums = [0,1,2,4,5,6,7]` might become: + +* `[4,5,6,7,0,1,2]` if it was rotated `4` times. +* `[0,1,2,4,5,6,7]` if it was rotated `7` times. + +Notice that **rotating** an array `[a[0], a[1], a[2], ..., a[n-1]]` 1 time results in the array `[a[n-1], a[0], a[1], a[2], ..., a[n-2]]`. + +Given the sorted rotated array `nums` of **unique** elements, return _the minimum element of this array_. + +You must write an algorithm that runs in `O(log n) time.` + +**Example 1:** + +**Input:** nums = [3,4,5,1,2] + +**Output:** 1 + +**Explanation:** The original array was [1,2,3,4,5] rotated 3 times. + +**Example 2:** + +**Input:** nums = [4,5,6,7,0,1,2] + +**Output:** 0 + +**Explanation:** The original array was [0,1,2,4,5,6,7] and it was rotated 4 times. + +**Example 3:** + +**Input:** nums = [11,13,15,17] + +**Output:** 11 + +**Explanation:** The original array was [11,13,15,17] and it was rotated 4 times. + +**Constraints:** + +* `n == nums.length` +* `1 <= n <= 5000` +* `-5000 <= nums[i] <= 5000` +* All the integers of `nums` are **unique**. +* `nums` is sorted and rotated between `1` and `n` times. diff --git a/src/main/erlang/g0101_0200/s0155_min_stack/MinStack.erl b/src/main/erlang/g0101_0200/s0155_min_stack/MinStack.erl new file mode 100644 index 0000000..769fcad --- /dev/null +++ b/src/main/erlang/g0101_0200/s0155_min_stack/MinStack.erl @@ -0,0 +1,55 @@ +% #Medium #Top_100_Liked_Questions #Top_Interview_Questions #Stack #Design +% #Data_Structure_II_Day_14_Stack_Queue #Programming_Skills_II_Day_18 #Level_2_Day_16_Design +% #Udemy_Design #Big_O_Time_O(1)_Space_O(N) #2025_01_18_Time_16_(100.00%)_Space_78.65_(100.00%) + +-spec min_stack_init_() -> any(). +min_stack_init_() -> + catch ets:delete(min_stack), + ets:new(min_stack, [named_table, ordered_set, public]), + ets:insert(min_stack, {size, 0}), + ok. + +-spec min_stack_push(Val :: integer()) -> any(). +min_stack_push(Val) -> + [{size, Size}] = ets:lookup(min_stack, size), + CurrentMin = case Size of + 0 -> Val; + _ -> min(Val, min_stack_get_min()) + end, + ets:insert(min_stack, {Size + 1, {Val, CurrentMin}}), + ets:insert(min_stack, {size, Size + 1}), + ok. + +-spec min_stack_pop() -> any(). +min_stack_pop() -> + [{size, Size}] = ets:lookup(min_stack, size), + case Size > 0 of + true -> + ets:delete(min_stack, Size), + ets:insert(min_stack, {size, Size - 1}), + ok; + false -> + ok + end. + +-spec min_stack_top() -> integer(). +min_stack_top() -> + [{size, Size}] = ets:lookup(min_stack, size), + case Size > 0 of + true -> + [{_, {Val, _}}] = ets:lookup(min_stack, Size), + Val; + false -> + 0 % Default value for empty stack + end. + +-spec min_stack_get_min() -> integer(). +min_stack_get_min() -> + [{size, Size}] = ets:lookup(min_stack, size), + case Size > 0 of + true -> + [{_, {_, Min}}] = ets:lookup(min_stack, Size), + Min; + false -> + 0 % Default value for empty stack + end. diff --git a/src/main/erlang/g0101_0200/s0155_min_stack/readme.md b/src/main/erlang/g0101_0200/s0155_min_stack/readme.md new file mode 100644 index 0000000..9daebe3 --- /dev/null +++ b/src/main/erlang/g0101_0200/s0155_min_stack/readme.md @@ -0,0 +1,40 @@ +155\. Min Stack + +Easy + +Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. + +Implement the `MinStack` class: + +* `MinStack()` initializes the stack object. +* `void push(int val)` pushes the element `val` onto the stack. +* `void pop()` removes the element on the top of the stack. +* `int top()` gets the top element of the stack. +* `int getMin()` retrieves the minimum element in the stack. + +**Example 1:** + +**Input** + + ["MinStack","push","push","push","getMin","pop","top","getMin"] + [[],[-2],[0],[-3],[],[],[],[]] + +**Output:** [null,null,null,null,-3,null,0,-2] + +**Explanation:** + + MinStack minStack = new MinStack(); + minStack.push(-2); + minStack.push(0); + minStack.push(-3); + minStack.getMin(); // return -3 + minStack.pop(); + minStack.top(); // return 0 + minStack.getMin(); // return -2 + +**Constraints:** + +* -231 <= val <= 231 - 1 +* Methods `pop`, `top` and `getMin` operations will always be called on **non-empty** stacks. +* At most 3 * 104 calls will be made to `push`, `pop`, `top`, and `getMin`. + diff --git a/src/main/erlang/g0101_0200/s0169_majority_element/Solution.erl b/src/main/erlang/g0101_0200/s0169_majority_element/Solution.erl new file mode 100644 index 0000000..8c08122 --- /dev/null +++ b/src/main/erlang/g0101_0200/s0169_majority_element/Solution.erl @@ -0,0 +1,15 @@ +% #Easy #Top_100_Liked_Questions #Top_Interview_Questions #Array #Hash_Table #Sorting #Counting +% #Divide_and_Conquer #Data_Structure_II_Day_1_Array #Udemy_Famous_Algorithm +% #Big_O_Time_O(n)_Space_O(1) #2025_01_18_Time_2_(100.00%)_Space_76.02_(100.00%) + +-spec majority_element(Nums :: [integer()]) -> integer(). +majority_element(Nums) -> + element(1, lists:foldl( + fun(Num, {Candi, Cnt}) -> + NewCandi = if Cnt == 0 -> Num; true -> Candi end, + NewCnt = if NewCandi == Num -> Cnt + 1; true -> Cnt - 1 end, + {NewCandi, NewCnt} + end, + {0, 0}, + Nums + )). diff --git a/src/main/erlang/g0101_0200/s0169_majority_element/readme.md b/src/main/erlang/g0101_0200/s0169_majority_element/readme.md new file mode 100644 index 0000000..66b1443 --- /dev/null +++ b/src/main/erlang/g0101_0200/s0169_majority_element/readme.md @@ -0,0 +1,27 @@ +169\. Majority Element + +Easy + +Given an array `nums` of size `n`, return _the majority element_. + +The majority element is the element that appears more than `⌊n / 2⌋` times. You may assume that the majority element always exists in the array. + +**Example 1:** + +**Input:** nums = [3,2,3] + +**Output:** 3 + +**Example 2:** + +**Input:** nums = [2,2,1,1,1,2,2] + +**Output:** 2 + +**Constraints:** + +* `n == nums.length` +* 1 <= n <= 5 * 104 +* -109 <= nums[i] <= 109 + +**Follow-up:** Could you solve the problem in linear time and in `O(1)` space? diff --git a/src/main/erlang/g0101_0200/s0198_house_robber/Solution.erl b/src/main/erlang/g0101_0200/s0198_house_robber/Solution.erl new file mode 100644 index 0000000..b6a9e9f --- /dev/null +++ b/src/main/erlang/g0101_0200/s0198_house_robber/Solution.erl @@ -0,0 +1,24 @@ +% #Medium #Top_100_Liked_Questions #Top_Interview_Questions #Array #Dynamic_Programming +% #Algorithm_I_Day_12_Dynamic_Programming #Dynamic_Programming_I_Day_3 +% #Level_2_Day_12_Dynamic_Programming #Udemy_Dynamic_Programming #Big_O_Time_O(n)_Space_O(n) +% #2025_01_18_Time_0_(100.00%)_Space_58.88_(100.00%) + +-spec rob(Nums :: [integer()]) -> integer(). +rob(Nums) -> + Results = lists:foldr( + fun(E, Results) -> + Result = max(nth(2, Results), nth(3, Results)), + [Result + E| Results] + end, + [], + Nums + ), + max(nth(1, Results), nth(2, Results)). + +nth(Pos, Results) -> + case length(Results) of + N when N < Pos -> + 0; + _ -> + lists:nth(Pos, Results) + end. diff --git a/src/main/erlang/g0101_0200/s0198_house_robber/readme.md b/src/main/erlang/g0101_0200/s0198_house_robber/readme.md new file mode 100644 index 0000000..71ac79a --- /dev/null +++ b/src/main/erlang/g0101_0200/s0198_house_robber/readme.md @@ -0,0 +1,28 @@ +198\. House Robber + +Medium + +You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security systems connected and **it will automatically contact the police if two adjacent houses were broken into on the same night**. + +Given an integer array `nums` representing the amount of money of each house, return _the maximum amount of money you can rob tonight **without alerting the police**_. + +**Example 1:** + +**Input:** nums = [1,2,3,1] + +**Output:** 4 + +**Explanation:** Rob house 1 (money = 1) and then rob house 3 (money = 3). Total amount you can rob = 1 + 3 = 4. + +**Example 2:** + +**Input:** nums = [2,7,9,3,1] + +**Output:** 12 + +**Explanation:** Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1). Total amount you can rob = 2 + 9 + 1 = 12. + +**Constraints:** + +* `1 <= nums.length <= 100` +* `0 <= nums[i] <= 400` diff --git a/src/main/erlang/g0101_0200/s0200_number_of_islands/Solution.erl b/src/main/erlang/g0101_0200/s0200_number_of_islands/Solution.erl new file mode 100644 index 0000000..0463c83 --- /dev/null +++ b/src/main/erlang/g0101_0200/s0200_number_of_islands/Solution.erl @@ -0,0 +1,41 @@ +% #Medium #Top_100_Liked_Questions #Top_Interview_Questions #Array #Depth_First_Search +% #Breadth_First_Search #Matrix #Union_Find +% #Algorithm_II_Day_6_Breadth_First_Search_Depth_First_Search +% #Graph_Theory_I_Day_1_Matrix_Related_Problems #Level_1_Day_9_Graph/BFS/DFS #Udemy_Graph +% #Big_O_Time_O(M*N)_Space_O(M*N) #2025_01_21_Time_350_(100.00%)_Space_110.42_(100.00%) + +-spec num_islands([[char()]]) -> integer(). +num_islands(Grid) -> + Table = ets:new(grid, []), + lists:foreach( + fun({Row, I}) -> + lists:foreach( + fun({X, J}) when X =:= $1 -> + ets:insert(Table, {{I, J}}); + (_) -> ok + end, + lists:zip(Row, lists:seq(0, length(Row) - 1)) + ) + end, + lists:zip(Grid, lists:seq(0, length(Grid) - 1)) + ), + count(Table, 0). + +count(Table, Ans) -> + case ets:first(Table) of + '$end_of_table' -> Ans; + {I, J} -> + sink_island(Table, {I, J}), + count(Table, Ans + 1) + end. + +sink_island(Table, {I, J}) -> + case ets:member(Table, {I, J}) of + true -> + ets:delete(Table, {I, J}), + sink_island(Table, {I - 1, J}), + sink_island(Table, {I + 1, J}), + sink_island(Table, {I, J - 1}), + sink_island(Table, {I, J + 1}); + false -> ok + end. diff --git a/src/main/erlang/g0101_0200/s0200_number_of_islands/readme.md b/src/main/erlang/g0101_0200/s0200_number_of_islands/readme.md new file mode 100644 index 0000000..78b086e --- /dev/null +++ b/src/main/erlang/g0101_0200/s0200_number_of_islands/readme.md @@ -0,0 +1,46 @@ +200\. Number of Islands + +Medium + +Given an `m x n` 2D binary grid `grid` which represents a map of `'1'`s (land) and `'0'`s (water), return _the number of islands_. + +An **island** is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water. + +**Example 1:** + +**Input:** grid = [ + +["1","1","1","1","0"], + +["1","1","0","1","0"], + +["1","1","0","0","0"], + +["0","0","0","0","0"] + +] + +**Output:** 1 + +**Example 2:** + +**Input:** grid = [ + +["1","1","0","0","0"], + +["1","1","0","0","0"], + +["0","0","1","0","0"], + +["0","0","0","1","1"] + +] + +**Output:** 3 + +**Constraints:** + +* `m == grid.length` +* `n == grid[i].length` +* `1 <= m, n <= 300` +* `grid[i][j]` is `'0'` or `'1'`. diff --git a/src/main/erlang/g0201_0300/s0206_reverse_linked_list/Solution.erl b/src/main/erlang/g0201_0300/s0206_reverse_linked_list/Solution.erl new file mode 100644 index 0000000..fbc8c83 --- /dev/null +++ b/src/main/erlang/g0201_0300/s0206_reverse_linked_list/Solution.erl @@ -0,0 +1,15 @@ +% #Easy #Top_100_Liked_Questions #Top_Interview_Questions #Linked_List #Recursion +% #Data_Structure_I_Day_8_Linked_List #Algorithm_I_Day_10_Recursion_Backtracking +% #Level_1_Day_3_Linked_List #Udemy_Linked_List #Big_O_Time_O(N)_Space_O(1) +% #2025_01_18_Time_0_(100.00%)_Space_64.38_(100.00%) + +%% Definition for singly-linked list. +%% +%% -record(list_node, {val = 0 :: integer(), +%% next = null :: 'null' | #list_node{}}). + +-spec reverse_list(Head :: #list_node{} | null) -> #list_node{} | null. +reverse_list(null) -> null; +reverse_list(#list_node{val=V, next=Next}) -> reverse_list(Next, #list_node{val=V, next=null}). +reverse_list(null, Acc) -> Acc; +reverse_list(#list_node{val=V,next=Next}, Acc) -> reverse_list(Next, #list_node{val=V, next=Acc}). diff --git a/src/main/erlang/g0201_0300/s0206_reverse_linked_list/readme.md b/src/main/erlang/g0201_0300/s0206_reverse_linked_list/readme.md new file mode 100644 index 0000000..7ded239 --- /dev/null +++ b/src/main/erlang/g0201_0300/s0206_reverse_linked_list/readme.md @@ -0,0 +1,34 @@ +206\. Reverse Linked List + +Easy + +Given the `head` of a singly linked list, reverse the list, and return _the reversed list_. + +**Example 1:** + +![](https://assets.leetcode.com/uploads/2021/02/19/rev1ex1.jpg) + +**Input:** head = [1,2,3,4,5] + +**Output:** [5,4,3,2,1] + +**Example 2:** + +![](https://assets.leetcode.com/uploads/2021/02/19/rev1ex2.jpg) + +**Input:** head = [1,2] + +**Output:** [2,1] + +**Example 3:** + +**Input:** head = [] + +**Output:** [] + +**Constraints:** + +* The number of nodes in the list is the range `[0, 5000]`. +* `-5000 <= Node.val <= 5000` + +**Follow up:** A linked list can be reversed either iteratively or recursively. Could you implement both? diff --git a/src/main/erlang/g0201_0300/s0207_course_schedule/Solution.erl b/src/main/erlang/g0201_0300/s0207_course_schedule/Solution.erl new file mode 100644 index 0000000..bd3e6b8 --- /dev/null +++ b/src/main/erlang/g0201_0300/s0207_course_schedule/Solution.erl @@ -0,0 +1,69 @@ +% #Medium #Top_100_Liked_Questions #Top_Interview_Questions #Depth_First_Search +% #Breadth_First_Search #Graph #Topological_Sort #Big_O_Time_O(N)_Space_O(N) +% #2025_01_19_Time_220_(100.00%)_Space_67.41_(100.00%) + +-define(WHITE, 0). +-define(GRAY, 1). +-define(BLACK, 2). + +-spec can_finish(NumCourses :: integer(), Prerequisites :: [[integer()]]) -> boolean(). +can_finish(NumCourses, Prerequisites) -> + % Create adjacency list as a list of lists instead of a map + AdjList = create_adj_list(NumCourses, Prerequisites), + % Use array for colors instead of map + Colors = array:new(NumCourses, {default, ?WHITE}), + % Check for cycles + not has_cycle_in_graph(AdjList, Colors, 0, NumCourses). + +-spec create_adj_list(NumCourses :: integer(), Prerequisites :: [[integer()]]) -> [[integer()]]. +create_adj_list(NumCourses, Prerequisites) -> + % Initialize empty lists for each course + EmptyAdj = [[] || _ <- lists:seq(1, NumCourses)], + % Fill adjacency lists + lists:foldl( + fun([To, From], Acc) -> + lists:sublist(Acc, From) ++ + [[To | lists:nth(From + 1, Acc)]] ++ + lists:nthtail(From + 1, Acc) + end, + EmptyAdj, + Prerequisites + ). + +-spec has_cycle_in_graph([[integer()]], array:array(), integer(), integer()) -> boolean(). +has_cycle_in_graph(_AdjList, _Colors, Current, NumCourses) when Current >= NumCourses -> + false; +has_cycle_in_graph(AdjList, Colors, Current, NumCourses) -> + case array:get(Current, Colors) =:= ?WHITE andalso length(lists:nth(Current + 1, AdjList)) > 0 of + true -> + case dfs(AdjList, Colors, Current) of + {true, _} -> true; + {false, NewColors} -> + has_cycle_in_graph(AdjList, NewColors, Current + 1, NumCourses) + end; + false -> + has_cycle_in_graph(AdjList, Colors, Current + 1, NumCourses) + end. + +-spec dfs([[integer()]], array:array(), integer()) -> {boolean(), array:array()}. +dfs(AdjList, Colors, Node) -> + Colors1 = array:set(Node, ?GRAY, Colors), + Neighbors = lists:nth(Node + 1, AdjList), + check_neighbors(AdjList, Neighbors, Colors1, Node). + +-spec check_neighbors([[integer()]], [integer()], array:array(), integer()) -> {boolean(), array:array()}. +check_neighbors(_, [], Colors, Node) -> + {false, array:set(Node, ?BLACK, Colors)}; +check_neighbors(AdjList, [Neighbor|Rest], Colors, Node) -> + case array:get(Neighbor, Colors) of + ?GRAY -> + {true, Colors}; + ?WHITE -> + case dfs(AdjList, Colors, Neighbor) of + {true, NewColors} -> {true, NewColors}; + {false, NewColors} -> + check_neighbors(AdjList, Rest, NewColors, Node) + end; + ?BLACK -> + check_neighbors(AdjList, Rest, Colors, Node) + end. diff --git a/src/main/erlang/g0201_0300/s0207_course_schedule/readme.md b/src/main/erlang/g0201_0300/s0207_course_schedule/readme.md new file mode 100644 index 0000000..fa1d34b --- /dev/null +++ b/src/main/erlang/g0201_0300/s0207_course_schedule/readme.md @@ -0,0 +1,33 @@ +207\. Course Schedule + +Medium + +There are a total of `numCourses` courses you have to take, labeled from `0` to `numCourses - 1`. You are given an array `prerequisites` where prerequisites[i] = [ai, bi] indicates that you **must** take course bi first if you want to take course ai. + +* For example, the pair `[0, 1]`, indicates that to take course `0` you have to first take course `1`. + +Return `true` if you can finish all courses. Otherwise, return `false`. + +**Example 1:** + +**Input:** numCourses = 2, prerequisites = [[1,0]] + +**Output:** true + +**Explanation:** There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible. + +**Example 2:** + +**Input:** numCourses = 2, prerequisites = [[1,0],[0,1]] + +**Output:** false + +**Explanation:** There are a total of 2 courses to take. To take course 1 you should have finished course 0, and to take course 0 you should also have finished course 1. So it is impossible. + +**Constraints:** + +* `1 <= numCourses <= 2000` +* `0 <= prerequisites.length <= 5000` +* `prerequisites[i].length == 2` +* 0 <= ai, bi < numCourses +* All the pairs prerequisites[i] are **unique**. diff --git a/src/main/erlang/g0201_0300/s0208_implement_trie_prefix_tree/Trie.erl b/src/main/erlang/g0201_0300/s0208_implement_trie_prefix_tree/Trie.erl new file mode 100644 index 0000000..266b9e0 --- /dev/null +++ b/src/main/erlang/g0201_0300/s0208_implement_trie_prefix_tree/Trie.erl @@ -0,0 +1,61 @@ +% #Medium #Top_100_Liked_Questions #Top_Interview_Questions #String #Hash_Table #Design #Trie +% #Level_2_Day_16_Design #Udemy_Trie_and_Heap +% #Big_O_Time_O(word.length())_or_O(prefix.length())_Space_O(N) +% #2025_01_19_Time_85_(100.00%)_Space_99.16_(100.00%) + +% Initialize the trie using ETS +-spec trie_init_() -> any(). +trie_init_() -> + % Create ETS table if it doesn't exist + case ets:info(trie_table) of + undefined -> + ets:new(trie_table, [set, public, named_table]); + _ -> + ets:delete(trie_table), + ets:new(trie_table, [set, public, named_table]) + end. + +% Insert a word into the trie +-spec trie_insert(Word :: unicode:unicode_binary()) -> any(). +trie_insert(Word) -> + % Insert all prefixes with false flag + insert_prefixes(Word), + % Mark the complete word with true flag + ets:insert(trie_table, {Word, true}). + +% Search for a complete word +-spec trie_search(Word :: unicode:unicode_binary()) -> boolean(). +trie_search(Word) -> + case ets:lookup(trie_table, Word) of + [{_, true}] -> true; + _ -> false + end. + +% Check if any word starts with the given prefix +-spec trie_starts_with(Prefix :: unicode:unicode_binary()) -> boolean(). +trie_starts_with(Prefix) -> + case ets:lookup(trie_table, Prefix) of + [{_, _}] -> true; + [] -> false + end. + +% Helper function to insert all prefixes of a word +-spec insert_prefixes(Word :: unicode:unicode_binary()) -> ok. +insert_prefixes(Word) -> + Prefixes = get_all_prefixes(Word), + [ets:insert_new(trie_table, {Prefix, false}) || Prefix <- Prefixes],` + ok. + +% Helper function to generate all prefixes of a word +-spec get_all_prefixes(Word :: unicode:unicode_binary()) -> [unicode:unicode_binary()]. +get_all_prefixes(Word) -> + Size = byte_size(Word), + [binary:part(Word, 0, Len) || Len <- lists:seq(1, Size - 1)]. + +%% Your functions will be called as such: +%% trie_init_(), +%% trie_insert(Word), +%% Param_2 = trie_search(Word), +%% Param_3 = trie_starts_with(Prefix), + +%% trie_init_ will be called before every test case, in which you can do some necessary initializations. diff --git a/src/main/erlang/g0201_0300/s0208_implement_trie_prefix_tree/readme.md b/src/main/erlang/g0201_0300/s0208_implement_trie_prefix_tree/readme.md new file mode 100644 index 0000000..e9d3909 --- /dev/null +++ b/src/main/erlang/g0201_0300/s0208_implement_trie_prefix_tree/readme.md @@ -0,0 +1,40 @@ +208\. Implement Trie (Prefix Tree) + +Medium + +A [**trie**](https://en.wikipedia.org/wiki/Trie) (pronounced as "try") or **prefix tree** is a tree data structure used to efficiently store and retrieve keys in a dataset of strings. There are various applications of this data structure, such as autocomplete and spellchecker. + +Implement the Trie class: + +* `Trie()` Initializes the trie object. +* `void insert(String word)` Inserts the string `word` into the trie. +* `boolean search(String word)` Returns `true` if the string `word` is in the trie (i.e., was inserted before), and `false` otherwise. +* `boolean startsWith(String prefix)` Returns `true` if there is a previously inserted string `word` that has the prefix `prefix`, and `false` otherwise. + +**Example 1:** + +**Input** ["Trie", "insert", "search", "search", "startsWith", "insert", "search"] [[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]] + +**Output:** [null, null, true, false, true, null, true] + +**Explanation:** + +Trie trie = new Trie(); + +trie.insert("apple"); + +trie.search("apple"); // return True + +trie.search("app"); // return False + +trie.startsWith("app"); // return True + +trie.insert("app"); + +trie.search("app"); // return True + +**Constraints:** + +* `1 <= word.length, prefix.length <= 2000` +* `word` and `prefix` consist only of lowercase English letters. +* At most 3 * 104 calls **in total** will be made to `insert`, `search`, and `startsWith`. diff --git a/src/main/erlang/g0201_0300/s0215_kth_largest_element_in_an_array/Solution.erl b/src/main/erlang/g0201_0300/s0215_kth_largest_element_in_an_array/Solution.erl new file mode 100644 index 0000000..d8184a0 --- /dev/null +++ b/src/main/erlang/g0201_0300/s0215_kth_largest_element_in_an_array/Solution.erl @@ -0,0 +1,25 @@ +% #Medium #Top_100_Liked_Questions #Top_Interview_Questions #Array #Sorting #Heap_Priority_Queue +% #Divide_and_Conquer #Quickselect #Data_Structure_II_Day_20_Heap_Priority_Queue +% #Big_O_Time_O(n*log(n))_Space_O(log(n)) #2025_01_19_Time_803_(100.00%)_Space_147.74_(100.00%) + +-spec find_kth_largest(Nums :: [integer()], K :: integer()) -> integer(). +find_kth_largest(Nums, K) -> + Q = gb_sets:new(), + FinalQ = lists:foldl(fun({N, I}, AccQ) -> + case gb_sets:is_element({N, I}, AccQ) of + true -> AccQ; + false -> + case gb_sets:size(AccQ) < K of + true -> + gb_sets:insert({N, I}, AccQ); + false -> + {Smallest, TempQ} = gb_sets:take_smallest(AccQ), + gb_sets:insert(max(Smallest, {N, I}), TempQ) + end + end + end, Q, lists:zip(Nums, lists:seq(1, length(Nums)))), + element(1, gb_sets:smallest(FinalQ)). + +% Helper function to find the maximum of two tuples based on their first element. +max({N1, I1}, {N2, I2}) when N1 >= N2 -> {N1, I1}; +max(_, {N2, I2}) -> {N2, I2}. diff --git a/src/main/erlang/g0201_0300/s0215_kth_largest_element_in_an_array/readme.md b/src/main/erlang/g0201_0300/s0215_kth_largest_element_in_an_array/readme.md new file mode 100644 index 0000000..e6b9072 --- /dev/null +++ b/src/main/erlang/g0201_0300/s0215_kth_largest_element_in_an_array/readme.md @@ -0,0 +1,26 @@ +215\. Kth Largest Element in an Array + +Medium + +Given an integer array `nums` and an integer `k`, return _the_ kth _largest element in the array_. + +Note that it is the kth largest element in the sorted order, not the kth distinct element. + +You must solve it in `O(n)` time complexity. + +**Example 1:** + +**Input:** nums = [3,2,1,5,6,4], k = 2 + +**Output:** 5 + +**Example 2:** + +**Input:** nums = [3,2,3,1,2,4,5,5,6], k = 4 + +**Output:** 4 + +**Constraints:** + +* 1 <= k <= nums.length <= 105 +* -104 <= nums[i] <= 104 diff --git a/src/main/erlang/g0201_0300/s0221_maximal_square/Solution.erl b/src/main/erlang/g0201_0300/s0221_maximal_square/Solution.erl new file mode 100644 index 0000000..5b132e8 --- /dev/null +++ b/src/main/erlang/g0201_0300/s0221_maximal_square/Solution.erl @@ -0,0 +1,61 @@ +% #Medium #Array #Dynamic_Programming #Matrix #Dynamic_Programming_I_Day_16 +% #Big_O_Time_O(m*n)_Space_O(m*n) #2025_01_19_Time_3221_(100.00%)_Space_127.48_(100.00%) + +-spec maximal_square(Matrix :: [[char()]]) -> integer(). +maximal_square([]) -> 0; +maximal_square([[]|_]) -> 0; +maximal_square(Matrix) -> + M = length(Matrix), + N = length(hd(Matrix)), + + % Initialize DP array with all zeros + DP = lists:duplicate(M + 1, lists:duplicate(N + 1, 0)), + + % Iterate through matrix and build DP table + {MaxSquare, _} = lists:foldl( + fun(I, {MaxSoFar, DPCurrent}) -> + process_row(I, Matrix, N, MaxSoFar, DPCurrent) + end, + {0, DP}, + lists:seq(1, M) + ), + + MaxSquare * MaxSquare. + +process_row(I, Matrix, N, MaxSoFar, DP) -> + lists:foldl( + fun(J, {CurrentMax, CurrentDP}) -> + case lists:nth(J, lists:nth(I, Matrix)) of + $1 -> + Val1 = get_dp_value(CurrentDP, I-1, J), + Val2 = get_dp_value(CurrentDP, I, J-1), + Val3 = get_dp_value(CurrentDP, I-1, J-1), + NewVal = 1 + min3(Val1, Val2, Val3), + NewDP = set_dp_value(CurrentDP, I, J, NewVal), + {max(CurrentMax, NewVal), NewDP}; + _ -> + {CurrentMax, CurrentDP} + end + end, + {MaxSoFar, DP}, + lists:seq(1, N) + ). + +get_dp_value(DP, I, J) when I > 0, J > 0 -> + lists:nth(J + 1, lists:nth(I + 1, DP)); +get_dp_value(_, _, _) -> 0. + +set_dp_value(DP, I, J, Value) -> + Row = lists:nth(I + 1, DP), + NewRow = list_set(Row, J + 1, Value), + list_set(DP, I + 1, NewRow). + +list_set(List, Pos, Value) -> + {Head, [_|Tail]} = lists:split(Pos - 1, List), + Head ++ [Value] ++ Tail. + +min3(A, B, C) -> + min(A, min(B, C)). + +max(A, B) when A > B -> A; +max(_, B) -> B. diff --git a/src/main/erlang/g0201_0300/s0221_maximal_square/readme.md b/src/main/erlang/g0201_0300/s0221_maximal_square/readme.md new file mode 100644 index 0000000..7a2658a --- /dev/null +++ b/src/main/erlang/g0201_0300/s0221_maximal_square/readme.md @@ -0,0 +1,34 @@ +221\. Maximal Square + +Medium + +Given an `m x n` binary `matrix` filled with `0`'s and `1`'s, _find the largest square containing only_ `1`'s _and return its area_. + +**Example 1:** + +![](https://assets.leetcode.com/uploads/2020/11/26/max1grid.jpg) + +**Input:** matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]] + +**Output:** 4 + +**Example 2:** + +![](https://assets.leetcode.com/uploads/2020/11/26/max2grid.jpg) + +**Input:** matrix = [["0","1"],["1","0"]] + +**Output:** 1 + +**Example 3:** + +**Input:** matrix = [["0"]] + +**Output:** 0 + +**Constraints:** + +* `m == matrix.length` +* `n == matrix[i].length` +* `1 <= m, n <= 300` +* `matrix[i][j]` is `'0'` or `'1'`. diff --git a/src/main/erlang/g0201_0300/s0226_invert_binary_tree/Solution.erl b/src/main/erlang/g0201_0300/s0226_invert_binary_tree/Solution.erl new file mode 100644 index 0000000..0d7e407 --- /dev/null +++ b/src/main/erlang/g0201_0300/s0226_invert_binary_tree/Solution.erl @@ -0,0 +1,15 @@ +% #Easy #Top_100_Liked_Questions #Depth_First_Search #Breadth_First_Search #Tree #Binary_Tree +% #Data_Structure_I_Day_12_Tree #Level_2_Day_6_Tree #Udemy_Tree_Stack_Queue +% #Big_O_Time_O(n)_Space_O(n) #2025_01_19_Time_0_(100.00%)_Space_62.15_(100.00%) + +%% Definition for a binary tree node. +%% +%% -record(tree_node, {val = 0 :: integer(), +%% left = null :: 'null' | #tree_node{}, +%% right = null :: 'null' | #tree_node{}}). + +-spec invert_tree(Root :: #tree_node{} | null) -> #tree_node{} | null. +invert_tree(null) -> + null; +invert_tree(#tree_node{left=Left, right=Right}= Cat)-> + Cat#tree_node{left=invert_tree(Right), right=invert_tree(Left)}. diff --git a/src/main/erlang/g0201_0300/s0226_invert_binary_tree/readme.md b/src/main/erlang/g0201_0300/s0226_invert_binary_tree/readme.md new file mode 100644 index 0000000..40ccaaa --- /dev/null +++ b/src/main/erlang/g0201_0300/s0226_invert_binary_tree/readme.md @@ -0,0 +1,32 @@ +226\. Invert Binary Tree + +Easy + +Given the `root` of a binary tree, invert the tree, and return _its root_. + +**Example 1:** + +![](https://assets.leetcode.com/uploads/2021/03/14/invert1-tree.jpg) + +**Input:** root = [4,2,7,1,3,6,9] + +**Output:** [4,7,2,9,6,3,1] + +**Example 2:** + +![](https://assets.leetcode.com/uploads/2021/03/14/invert2-tree.jpg) + +**Input:** root = [2,1,3] + +**Output:** [2,3,1] + +**Example 3:** + +**Input:** root = [] + +**Output:** [] + +**Constraints:** + +* The number of nodes in the tree is in the range `[0, 100]`. +* `-100 <= Node.val <= 100` diff --git a/src/main/erlang/g0201_0300/s0230_kth_smallest_element_in_a_bst/Solution.erl b/src/main/erlang/g0201_0300/s0230_kth_smallest_element_in_a_bst/Solution.erl new file mode 100644 index 0000000..2e096ca --- /dev/null +++ b/src/main/erlang/g0201_0300/s0230_kth_smallest_element_in_a_bst/Solution.erl @@ -0,0 +1,42 @@ +% #Medium #Top_100_Liked_Questions #Depth_First_Search #Tree #Binary_Tree #Binary_Search_Tree +% #Data_Structure_II_Day_17_Tree #Level_2_Day_9_Binary_Search_Tree #Big_O_Time_O(n)_Space_O(n) +% #2025_01_19_Time_0_(100.00%)_Space_76.55_(100.00%) + +%% Definition for a binary tree node. +%% +%% -record(tree_node, {val = 0 :: integer(), +%% left = null :: 'null' | #tree_node{}, +%% right = null :: 'null' | #tree_node{}}). + +% Main function to find kth smallest element +-spec kth_smallest(Root :: #tree_node{} | null, K :: integer()) -> integer(). +kth_smallest(Root, K) -> + {_, Value} = find_kth_smallest(Root, K, 0), + Value. + +% Helper function to traverse the tree and find kth smallest +-spec find_kth_smallest(Node :: #tree_node{} | null, K :: integer(), Count :: integer()) -> + {integer(), integer() | null}. +find_kth_smallest(null, _, Count) -> + {Count, null}; +find_kth_smallest(Node, K, Count) -> + % Search left subtree + {NewCount, LeftValue} = find_kth_smallest(Node#tree_node.left, K, Count), + + % If we found the value in left subtree, return it + case LeftValue of + null -> + % Increment count for current node + CurrentCount = NewCount + 1, + + % Check if current node is the kth smallest + case CurrentCount =:= K of + true -> + {CurrentCount, Node#tree_node.val}; + false -> + % Search right subtree + find_kth_smallest(Node#tree_node.right, K, CurrentCount) + end; + _ -> + {NewCount, LeftValue} + end. diff --git a/src/main/erlang/g0201_0300/s0230_kth_smallest_element_in_a_bst/readme.md b/src/main/erlang/g0201_0300/s0230_kth_smallest_element_in_a_bst/readme.md new file mode 100644 index 0000000..21be903 --- /dev/null +++ b/src/main/erlang/g0201_0300/s0230_kth_smallest_element_in_a_bst/readme.md @@ -0,0 +1,29 @@ +230\. Kth Smallest Element in a BST + +Medium + +Given the `root` of a binary search tree, and an integer `k`, return _the_ kth _smallest value (**1-indexed**) of all the values of the nodes in the tree_. + +**Example 1:** + +![](https://assets.leetcode.com/uploads/2021/01/28/kthtree1.jpg) + +**Input:** root = [3,1,4,null,2], k = 1 + +**Output:** 1 + +**Example 2:** + +![](https://assets.leetcode.com/uploads/2021/01/28/kthtree2.jpg) + +**Input:** root = [5,3,6,2,4,null,null,1], k = 3 + +**Output:** 3 + +**Constraints:** + +* The number of nodes in the tree is `n`. +* 1 <= k <= n <= 104 +* 0 <= Node.val <= 104 + +**Follow up:** If the BST is modified often (i.e., we can do insert and delete operations) and you need to find the kth smallest frequently, how would you optimize? diff --git a/src/main/erlang/g0201_0300/s0234_palindrome_linked_list/Solution.erl b/src/main/erlang/g0201_0300/s0234_palindrome_linked_list/Solution.erl new file mode 100644 index 0000000..d3f693f --- /dev/null +++ b/src/main/erlang/g0201_0300/s0234_palindrome_linked_list/Solution.erl @@ -0,0 +1,20 @@ +% #Easy #Top_100_Liked_Questions #Two_Pointers #Stack #Linked_List #Recursion +% #Level_2_Day_3_Linked_List #Udemy_Linked_List #Big_O_Time_O(n)_Space_O(1) +% #2025_01_19_Time_25_(100.00%)_Space_109.06_(100.00%) + +%% Definition for singly-linked list. +%% +%% -record(list_node, {val = 0 :: integer(), +%% next = null :: 'null' | #list_node{}}). + +-spec is_palindrome(Head :: #list_node{} | null) -> boolean(). +-import(lists,[reverse/1]). + +list_to_seq(null) -> []; +list_to_seq(Head) -> + [Head#list_node.val] ++ list_to_seq(Head#list_node.next). + +is_palindrome(null) -> false; +is_palindrome(Head) -> + Seq = list_to_seq(Head), + Seq =:= reverse(Seq). diff --git a/src/main/erlang/g0201_0300/s0234_palindrome_linked_list/readme.md b/src/main/erlang/g0201_0300/s0234_palindrome_linked_list/readme.md new file mode 100644 index 0000000..9ee1dce --- /dev/null +++ b/src/main/erlang/g0201_0300/s0234_palindrome_linked_list/readme.md @@ -0,0 +1,28 @@ +234\. Palindrome Linked List + +Easy + +Given the `head` of a singly linked list, return `true` _if it is a palindrome or_ `false` _otherwise_. + +**Example 1:** + +![](https://assets.leetcode.com/uploads/2021/03/03/pal1linked-list.jpg) + +**Input:** head = [1,2,2,1] + +**Output:** true + +**Example 2:** + +![](https://assets.leetcode.com/uploads/2021/03/03/pal2linked-list.jpg) + +**Input:** head = [1,2] + +**Output:** false + +**Constraints:** + +* The number of nodes in the list is in the range [1, 105]. +* `0 <= Node.val <= 9` + +**Follow up:** Could you do it in `O(n)` time and `O(1)` space? diff --git a/src/main/erlang/g0201_0300/s0238_product_of_array_except_self/Solution.erl b/src/main/erlang/g0201_0300/s0238_product_of_array_except_self/Solution.erl new file mode 100644 index 0000000..f04e382 --- /dev/null +++ b/src/main/erlang/g0201_0300/s0238_product_of_array_except_self/Solution.erl @@ -0,0 +1,17 @@ +% #Medium #Top_100_Liked_Questions #Array #Prefix_Sum #Data_Structure_II_Day_5_Array #Udemy_Arrays +% #Big_O_Time_O(n^2)_Space_O(n) #2025_01_19_Time_22_(100.00%)_Space_112.22_(100.00%) + +-spec product_except_self(Nums :: [integer()]) -> [integer()]. +product_except_self(Nums) -> + Forwards = product(Nums, [], 1), + Backwards = lists:reverse(product(lists:reverse(Nums), [], 1)), + except_self([1|Forwards], Backwards ++ [1], []). + +product([], Res, _) -> lists:reverse(Res); +product([H|T], Res, Acc) -> + P = H * Acc, + product(T, [P|Res], P). + +except_self([_], [_], Res) -> lists:reverse(Res); +except_self([F|T1], [_, B|T2], Res) -> + except_self(T1, [B|T2], [F * B|Res]). diff --git a/src/main/erlang/g0201_0300/s0238_product_of_array_except_self/readme.md b/src/main/erlang/g0201_0300/s0238_product_of_array_except_self/readme.md new file mode 100644 index 0000000..48289c8 --- /dev/null +++ b/src/main/erlang/g0201_0300/s0238_product_of_array_except_self/readme.md @@ -0,0 +1,29 @@ +238\. Product of Array Except Self + +Medium + +Given an integer array `nums`, return _an array_ `answer` _such that_ `answer[i]` _is equal to the product of all the elements of_ `nums` _except_ `nums[i]`. + +The product of any prefix or suffix of `nums` is **guaranteed** to fit in a **32-bit** integer. + +You must write an algorithm that runs in `O(n)` time and without using the division operation. + +**Example 1:** + +**Input:** nums = [1,2,3,4] + +**Output:** [24,12,8,6] + +**Example 2:** + +**Input:** nums = [-1,1,0,-3,3] + +**Output:** [0,0,9,0,0] + +**Constraints:** + +* 2 <= nums.length <= 105 +* `-30 <= nums[i] <= 30` +* The product of any prefix or suffix of `nums` is **guaranteed** to fit in a **32-bit** integer. + +**Follow up:** Can you solve the problem in `O(1) `extra space complexity? (The output array **does not** count as extra space for space complexity analysis.) diff --git a/src/main/erlang/g0201_0300/s0239_sliding_window_maximum/Solution.erl b/src/main/erlang/g0201_0300/s0239_sliding_window_maximum/Solution.erl new file mode 100644 index 0000000..a50d7cd --- /dev/null +++ b/src/main/erlang/g0201_0300/s0239_sliding_window_maximum/Solution.erl @@ -0,0 +1,33 @@ +% #Hard #Top_100_Liked_Questions #Array #Heap_Priority_Queue #Sliding_Window #Queue +% #Monotonic_Queue #Udemy_Arrays #Big_O_Time_O(n*k)_Space_O(n+k) +% #2025_01_19_Time_422_(100.00%)_Space_151.54_(100.00%) + +-spec max_sliding_window(Nums :: [integer()], K :: integer()) -> [integer()]. +max_sliding_window(Nums, K) -> + {Results, _} = lists:mapfoldl( + fun({X, I}, Q) -> + Q2 = enqueue(Q, X, I), + get_max(Q2, I - K) + end, + queue:new(), + lists:zip(Nums, lists:seq(0, length(Nums)-1)) + ), + lists:nthtail(K-1, Results). + +-spec enqueue(queue:queue(), integer(), integer()) -> queue:queue(). +enqueue(Q, X, I) -> + case queue:peek_r(Q) of + {value, {Y, _}} when Y =< X -> + enqueue(queue:drop_r(Q), X, I); + _ -> + queue:in({X, I}, Q) + end. + +-spec get_max(queue:queue(), integer()) -> {integer(), queue:queue()}. +get_max(Q, DropUntil) -> + case queue:peek(Q) of + {value, {_, J}} when J =< DropUntil -> + get_max(queue:drop(Q), DropUntil); + {value, {Y, _}} -> + {Y, Q} + end. diff --git a/src/main/erlang/g0201_0300/s0239_sliding_window_maximum/readme.md b/src/main/erlang/g0201_0300/s0239_sliding_window_maximum/readme.md new file mode 100644 index 0000000..9e147a5 --- /dev/null +++ b/src/main/erlang/g0201_0300/s0239_sliding_window_maximum/readme.md @@ -0,0 +1,43 @@ +239\. Sliding Window Maximum + +Hard + +You are given an array of integers `nums`, there is a sliding window of size `k` which is moving from the very left of the array to the very right. You can only see the `k` numbers in the window. Each time the sliding window moves right by one position. + +Return _the max sliding window_. + +**Example 1:** + +**Input:** nums = [1,3,-1,-3,5,3,6,7], k = 3 + +**Output:** [3,3,5,5,6,7] + +**Explanation:** + +Window position Max + +--------------- ----- + +[1 3 -1] -3 5 3 6 7 **3** + +1 [3 -1 -3] 5 3 6 7 **3** + +1 3 [-1 -3 5] 3 6 7 **5** + +1 3 -1 [-3 5 3] 6 7 **5** + +1 3 -1 -3 [5 3 6] 7 **6** + +1 3 -1 -3 5 [3 6 7] **7** + +**Example 2:** + +**Input:** nums = [1], k = 1 + +**Output:** [1] + +**Constraints:** + +* 1 <= nums.length <= 105 +* -104 <= nums[i] <= 104 +* `1 <= k <= nums.length` diff --git a/src/main/erlang/g0201_0300/s0287_find_the_duplicate_number/Solution.erl b/src/main/erlang/g0201_0300/s0287_find_the_duplicate_number/Solution.erl new file mode 100644 index 0000000..c0ab09c --- /dev/null +++ b/src/main/erlang/g0201_0300/s0287_find_the_duplicate_number/Solution.erl @@ -0,0 +1,8 @@ +% #Medium #Top_100_Liked_Questions #Array #Binary_Search #Two_Pointers #Bit_Manipulation +% #Binary_Search_II_Day_5 #Big_O_Time_O(n)_Space_O(n) +% #2025_01_19_Time_234_(100.00%)_Space_156.27_(100.00%) + +-spec find_duplicate(Nums :: [integer()]) -> integer(). +find_duplicate(Nums) -> + [Head | _] = lists:subtract(Nums, lists:usort(Nums)), + Head. diff --git a/src/main/erlang/g0201_0300/s0287_find_the_duplicate_number/readme.md b/src/main/erlang/g0201_0300/s0287_find_the_duplicate_number/readme.md new file mode 100644 index 0000000..b2a7021 --- /dev/null +++ b/src/main/erlang/g0201_0300/s0287_find_the_duplicate_number/readme.md @@ -0,0 +1,33 @@ +287\. Find the Duplicate Number + +Medium + +Given an array of integers `nums` containing `n + 1` integers where each integer is in the range `[1, n]` inclusive. + +There is only **one repeated number** in `nums`, return _this repeated number_. + +You must solve the problem **without** modifying the array `nums` and uses only constant extra space. + +**Example 1:** + +**Input:** nums = [1,3,4,2,2] + +**Output:** 2 + +**Example 2:** + +**Input:** nums = [3,1,3,4,2] + +**Output:** 3 + +**Constraints:** + +* 1 <= n <= 105 +* `nums.length == n + 1` +* `1 <= nums[i] <= n` +* All the integers in `nums` appear only **once** except for **precisely one integer** which appears **two or more** times. + +**Follow up:** + +* How can we prove that at least one duplicate number must exist in `nums`? +* Can you solve the problem in linear runtime complexity? diff --git a/src/main/erlang/g0201_0300/s0300_longest_increasing_subsequence/Solution.erl b/src/main/erlang/g0201_0300/s0300_longest_increasing_subsequence/Solution.erl new file mode 100644 index 0000000..4f85694 --- /dev/null +++ b/src/main/erlang/g0201_0300/s0300_longest_increasing_subsequence/Solution.erl @@ -0,0 +1,29 @@ +% #Medium #Top_100_Liked_Questions #Array #Dynamic_Programming #Binary_Search +% #Algorithm_II_Day_16_Dynamic_Programming #Binary_Search_II_Day_3 #Dynamic_Programming_I_Day_18 +% #Udemy_Dynamic_Programming #Big_O_Time_O(n*log_n)_Space_O(n) +% #2025_01_20_Time_954_(100.00%)_Space_64.54_(100.00%) + +-spec length_of_lis(Nums :: [integer()]) -> integer(). +length_of_lis(Nums) -> + Pred = fun(V, Index) -> { {Index, V}, Index + 1} end, + {IVals, _} = lists:mapfoldl(Pred, 0, Nums), + [H|T] = IVals, + Tid = ets:new(lis, []), + length_of_lis([], T, H, Tid, 0). + +length_of_lis(Before, [], {_, Val}, Tid, Max) -> + max(lis(Before, Val, Tid) + 1, Max); +length_of_lis(Before, [Next|After], Current={Index, Val}, Tid, Max) -> + Lis = lis(Before, Val, Tid) + 1, + ets:insert(Tid, {Index, Lis}), + length_of_lis([Current|Before], After, Next, Tid, max(Max, Lis)). + +lis([], _, _) -> 0; +lis(L, N, Tid) -> + Opts = lists:filter(fun({I, V}) -> V < N end, L), + Pred = fun({I, _}) -> ets:lookup_element(Tid, I, 2) end, + case Opts of + [] -> 0; + _ -> + lists:max(lists:map(Pred, Opts)) + end. diff --git a/src/main/erlang/g0201_0300/s0300_longest_increasing_subsequence/readme.md b/src/main/erlang/g0201_0300/s0300_longest_increasing_subsequence/readme.md new file mode 100644 index 0000000..e37cf43 --- /dev/null +++ b/src/main/erlang/g0201_0300/s0300_longest_increasing_subsequence/readme.md @@ -0,0 +1,34 @@ +300\. Longest Increasing Subsequence + +Medium + +Given an integer array `nums`, return the length of the longest strictly increasing subsequence. + +A **subsequence** is a sequence that can be derived from an array by deleting some or no elements without changing the order of the remaining elements. For example, `[3,6,2,7]` is a subsequence of the array `[0,3,1,6,2,2,7]`. + +**Example 1:** + +**Input:** nums = [10,9,2,5,3,7,101,18] + +**Output:** 4 + +**Explanation:** The longest increasing subsequence is [2,3,7,101], therefore the length is 4. + +**Example 2:** + +**Input:** nums = [0,1,0,3,2,3] + +**Output:** 4 + +**Example 3:** + +**Input:** nums = [7,7,7,7,7,7,7] + +**Output:** 1 + +**Constraints:** + +* `1 <= nums.length <= 2500` +* -104 <= nums[i] <= 104 + +**Follow up:** Can you come up with an algorithm that runs in `O(n log(n))` time complexity? diff --git a/src/main/erlang/g0301_0400/s0322_coin_change/Solution.erl b/src/main/erlang/g0301_0400/s0322_coin_change/Solution.erl new file mode 100644 index 0000000..7f7d756 --- /dev/null +++ b/src/main/erlang/g0301_0400/s0322_coin_change/Solution.erl @@ -0,0 +1,53 @@ +% #Medium #Top_100_Liked_Questions #Array #Dynamic_Programming #Breadth_First_Search +% #Algorithm_II_Day_18_Dynamic_Programming #Dynamic_Programming_I_Day_20 +% #Level_2_Day_12_Dynamic_Programming #Big_O_Time_O(m*n)_Space_O(amount) +% #2025_01_20_Time_797_(100.00%)_Space_66.72_(100.00%) + +-spec coin_change(Coins :: [integer()], Amount :: integer()) -> integer(). +coin_change(Coins, Amount) -> + % Sort coins in ascending order + SortedCoins = lists:sort(Coins), + + % Initialize DP map with base case + InitDP = #{0 => 0}, + + % Build DP table for amounts from 1 to target + case Amount of + 0 -> 0; + _ -> + FinalDP = build_dp_table(SortedCoins, lists:seq(1, Amount), InitDP), + % Get result or return -1 if not possible + maps:get(Amount, FinalDP, -1) + end. + +% Build DP table for all amounts +-spec build_dp_table([integer()], [integer()], map()) -> map(). +build_dp_table(_Coins, [], DP) -> DP; +build_dp_table(Coins, [Amount|Rest], DP) -> + NewDP = process_coins_for_amount(Coins, Amount, DP), + build_dp_table(Coins, Rest, NewDP). + +% Process all coins for current amount +-spec process_coins_for_amount([integer()], integer(), map()) -> map(). +process_coins_for_amount([], _Amount, DP) -> DP; +process_coins_for_amount([Coin|Rest], Amount, DP) -> + case Coin > Amount of + true -> + % Stop if coin is larger than current amount + DP; + false -> + % Try using current coin + case maps:get(Amount - Coin, DP, undefined) of + undefined -> + % Can't use this coin, try next + process_coins_for_amount(Rest, Amount, DP); + PrevCount -> + % Can use this coin, update minimum coins needed + NewCount = PrevCount + 1, + NewDP = maps:update_with(Amount, + fun(OldVal) -> min(OldVal, NewCount) end, + NewCount, + DP), + process_coins_for_amount(Rest, Amount, NewDP) + end + end. diff --git a/src/main/erlang/g0301_0400/s0322_coin_change/readme.md b/src/main/erlang/g0301_0400/s0322_coin_change/readme.md new file mode 100644 index 0000000..07bc715 --- /dev/null +++ b/src/main/erlang/g0301_0400/s0322_coin_change/readme.md @@ -0,0 +1,35 @@ +322\. Coin Change + +Medium + +You are given an integer array `coins` representing coins of different denominations and an integer `amount` representing a total amount of money. + +Return _the fewest number of coins that you need to make up that amount_. If that amount of money cannot be made up by any combination of the coins, return `-1`. + +You may assume that you have an infinite number of each kind of coin. + +**Example 1:** + +**Input:** coins = [1,2,5], amount = 11 + +**Output:** 3 + +**Explanation:** 11 = 5 + 5 + 1 + +**Example 2:** + +**Input:** coins = [2], amount = 3 + +**Output:** -1 + +**Example 3:** + +**Input:** coins = [1], amount = 0 + +**Output:** 0 + +**Constraints:** + +* `1 <= coins.length <= 12` +* 1 <= coins[i] <= 231 - 1 +* 0 <= amount <= 104 diff --git a/src/main/erlang/g0301_0400/s0338_counting_bits/Solution.erl b/src/main/erlang/g0301_0400/s0338_counting_bits/Solution.erl new file mode 100644 index 0000000..d94b191 --- /dev/null +++ b/src/main/erlang/g0301_0400/s0338_counting_bits/Solution.erl @@ -0,0 +1,17 @@ +% #Easy #Dynamic_Programming #Bit_Manipulation #Udemy_Bit_Manipulation +% #Big_O_Time_O(num)_Space_O(num) #2025_01_20_Time_38_(100.00%)_Space_77.22_(100.00%) + +-spec count_bits(N :: integer()) -> [integer()]. +count_bits(N) -> + InitMap = maps:from_list([{X, 0} || X <- lists:seq(0, N div 2)]), + lists:reverse(do_count_bits(1, N, InitMap, [0])). + +do_count_bits(I, N, _Map, Acc) when I > N -> + Acc; +do_count_bits(I, N, Map, Acc) -> + IBits = maps:get(I div 2, Map) + (I rem 2), + NewMap = case I > (N div 2) of + true -> Map; + false -> maps:put(I, IBits, Map) + end, + do_count_bits(I + 1, N, NewMap, [IBits | Acc]). diff --git a/src/main/erlang/g0301_0400/s0338_counting_bits/readme.md b/src/main/erlang/g0301_0400/s0338_counting_bits/readme.md new file mode 100644 index 0000000..2cf9a11 --- /dev/null +++ b/src/main/erlang/g0301_0400/s0338_counting_bits/readme.md @@ -0,0 +1,41 @@ +338\. Counting Bits + +Easy + +Given an integer `n`, return _an array_ `ans` _of length_ `n + 1` _such that for each_ `i` (`0 <= i <= n`)_,_ `ans[i]` _is the **number of**_ `1`_**'s** in the binary representation of_ `i`. + +**Example 1:** + +**Input:** n = 2 + +**Output:** [0,1,1] + +**Explanation:** + + 0 --> 0 + 1 --> 1 + 2 --> 10 + +**Example 2:** + +**Input:** n = 5 + +**Output:** [0,1,1,2,1,2] + +**Explanation:** + + 0 --> 0 + 1 --> 1 + 2 --> 10 + 3 --> 11 + 4 --> 100 + 5 --> 101 + +**Constraints:** + +* 0 <= n <= 105 + +**Follow up:** + +* It is very easy to come up with a solution with a runtime of `O(n log n)`. Can you do it in linear time `O(n)` and possibly in a single pass? +* Can you do it without using any built-in function (i.e., like `__builtin_popcount` in C++)? diff --git a/src/main/erlang/g0301_0400/s0347_top_k_frequent_elements/Solution.erl b/src/main/erlang/g0301_0400/s0347_top_k_frequent_elements/Solution.erl new file mode 100644 index 0000000..4abea4d --- /dev/null +++ b/src/main/erlang/g0301_0400/s0347_top_k_frequent_elements/Solution.erl @@ -0,0 +1,25 @@ +% #Medium #Top_100_Liked_Questions #Array #Hash_Table #Sorting #Heap_Priority_Queue #Counting +% #Divide_and_Conquer #Quickselect #Bucket_Sort #Data_Structure_II_Day_20_Heap_Priority_Queue +% #Big_O_Time_O(n*log(n))_Space_O(k) #2025_01_20_Time_12_(100.00%)_Space_80.46_(100.00%) + +-spec top_k_frequent(Nums :: [integer()], K :: integer()) -> [integer()]. +top_k_frequent(Nums, K) -> + % Count frequencies using a map + FreqMap = lists:foldl( + fun(N, Map) -> + maps:update_with(N, fun(V) -> V + 1 end, 1, Map) + end, + #{}, + Nums + ), + + % Convert map to list, sort by frequency (descending), take K elements + FreqList = maps:to_list(FreqMap), + SortedList = lists:sort( + fun({_, Count1}, {_, Count2}) -> Count1 > Count2 end, + FreqList + ), + TopK = lists:sublist(SortedList, K), + + % Extract only the numbers from the result + [Num || {Num, _Count} <- TopK]. diff --git a/src/main/erlang/g0301_0400/s0347_top_k_frequent_elements/readme.md b/src/main/erlang/g0301_0400/s0347_top_k_frequent_elements/readme.md new file mode 100644 index 0000000..1654ce1 --- /dev/null +++ b/src/main/erlang/g0301_0400/s0347_top_k_frequent_elements/readme.md @@ -0,0 +1,26 @@ +347\. Top K Frequent Elements + +Medium + +Given an integer array `nums` and an integer `k`, return _the_ `k` _most frequent elements_. You may return the answer in **any order**. + +**Example 1:** + +**Input:** nums = [1,1,1,2,2,3], k = 2 + +**Output:** [1,2] + +**Example 2:** + +**Input:** nums = [1], k = 1 + +**Output:** [1] + +**Constraints:** + +* 1 <= nums.length <= 105 +* -104 <= nums[i] <= 104 +* `k` is in the range `[1, the number of unique elements in the array]`. +* It is **guaranteed** that the answer is **unique**. + +**Follow up:** Your algorithm's time complexity must be better than `O(n log n)`, where n is the array's size. diff --git a/src/main/erlang/g0301_0400/s0394_decode_string/Solution.erl b/src/main/erlang/g0301_0400/s0394_decode_string/Solution.erl new file mode 100644 index 0000000..133e3e9 --- /dev/null +++ b/src/main/erlang/g0301_0400/s0394_decode_string/Solution.erl @@ -0,0 +1,58 @@ +% #Medium #Top_100_Liked_Questions #String #Stack #Recursion #Level_1_Day_14_Stack #Udemy_Strings +% #Big_O_Time_O(n)_Space_O(n) #2025_01_20_Time_0_(100.00%)_Space_58.58_(100.00%) + +-spec decode_string(S :: unicode:unicode_binary()) -> unicode:unicode_binary(). +decode_string(S) -> + decode_helper(S, 1). + +decode_helper(S, I) when I > byte_size(S) -> + <<>>; +decode_helper(S, I) -> + decode_helper(S, I, 0, <<>>). + +decode_helper(S, I, _Count, Acc) when I > byte_size(S) -> + Acc; +decode_helper(S, I, Count, Acc) -> + case binary:at(S, I-1) of + C when C >= $a, C =< $z; C >= $A, C =< $Z -> + decode_helper(S, I+1, Count, <>); + C when C >= $0, C =< $9 -> + NewCount = Count * 10 + (C - $0), + decode_helper(S, I+1, NewCount, Acc); + $[ -> + {Repeated, NextI} = decode_bracket(S, I+1), + RepeatedStr = repeat_string(Repeated, Count), + decode_helper(S, NextI, 0, <>); + _ -> + decode_helper(S, I+1, Count, Acc) + end. + +decode_bracket(S, I) -> + decode_bracket(S, I, 0, <<>>). + +decode_bracket(S, I, Count, Acc) when I > byte_size(S) -> + {Acc, I}; +decode_bracket(S, I, Count, Acc) -> + case binary:at(S, I-1) of + C when C >= $a, C =< $z; C >= $A, C =< $Z -> + decode_bracket(S, I+1, Count, <>); + C when C >= $0, C =< $9 -> + NewCount = Count * 10 + (C - $0), + decode_bracket(S, I+1, NewCount, Acc); + $[ -> + {Repeated, NextI} = decode_bracket(S, I+1), + RepeatedStr = repeat_string(Repeated, Count), + decode_bracket(S, NextI, 0, <>); + $] -> + {Acc, I+1}; + _ -> + decode_bracket(S, I+1, Count, Acc) + end. + +repeat_string(Str, Count) -> + repeat_string(Str, Count, <<>>). + +repeat_string(_, 0, Acc) -> + Acc; +repeat_string(Str, Count, Acc) -> + repeat_string(Str, Count-1, <>). diff --git a/src/main/erlang/g0301_0400/s0394_decode_string/readme.md b/src/main/erlang/g0301_0400/s0394_decode_string/readme.md new file mode 100644 index 0000000..83448e5 --- /dev/null +++ b/src/main/erlang/g0301_0400/s0394_decode_string/readme.md @@ -0,0 +1,36 @@ +394\. Decode String + +Medium + +Given an encoded string, return its decoded string. + +The encoding rule is: `k[encoded_string]`, where the `encoded_string` inside the square brackets is being repeated exactly `k` times. Note that `k` is guaranteed to be a positive integer. + +You may assume that the input string is always valid; there are no extra white spaces, square brackets are well-formed, etc. Furthermore, you may assume that the original data does not contain any digits and that digits are only for those repeat numbers, `k`. For example, there will not be input like `3a` or `2[4]`. + +The test cases are generated so that the length of the output will never exceed 105. + +**Example 1:** + +**Input:** s = "3[a]2[bc]" + +**Output:** "aaabcbc" + +**Example 2:** + +**Input:** s = "3[a2[c]]" + +**Output:** "accaccacc" + +**Example 3:** + +**Input:** s = "2[abc]3[cd]ef" + +**Output:** "abcabccdcdcdef" + +**Constraints:** + +* `1 <= s.length <= 30` +* `s` consists of lowercase English letters, digits, and square brackets `'[]'`. +* `s` is guaranteed to be **a valid** input. +* All the integers in `s` are in the range `[1, 300]`. diff --git a/src/main/erlang/g0401_0500/s0416_partition_equal_subset_sum/Solution.erl b/src/main/erlang/g0401_0500/s0416_partition_equal_subset_sum/Solution.erl new file mode 100644 index 0000000..f536ea2 --- /dev/null +++ b/src/main/erlang/g0401_0500/s0416_partition_equal_subset_sum/Solution.erl @@ -0,0 +1,28 @@ +% #Medium #Top_100_Liked_Questions #Array #Dynamic_Programming #Level_2_Day_13_Dynamic_Programming +% #Big_O_Time_O(n*sums)_Space_O(n*sums) #2025_01_22_Time_585_(100.00%)_Space_63.47_(100.00%) + +-spec can_partition(Nums :: [integer()]) -> boolean(). +can_partition(Nums) -> + Sum = lists:sum(Nums), + case Sum rem 2 of + 0 -> + Target = Sum div 2, + Dp = lists:foldl( + fun(Num, Acc) -> + maps:fold( + fun(Sum0, true, InnerAcc) -> + case Sum0 + Num =< Target of + true -> InnerAcc#{Sum0 + Num => true}; + false -> InnerAcc + end; + (_, false, InnerAcc) -> InnerAcc + end, + Acc#{Num => true}, + Acc) + end, + #{0 => true}, + Nums), + maps:get(Target, Dp, false); + _ -> + false + end. diff --git a/src/main/erlang/g0401_0500/s0416_partition_equal_subset_sum/readme.md b/src/main/erlang/g0401_0500/s0416_partition_equal_subset_sum/readme.md new file mode 100644 index 0000000..6e0d55a --- /dev/null +++ b/src/main/erlang/g0401_0500/s0416_partition_equal_subset_sum/readme.md @@ -0,0 +1,26 @@ +416\. Partition Equal Subset Sum + +Medium + +Given a **non-empty** array `nums` containing **only positive integers**, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal. + +**Example 1:** + +**Input:** nums = [1,5,11,5] + +**Output:** true + +**Explanation:** The array can be partitioned as [1, 5, 5] and [11]. + +**Example 2:** + +**Input:** nums = [1,2,3,5] + +**Output:** false + +**Explanation:** The array cannot be partitioned into equal sum subsets. + +**Constraints:** + +* `1 <= nums.length <= 200` +* `1 <= nums[i] <= 100` diff --git a/src/main/erlang/g0401_0500/s0437_path_sum_iii/Solution.erl b/src/main/erlang/g0401_0500/s0437_path_sum_iii/Solution.erl new file mode 100644 index 0000000..8ff5ce5 --- /dev/null +++ b/src/main/erlang/g0401_0500/s0437_path_sum_iii/Solution.erl @@ -0,0 +1,21 @@ +% #Medium #Depth_First_Search #Tree #Binary_Tree #Level_2_Day_7_Tree #Big_O_Time_O(n)_Space_O(n) +% #2025_01_22_Time_45_(100.00%)_Space_104.65_(100.00%) + +%% Definition for a binary tree node. +%% +%% -record(tree_node, {val = 0 :: integer(), +%% left = null :: 'null' | #tree_node{}, +%% right = null :: 'null' | #tree_node{}}). + +-spec path_sum(Root :: #tree_node{} | null, TargetSum :: integer()) -> integer(). +path_sum(null, _TargetSum) -> 0; +path_sum(Root, TargetSum) -> + path_sum(Root, TargetSum, []). + +path_sum(null, _TargetSum, _PartialSums) -> 0; +path_sum(Root, TargetSum, PartialSums) -> + NewPartials = [Root#tree_node.val | [Sum + Root#tree_node.val || Sum <- PartialSums]], + EqualPaths = length([Sum || Sum <- NewPartials, Sum =:= TargetSum]), + EqualPaths + + path_sum(Root#tree_node.left, TargetSum, NewPartials) + + path_sum(Root#tree_node.right, TargetSum, NewPartials). diff --git a/src/main/erlang/g0401_0500/s0437_path_sum_iii/readme.md b/src/main/erlang/g0401_0500/s0437_path_sum_iii/readme.md new file mode 100644 index 0000000..2943bf0 --- /dev/null +++ b/src/main/erlang/g0401_0500/s0437_path_sum_iii/readme.md @@ -0,0 +1,29 @@ +437\. Path Sum III + +Medium + +Given the `root` of a binary tree and an integer `targetSum`, return _the number of paths where the sum of the values along the path equals_ `targetSum`. + +The path does not need to start or end at the root or a leaf, but it must go downwards (i.e., traveling only from parent nodes to child nodes). + +**Example 1:** + +![](https://assets.leetcode.com/uploads/2021/04/09/pathsum3-1-tree.jpg) + +**Input:** root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8 + +**Output:** 3 + +**Explanation:** The paths that sum to 8 are shown. + +**Example 2:** + +**Input:** root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22 + +**Output:** 3 + +**Constraints:** + +* The number of nodes in the tree is in the range `[0, 1000]`. +* -109 <= Node.val <= 109 +* `-1000 <= targetSum <= 1000` diff --git a/src/main/erlang/g0401_0500/s0438_find_all_anagrams_in_a_string/Solution.erl b/src/main/erlang/g0401_0500/s0438_find_all_anagrams_in_a_string/Solution.erl new file mode 100644 index 0000000..03ea9b2 --- /dev/null +++ b/src/main/erlang/g0401_0500/s0438_find_all_anagrams_in_a_string/Solution.erl @@ -0,0 +1,47 @@ +% #Medium #Top_100_Liked_Questions #String #Hash_Table #Sliding_Window +% #Algorithm_II_Day_5_Sliding_Window #Programming_Skills_II_Day_12 +% #Level_1_Day_12_Sliding_Window/Two_Pointer #Big_O_Time_O(n+m)_Space_O(1) +% #2025_01_22_Time_43_(100.00%)_Space_63.56_(100.00%) + +-spec find_anagrams(S :: unicode:unicode_binary(), P :: unicode:unicode_binary()) -> [integer()]. +find_anagrams(S, P) -> + PLen = byte_size(P), + SLen = byte_size(S), + case PLen =< SLen of + true -> + Map = init_freq_map(P), + Window = init_freq_map(binary_part(S, 0, PLen)), + check_windows(S, PLen, Map, Window, 0, []); + false -> + [] + end. + +init_freq_map(Bin) -> + lists:foldl( + fun(C, Acc) -> + maps:put(C - $a, maps:get(C - $a, Acc, 0) + 1, Acc) + end, + maps:new(), + binary_to_list(Bin) + ). + +check_windows(S, PLen, Map, Window, I, Result) when I =< byte_size(S) - PLen -> + NewResult = case maps:to_list(Window) =:= maps:to_list(Map) of + true -> [I | Result]; + false -> Result + end, + case I + PLen of + SLen when SLen >= byte_size(S) -> + lists:reverse(NewResult); + Next -> + RemoveChar = binary:at(S, I) - $a, + AddChar = binary:at(S, Next) - $a, + NewWindow1 = case maps:get(RemoveChar, Window) of + 1 -> maps:remove(RemoveChar, Window); + N -> maps:put(RemoveChar, N - 1, Window) + end, + NewWindow2 = maps:put(AddChar, maps:get(AddChar, NewWindow1, 0) + 1, NewWindow1), + check_windows(S, PLen, Map, NewWindow2, I + 1, NewResult) + end; +check_windows(_, _, _, _, _, Result) -> + lists:reverse(Result). diff --git a/src/main/erlang/g0401_0500/s0438_find_all_anagrams_in_a_string/readme.md b/src/main/erlang/g0401_0500/s0438_find_all_anagrams_in_a_string/readme.md new file mode 100644 index 0000000..3000942 --- /dev/null +++ b/src/main/erlang/g0401_0500/s0438_find_all_anagrams_in_a_string/readme.md @@ -0,0 +1,38 @@ +438\. Find All Anagrams in a String + +Medium + +Given two strings `s` and `p`, return _an array of all the start indices of_ `p`_'s anagrams in_ `s`. You may return the answer in **any order**. + +An **Anagram** is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once. + +**Example 1:** + +**Input:** s = "cbaebabacd", p = "abc" + +**Output:** [0,6] + +**Explanation:** + +The substring with start index = 0 is "cba", which is an anagram of "abc". + +The substring with start index = 6 is "bac", which is an anagram of "abc". + +**Example 2:** + +**Input:** s = "abab", p = "ab" + +**Output:** [0,1,2] + +**Explanation:** + +The substring with start index = 0 is "ab", which is an anagram of "ab". + +The substring with start index = 1 is "ba", which is an anagram of "ab". + +The substring with start index = 2 is "ab", which is an anagram of "ab". + +**Constraints:** + +* 1 <= s.length, p.length <= 3 * 104 +* `s` and `p` consist of lowercase English letters. diff --git a/src/main/erlang/g0401_0500/s0494_target_sum/Solution.erl b/src/main/erlang/g0401_0500/s0494_target_sum/Solution.erl new file mode 100644 index 0000000..a611b1c --- /dev/null +++ b/src/main/erlang/g0401_0500/s0494_target_sum/Solution.erl @@ -0,0 +1,36 @@ +% #Medium #Array #Dynamic_Programming #Backtracking #Big_O_Time_O(n*(sum+s))_Space_O(n*(sum+s)) +% #2025_01_22_Time_377_(100.00%)_Space_60.11_(100.00%) + +-spec find_target_sum_ways(Nums :: [integer()], Target :: integer()) -> integer(). +find_target_sum_ways(Nums, Target) -> + TotalSum = lists:sum(Nums), + Sum = TotalSum - Target, + case Sum < 0 orelse Sum rem 2 =:= 1 of + true -> 0; + false -> solve(Nums, Sum div 2) + end. + +-spec solve(Nums :: [integer()], Target :: integer()) -> integer(). +solve([First|_] = Nums, Target) -> + Prev = lists:duplicate(Target + 1, 0), + InitPrev = case First of + 0 -> lists:sublist([2|lists:duplicate(Target, 0)], Target + 1); + _ when First =< Target -> + lists:sublist([1] ++ lists:duplicate(First - 1, 0) ++ [1] ++ + lists:duplicate(Target - First, 0), Target + 1); + _ -> [1|lists:duplicate(Target, 0)] + end, + process_nums(tl(Nums), Target, InitPrev). + +process_nums([], _Target, Prev) -> + lists:last(Prev); +process_nums([Num|Rest], Target, Prev) -> + Curr = lists:foldl(fun(J, Acc) -> + Taken = case J >= Num of + true -> lists:nth(J - Num + 1, Prev); + false -> 0 + end, + NonTaken = lists:nth(J + 1, Prev), + Acc ++ [Taken + NonTaken] + end, [], lists:seq(0, Target)), + process_nums(Rest, Target, Curr). diff --git a/src/main/erlang/g0401_0500/s0494_target_sum/readme.md b/src/main/erlang/g0401_0500/s0494_target_sum/readme.md new file mode 100644 index 0000000..86fe038 --- /dev/null +++ b/src/main/erlang/g0401_0500/s0494_target_sum/readme.md @@ -0,0 +1,42 @@ +494\. Target Sum + +Medium + +You are given an integer array `nums` and an integer `target`. + +You want to build an **expression** out of nums by adding one of the symbols `'+'` and `'-'` before each integer in nums and then concatenate all the integers. + +* For example, if `nums = [2, 1]`, you can add a `'+'` before `2` and a `'-'` before `1` and concatenate them to build the expression `"+2-1"`. + +Return the number of different **expressions** that you can build, which evaluates to `target`. + +**Example 1:** + +**Input:** nums = [1,1,1,1,1], target = 3 + +**Output:** 5 + +**Explanation:** There are 5 ways to assign symbols to make the sum of nums be target 3. + +-1 + 1 + 1 + 1 + 1 = 3 + ++1 - 1 + 1 + 1 + 1 = 3 + ++1 + 1 - 1 + 1 + 1 = 3 + ++1 + 1 + 1 - 1 + 1 = 3 + + +1 + 1 + 1 + 1 - 1 = 3 + +**Example 2:** + +**Input:** nums = [1], target = 1 + +**Output:** 1 + +**Constraints:** + +* `1 <= nums.length <= 20` +* `0 <= nums[i] <= 1000` +* `0 <= sum(nums[i]) <= 1000` +* `-1000 <= target <= 1000` diff --git a/src/main/erlang/g0501_0600/s0543_diameter_of_binary_tree/Solution.erl b/src/main/erlang/g0501_0600/s0543_diameter_of_binary_tree/Solution.erl new file mode 100644 index 0000000..8803268 --- /dev/null +++ b/src/main/erlang/g0501_0600/s0543_diameter_of_binary_tree/Solution.erl @@ -0,0 +1,25 @@ +% #Easy #Top_100_Liked_Questions #Depth_First_Search #Tree #Binary_Tree #Level_2_Day_7_Tree +% #Udemy_Tree_Stack_Queue #Big_O_Time_O(n)_Space_O(n) +% #2025_01_22_Time_485_(100.00%)_Space_74.78_(100.00%) + +%% Definition for a binary tree node. +%% +%% -record(tree_node, {val = 0 :: integer(), +%% left = null :: 'null' | #tree_node{}, +%% right = null :: 'null' | #tree_node{}}). + +-spec diameter_of_binary_tree(Root :: #tree_node{} | null) -> integer(). + +depth(null) -> 0; +depth(Root) -> + 1 + max(depth(Root#tree_node.left), depth(Root#tree_node.right)). + +diameter_of_binary_tree(null) -> 0; +diameter_of_binary_tree(Root) -> + max( + max( + diameter_of_binary_tree(Root#tree_node.left), + diameter_of_binary_tree(Root#tree_node.right) + ), + depth(Root#tree_node.left) + depth(Root#tree_node.right) + ). diff --git a/src/main/erlang/g0501_0600/s0543_diameter_of_binary_tree/readme.md b/src/main/erlang/g0501_0600/s0543_diameter_of_binary_tree/readme.md new file mode 100644 index 0000000..dec390f --- /dev/null +++ b/src/main/erlang/g0501_0600/s0543_diameter_of_binary_tree/readme.md @@ -0,0 +1,30 @@ +543\. Diameter of Binary Tree + +Easy + +Given the `root` of a binary tree, return _the length of the **diameter** of the tree_. + +The **diameter** of a binary tree is the **length** of the longest path between any two nodes in a tree. This path may or may not pass through the `root`. + +The **length** of a path between two nodes is represented by the number of edges between them. + +**Example 1:** + +![](https://assets.leetcode.com/uploads/2021/03/06/diamtree.jpg) + +**Input:** root = [1,2,3,4,5] + +**Output:** 3 + +**Explanation:** 3 is the length of the path [4,2,1,3] or [5,2,1,3]. + +**Example 2:** + +**Input:** root = [1,2] + +**Output:** 1 + +**Constraints:** + +* The number of nodes in the tree is in the range [1, 104]. +* `-100 <= Node.val <= 100` diff --git a/src/main/erlang/g1101_1200/s1143_longest_common_subsequence/Solution.erl b/src/main/erlang/g1101_1200/s1143_longest_common_subsequence/Solution.erl new file mode 100644 index 0000000..21bab68 --- /dev/null +++ b/src/main/erlang/g1101_1200/s1143_longest_common_subsequence/Solution.erl @@ -0,0 +1,33 @@ +% #Medium #Top_100_Liked_Questions #String #Dynamic_Programming +% #Algorithm_II_Day_17_Dynamic_Programming #Dynamic_Programming_I_Day_19 +% #Udemy_Dynamic_Programming #Big_O_Time_O(n*m)_Space_O(n*m) +% #2025_01_22_Time_2600_(100.00%)_Space_412.75_(100.00%) + +-spec longest_common_subsequence(Text1 :: unicode:unicode_binary(), Text2 :: unicode:unicode_binary()) -> integer(). +longest_common_subsequence(Text1, Text2) -> + S1 = binary_to_list(Text1), + S2 = binary_to_list(Text2), + Key = {length(S1) - 1, length(S2) - 1}, + Memo = #{}, + maps:get(Key, recur(Memo, S1, S2, Key), 0). + +-spec recur(map(), list(), list(), {integer(), integer()}) -> map(). +recur(Memo, [], _, Key) -> + maps:put(Key, 0, Memo); +recur(Memo, _, [], Key) -> + maps:put(Key, 0, Memo); +recur(Memo, [X | Xs] = Xss, [Y | Ys] = Yss, {I, J} = Key) -> + case maps:is_key(Key, Memo) of + true -> + Memo; + false -> + if + X =:= Y -> + Memo1 = recur(Memo, Xs, Ys, {I - 1, J - 1}), + maps:put(Key, 1 + maps:get({I - 1, J - 1}, Memo1, 0), Memo1); + true -> + Memo1 = recur(Memo, Xss, Ys, {I, J - 1}), + Memo2 = recur(Memo1, Xs, Yss, {I - 1, J}), + maps:put(Key, max(maps:get({I, J - 1}, Memo2, 0), maps:get({I - 1, J}, Memo2, 0)), Memo2) + end + end. diff --git a/src/main/erlang/g1101_1200/s1143_longest_common_subsequence/readme.md b/src/main/erlang/g1101_1200/s1143_longest_common_subsequence/readme.md new file mode 100644 index 0000000..b6504b9 --- /dev/null +++ b/src/main/erlang/g1101_1200/s1143_longest_common_subsequence/readme.md @@ -0,0 +1,40 @@ +1143\. Longest Common Subsequence + +Medium + +Given two strings `text1` and `text2`, return _the length of their longest **common subsequence**._ If there is no **common subsequence**, return `0`. + +A **subsequence** of a string is a new string generated from the original string with some characters (can be none) deleted without changing the relative order of the remaining characters. + +* For example, `"ace"` is a subsequence of `"abcde"`. + +A **common subsequence** of two strings is a subsequence that is common to both strings. + +**Example 1:** + +**Input:** text1 = "abcde", text2 = "ace" + +**Output:** 3 + +**Explanation:** The longest common subsequence is "ace" and its length is 3. + +**Example 2:** + +**Input:** text1 = "abc", text2 = "abc" + +**Output:** 3 + +**Explanation:** The longest common subsequence is "abc" and its length is 3. + +**Example 3:** + +**Input:** text1 = "abc", text2 = "def" + +**Output:** 0 + +**Explanation:** There is no such common subsequence, so the result is 0. + +**Constraints:** + +* `1 <= text1.length, text2.length <= 1000` +* `text1` and `text2` consist of only lowercase English characters. \ No newline at end of file