From f4ac4335b61246204fdbc0e2929249cab8ba028b Mon Sep 17 00:00:00 2001 From: Dusuna <94776135+dusunax@users.noreply.github.com> Date: Wed, 4 Dec 2024 15:26:45 +0900 Subject: [PATCH 01/12] add solution: contains duplicate --- contains-duplicate/SunaDu.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 contains-duplicate/SunaDu.py diff --git a/contains-duplicate/SunaDu.py b/contains-duplicate/SunaDu.py new file mode 100644 index 000000000..7daa1e6c7 --- /dev/null +++ b/contains-duplicate/SunaDu.py @@ -0,0 +1,22 @@ +''' +# Leetcode 217. Contains Duplicate + +use set to store distinct elements 🗂️ + +## Time and Space Complexity + +``` +TC: O(n) +SC: O(n) +``` + +### TC is O(n): +- iterating through the list just once to convert it to a set. + +### SC is O(n): +- creating a set to store the distinct elements of the list. +''' + +class Solution: + def containsDuplicate(self, nums: List[int]) -> bool: + return len(nums) != len(set(nums)) From 227415b0d01287b5c4e9368cf85677ddc70696d6 Mon Sep 17 00:00:00 2001 From: Dusuna <94776135+dusunax@users.noreply.github.com> Date: Wed, 4 Dec 2024 15:34:22 +0900 Subject: [PATCH 02/12] fix: add new line for lint rules --- contains-duplicate/SunaDu.py | 1 + 1 file changed, 1 insertion(+) diff --git a/contains-duplicate/SunaDu.py b/contains-duplicate/SunaDu.py index 7daa1e6c7..fb9255c70 100644 --- a/contains-duplicate/SunaDu.py +++ b/contains-duplicate/SunaDu.py @@ -20,3 +20,4 @@ class Solution: def containsDuplicate(self, nums: List[int]) -> bool: return len(nums) != len(set(nums)) + From 75e6d4456ba0f40a287c395b704adfb0f7160b4d Mon Sep 17 00:00:00 2001 From: Dusuna <94776135+dusunax@users.noreply.github.com> Date: Wed, 4 Dec 2024 15:40:27 +0900 Subject: [PATCH 03/12] fix: change filename to GitHub username --- contains-duplicate/{SunaDu.py => dusunax.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename contains-duplicate/{SunaDu.py => dusunax.py} (100%) diff --git a/contains-duplicate/SunaDu.py b/contains-duplicate/dusunax.py similarity index 100% rename from contains-duplicate/SunaDu.py rename to contains-duplicate/dusunax.py From be09081902970ef30f0c73b60b83ca1c59536e71 Mon Sep 17 00:00:00 2001 From: Dusuna <94776135+dusunax@users.noreply.github.com> Date: Wed, 4 Dec 2024 22:53:52 +0900 Subject: [PATCH 04/12] add solution: valid-palindrome --- valid-palindrome/dusunax.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 valid-palindrome/dusunax.py diff --git a/valid-palindrome/dusunax.py b/valid-palindrome/dusunax.py new file mode 100644 index 000000000..2b21482f5 --- /dev/null +++ b/valid-palindrome/dusunax.py @@ -0,0 +1,28 @@ +''' +# Leetcode 125. Valid Palindrome + +use regex to filter out non-alphanumeric characters 🔍 + +## Time and Space Complexity + +``` +TC: O(n) +SC: O(n) +``` + +### TC is O(n): +- iterating through the string just once to filter out non-alphanumeric characters. + +### SC is O(n): +- creating a new string to store the filtered characters. +''' + +class Solution: + def isPalindrome(self, s: str) -> bool: + if s is " ": + return True + + reg = "[^a-z0-9]" + converted_s = re.sub(reg, "", s.lower()) + + return converted_s == converted_s[::-1] From 9a395e9cb8f4ccb48101b62d2cb2524f2c7cfbb4 Mon Sep 17 00:00:00 2001 From: Dusuna <94776135+dusunax@users.noreply.github.com> Date: Thu, 5 Dec 2024 01:48:10 +0900 Subject: [PATCH 05/12] add solution: top-k-frequent-elements --- top-k-frequent-elements/dusunax.py | 33 ++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 top-k-frequent-elements/dusunax.py diff --git a/top-k-frequent-elements/dusunax.py b/top-k-frequent-elements/dusunax.py new file mode 100644 index 000000000..f57df5ab9 --- /dev/null +++ b/top-k-frequent-elements/dusunax.py @@ -0,0 +1,33 @@ +''' +# Leetcode 347. Top K Frequent Elements + +use **Counter** to count the frequency of each element in the list 🚀 +use **sorted()** to sort the elements by their frequency in descending order. + +## Time and Space Complexity + +``` +TC: O(n log n) +SC: O(n) +``` + +### TC is O(n log n): +- iterating through the list just once to count the frequency of each element. = O(n) +- sorting the elements by their frequency in descending order. = O(n log n) + +### SC is O(n): +- using a Counter to store the frequency of each element. = O(n) +- sorted() creates a new list that holds the elements of frequency_map. = O(n) +- result list that holds the top k frequent elements. = O(k) +''' + +class Solution: + def topKFrequent(self, nums: List[int], k: int) -> List[int]: + frequency_map = Counter(nums) # TC: O(n), SC: O(n) + sorted_frequencies = sorted(frequency_map.items(), key=lambda x: x[1], reverse=True) # TC: O(n log n), SC: O(n) + + result = [] # SC: O(k) + for e in sorted_frequencies: # TC: O(k) + result.append(e[0]) + + return result[0:k] \ No newline at end of file From 86658cbf96bd830216e5bbff433cef48271b185c Mon Sep 17 00:00:00 2001 From: Dusuna <94776135+dusunax@users.noreply.github.com> Date: Thu, 5 Dec 2024 01:56:51 +0900 Subject: [PATCH 06/12] fix: add new line for lint rules --- top-k-frequent-elements/dusunax.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/top-k-frequent-elements/dusunax.py b/top-k-frequent-elements/dusunax.py index f57df5ab9..4bb9ab3d1 100644 --- a/top-k-frequent-elements/dusunax.py +++ b/top-k-frequent-elements/dusunax.py @@ -30,4 +30,5 @@ def topKFrequent(self, nums: List[int], k: int) -> List[int]: for e in sorted_frequencies: # TC: O(k) result.append(e[0]) - return result[0:k] \ No newline at end of file + return result[0:k] + \ No newline at end of file From 395f249375d7deda585237d8dad6230f79736048 Mon Sep 17 00:00:00 2001 From: Dusuna <94776135+dusunax@users.noreply.github.com> Date: Thu, 5 Dec 2024 02:17:48 +0900 Subject: [PATCH 07/12] fix: fix new line --- top-k-frequent-elements/dusunax.py | 1 - 1 file changed, 1 deletion(-) diff --git a/top-k-frequent-elements/dusunax.py b/top-k-frequent-elements/dusunax.py index 4bb9ab3d1..ed2bf8547 100644 --- a/top-k-frequent-elements/dusunax.py +++ b/top-k-frequent-elements/dusunax.py @@ -31,4 +31,3 @@ def topKFrequent(self, nums: List[int], k: int) -> List[int]: result.append(e[0]) return result[0:k] - \ No newline at end of file From e6c66d59a5a5fcc75b02f4194fa3de59260fa4a8 Mon Sep 17 00:00:00 2001 From: Dusuna <94776135+dusunax@users.noreply.github.com> Date: Thu, 5 Dec 2024 03:25:18 +0900 Subject: [PATCH 08/12] fix solution: use equality operator, remove regex --- valid-palindrome/dusunax.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/valid-palindrome/dusunax.py b/valid-palindrome/dusunax.py index 2b21482f5..3cc7eff6e 100644 --- a/valid-palindrome/dusunax.py +++ b/valid-palindrome/dusunax.py @@ -19,10 +19,11 @@ class Solution: def isPalindrome(self, s: str) -> bool: - if s is " ": + if s == " ": return True - reg = "[^a-z0-9]" - converted_s = re.sub(reg, "", s.lower()) + s = s.lower() + converted_s = ''.join(c for c in s if c.isalnum()) return converted_s == converted_s[::-1] + From 89739e6e37f72e1f240e3a9b0ffc501d55cbe4b8 Mon Sep 17 00:00:00 2001 From: Dusuna <94776135+dusunax@users.noreply.github.com> Date: Thu, 5 Dec 2024 03:33:59 +0900 Subject: [PATCH 09/12] fix solution: update comment --- valid-palindrome/dusunax.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/valid-palindrome/dusunax.py b/valid-palindrome/dusunax.py index 3cc7eff6e..52ee0fd1a 100644 --- a/valid-palindrome/dusunax.py +++ b/valid-palindrome/dusunax.py @@ -1,7 +1,7 @@ ''' # Leetcode 125. Valid Palindrome -use regex to filter out non-alphanumeric characters 🔍 +use `isalnum()` to filter out non-alphanumeric characters 🔍 ## Time and Space Complexity @@ -11,10 +11,12 @@ ``` ### TC is O(n): -- iterating through the string just once to filter out non-alphanumeric characters. +- iterating through the string just once to filter out non-alphanumeric characters. O(n) ### SC is O(n): -- creating a new string to store the filtered characters. +- `s.lower()` creates a new string. O(n) +- creating a new string `converted_s` to store the filtered characters. O(n) +- `converted_s[::-1]` creates a new reversed string. O(n) ''' class Solution: From 24792fe69be72a00ea96de2e10df3012c8913ea0 Mon Sep 17 00:00:00 2001 From: Dusuna <94776135+dusunax@users.noreply.github.com> Date: Fri, 6 Dec 2024 18:12:08 +0900 Subject: [PATCH 10/12] add solution: longest-consecutive-sequence --- longest-consecutive-sequence/dusunax.py | 38 +++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 longest-consecutive-sequence/dusunax.py diff --git a/longest-consecutive-sequence/dusunax.py b/longest-consecutive-sequence/dusunax.py new file mode 100644 index 000000000..b912c4807 --- /dev/null +++ b/longest-consecutive-sequence/dusunax.py @@ -0,0 +1,38 @@ +''' +# Leetcode 128. Longest Consecutive Sequence + +keep time complexity O(n) by iterating through the set and accessing elements in O(1) time. ⚖️ + +## Time and Space Complexity +``` +TC: O(n) +SC: O(n) +``` + +### TC is O(n): +- iterating through the set. O(n) +- accessing elements in the set. O(1) +- while loop incrementing `current_num` while `current_num + 1 in nums_set`. O(1) + +### SC is O(n): +- creating a set from the list of numbers. O(n) +''' + +class Solution: + def longestConsecutive(self, nums: List[int]) -> int: + nums_set = set(nums) # O(n) + longest_sequence = 0 + + for num in nums_set: # O(n) + if (num - 1) not in nums_set: + current_num = num + current_sequence = 1 + + while current_num + 1 in nums_set: # O(1) + current_num += 1 + current_sequence += 1 + + longest_sequence = max(current_sequence, longest_sequence) + + return longest_sequence + From 3dff9204762bdd11ac3073420553983789fa4241 Mon Sep 17 00:00:00 2001 From: Dusuna <94776135+dusunax@users.noreply.github.com> Date: Fri, 6 Dec 2024 18:42:30 +0900 Subject: [PATCH 11/12] update solution: top-k-frequent-elements --- top-k-frequent-elements/dusunax.py | 42 +++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/top-k-frequent-elements/dusunax.py b/top-k-frequent-elements/dusunax.py index ed2bf8547..1e8ee7a4c 100644 --- a/top-k-frequent-elements/dusunax.py +++ b/top-k-frequent-elements/dusunax.py @@ -2,23 +2,44 @@ # Leetcode 347. Top K Frequent Elements use **Counter** to count the frequency of each element in the list 🚀 -use **sorted()** to sort the elements by their frequency in descending order. + +- **solution 1**: use **sorted()** to sort the elements by their frequency in descending order. +- **solution 2**: use **bucket sort** to sort the elements by their frequency in descending order. (efficient!) ## Time and Space Complexity +### solution 1: topKFrequent() + ``` TC: O(n log n) SC: O(n) ``` -### TC is O(n log n): +#### TC is O(n log n): - iterating through the list just once to count the frequency of each element. = O(n) - sorting the elements by their frequency in descending order. = O(n log n) -### SC is O(n): +#### SC is O(n): - using a Counter to store the frequency of each element. = O(n) - sorted() creates a new list that holds the elements of frequency_map. = O(n) - result list that holds the top k frequent elements. = O(k) + +### solution 2: topKFrequentBucketSort() + +``` +TC: O(n) +SC: O(n) +``` + +#### TC is O(n): +- iterating through the list just once to count the frequency of each element. = O(n) +- creating **buckets** to store the elements by their frequency. = O(n) +- iterating through the buckets in reverse order to get only the top k frequent elements. = O(n) + +#### SC is O(n): +- using a Counter to store the frequency of each element. = O(n) +- using buckets to store the elements by their frequency. = O(n) +- result list that holds only the top k frequent elements. = O(k) ''' class Solution: @@ -31,3 +52,18 @@ def topKFrequent(self, nums: List[int], k: int) -> List[int]: result.append(e[0]) return result[0:k] + + def topKFrequentBucketSort(self, nums: List[int], k: int) -> List[int]: + frequency_map = Counter(nums) + n = len(nums) + buckets = [[] for _ in range(n + 1)] + + for num, freq in frequency_map.items(): + buckets[freq].append(num) + + result = [] + for i in range(len(buckets) - 1, 0, -1): + for num in buckets[i]: + result.append(num) + if len(result) == k: + return result From 055969d5f165bc9d0cdecc2bdbf1ac9611a65cfe Mon Sep 17 00:00:00 2001 From: Dusuna <94776135+dusunax@users.noreply.github.com> Date: Sat, 7 Dec 2024 18:07:07 +0900 Subject: [PATCH 12/12] add solution: house-robber --- house-robber/dusunax.py | 44 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 house-robber/dusunax.py diff --git a/house-robber/dusunax.py b/house-robber/dusunax.py new file mode 100644 index 000000000..38c238942 --- /dev/null +++ b/house-robber/dusunax.py @@ -0,0 +1,44 @@ +''' +# Leetcode 198. House Robber + +use **dynamic programming** to solve this problem. (bottom-up approach) 🧩 + +choose bottom-up approach for less space complexity. + +## DP relation + +``` +dp[i] = max(dp[i - 1], dp[i - 2] + nums[i]) +``` + +- **dp[i - 1]:** skip and take the value from the previous house +- **dp[i - 2]:** rob the current house, add its value to the maximum money from two houses before + +## Time and Space Complexity + +``` +TC: O(n) +SC: O(n) +``` + +### TC is O(n): +- iterating through the list just once to calculate the maximum money. = O(n) + +### SC is O(n): +- using a list to store the maximum money at each house. = O(n) + +''' + +class Solution: + def rob(self, nums: List[int]) -> int: + if len(nums) == 1: + return nums[0] + + dp = [0] * len(nums) + dp[0] = nums[0] + dp[1] = max(nums[0], nums[1]) + + for i in range(2, len(nums)): + dp[i] = max(dp[i - 1], dp[i - 2] + nums[i]) + + return dp[-1]