Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .github/lc_chart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 4 additions & 6 deletions .github/workflows/update.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,22 +46,20 @@ jobs:

- name: Setup dependencies via uv
if: steps.latest_commit.outputs.should_skip == 'false'
run: uv sync --directory ./.github
run: uv sync

- name: Move solution files to their respective folders via lc_move.py
if: steps.latest_commit.outputs.should_skip == 'false'
id: move_step
run: |
export PYTHONPATH=$GITHUB_WORKSPACE
python ./scripts/lc_move.py | tee output.log
uv run python -B ./scripts/lc_move.py | tee output.log
echo "files_moved=$(grep '\[END\]' output.log | grep -o '[0-9]\+')" >> $GITHUB_OUTPUT
rm output.log

- name: Update progress chart and README via lc_markdown.py
if: steps.latest_commit.outputs.should_skip == 'false' && steps.move_step.outputs.files_moved != '0'
run: |
export PYTHONPATH=$GITHUB_WORKSPACE
python ./scripts/lc_markdown.py
uv run python -B ./scripts/lc_markdown.py

- name: Check for changed files
if: steps.latest_commit.outputs.should_skip == 'false' && steps.move_step.outputs.files_moved != '0'
Expand All @@ -77,7 +75,7 @@ jobs:
if ! git diff --cached --quiet; then
git config user.name $GIT_USERNAME
git config user.email $GIT_EMAIL
git commit -m "[auto] Update README and move solution files (R.N: ${{ github.run_number }})" \
git commit -m "[auto] update README and move solution files (R.N: ${{ github.run_number }})" \
-m "Push commit: ${{ github.sha }} " \
-m "Files moved: ${{ steps.move_step.outputs.files_moved }}" \
-m "Workflow: ${{ github.workflow }}" \
Expand Down
35 changes: 21 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@

Reetkode
========
My personal collection of [LeetCode](https://leetcode.com/) solutions done in multiple languages, shared for learning and reference. 😃
This README is generated using the following custom-built **Python** scripts: [`lc_markdown.py`](scripts/lc_markdown.py), [`lc_chart.py`](scripts/lc_chart.py), and [`lc_stats.py`](scripts/lc_stats.py), as part of an automated **GitHub Actions** [workflow](.github/workflows/main.yml) which runs during checks within pull requests made to the `main` branch, updating the README content and organising solution files prior to merging.
The following diagram illustrates the action flow of using these [scripts](scripts/):
![Script flow](.github/lc_flow.png?)
***
## Progress Overview
![LeetCode stats](.github/lc_chart.png?)

My personal collection of [LeetCode](https://leetcode.com/) solutions done in multiple languages, shared for learning and reference.

This README is generated using the following custom-built **Python** scripts: [`lc_markdown.py`](scripts/lc_markdown.py), [`lc_chart.py`](scripts/lc_chart.py), and [`lc_stats.py`](scripts/lc_stats.py), as part of an automated **GitHub Actions** [workflow](.github/workflows/update.yml) which runs during checks within pull requests made to the `main` branch, updating the README content and organising solution files prior to merging.

The following diagram illustrates the action flow of using these [scripts](scripts/):

![Script flow](.github/lc_flow.png?)
***
## Progress Overview
![LeetCode stats](.github/lc_chart.png?)

## Solutions Directory
|ID|Difficulty|Type|Title|Solutions|
| :--- | :--- | :--- | :--- | :--- |
Expand Down Expand Up @@ -46,13 +46,15 @@ The following diagram illustrates the action flow of using these [scripts](scrip
|**196**|🟩 Easy|🛢️|[Delete Duplicate Emails](https://lcid.cc/196)|<a href="sql/lce_p0196_delete_duplicate_emails_postgresql.sql"><img src=".github/icons/postgresql-original.svg" height="25"></a> <a href="sql/lce_p0196_delete_duplicate_emails_sqlserver.sql"><img src=".github/icons/sqlserver-original.svg" height="25"></a>|
|**197**|🟩 Easy|🛢️|[Rising Temperature](https://lcid.cc/197)|<a href="sql/lce_p0197_rising_temperature_mysql.sql"><img src=".github/icons/mysql-original.svg" height="25"></a> <a href="sql/lce_p0197_rising_temperature_postgresql.sql"><img src=".github/icons/postgresql-original.svg" height="25"></a>|
|**217**|🟩 Easy|⚙️|[Contains Duplicate](https://lcid.cc/217)|<a href="java/lce_p0217_contains_duplicate.java"><img src=".github/icons/java-original.svg" height="25"></a>|
|**230**|🟨 Medium|⚙️|[Kth Smallest Element In A Bst](https://lcid.cc/230)|<a href="python/lcm_p0230_kth_smallest_element_in_a_bst.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**238**|🟨 Medium|⚙️|[Product Of Array Except Self](https://lcid.cc/238)|<a href="java/lcm_p0238_product_of_array_except_self.java"><img src=".github/icons/java-original.svg" height="25"></a> <a href="python/lcm_p0238_product_of_array_except_self.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**242**|🟩 Easy|⚙️|[Valid Anagram](https://lcid.cc/242)|<a href="java/lce_p0242_valid_anagram.java"><img src=".github/icons/java-original.svg" height="25"></a> <a href="python/lce_p0242_valid_anagram.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**271**|🟨 Medium|⚙️|[Encode And Decode Strings](https://lcid.cc/271)|<a href="java/lcm_p0271_encode_and_decode_strings.java"><img src=".github/icons/java-original.svg" height="25"></a>|
|**283**|🟩 Easy|⚙️|[Move Zeroes](https://lcid.cc/283)|<a href="python/lce_p0283_move_zeroes.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**334**|🟨 Medium|⚙️|[Increasing Triplet Subsequence](https://lcid.cc/334)|<a href="python/lcm_p0334_increasing_triplet_subsequence.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**345**|🟩 Easy|⚙️|[Reverse Vowels Of A String](https://lcid.cc/345)|<a href="python/lce_p0345_reverse_vowels_of_a_string.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**347**|🟨 Medium|⚙️|[Top K Frequent Elements](https://lcid.cc/347)|<a href="java/lcm_p0347_top_k_frequent_elements.java"><img src=".github/icons/java-original.svg" height="25"></a>|
|**366**|🟨 Medium|⚙️|[Find Leaves Of Binary Tree](https://lcid.cc/366)|<a href="python/lcm_p0366_find_leaves_of_binary_tree.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**387**|🟩 Easy|⚙️|[First Unique Character String](https://lcid.cc/387)|<a href="python/lce_p0387_first_unique_character_string.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**389**|🟩 Easy|⚙️|[Find The Difference](https://lcid.cc/389)|<a href="python/lce_p0389_find_the_difference.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**392**|🟩 Easy|⚙️|[Is Subsequence](https://lcid.cc/392)|<a href="python/lce_p0392_is_subsequence.py"><img src=".github/icons/python-original.svg" height="25"></a>|
Expand Down Expand Up @@ -112,6 +114,7 @@ The following diagram illustrates the action flow of using these [scripts](scrip
|**1211**|🟩 Easy|🛢️|[Queries Quality And Percentage](https://lcid.cc/1211)|<a href="sql/lce_p1211_queries_quality_and_percentage_mysql.sql"><img src=".github/icons/mysql-original.svg" height="25"></a>|
|**1232**|🟩 Easy|⚙️|[Check If It Is A Straight Line](https://lcid.cc/1232)|<a href="python/lce_p1232_check_if_it_is_a_straight_line.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**1251**|🟩 Easy|🛢️|[Average Selling Price](https://lcid.cc/1251)|<a href="sql/lce_p1251_average_selling_price_mysql.sql"><img src=".github/icons/mysql-original.svg" height="25"></a>|
|**1255**|🟥 Hard|⚙️|[Maximum Score Words Formed By Letters](https://lcid.cc/1255)|<a href="python/lch_p1255_maximum_score_words_formed_by_letters.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**1280**|🟩 Easy|🛢️|[Students And Examinations](https://lcid.cc/1280)|<a href="sql/lce_p1280_students_and_examinations_mysql.sql"><img src=".github/icons/mysql-original.svg" height="25"></a>|
|**1321**|🟨 Medium|🛢️|[Restaurant Growth](https://lcid.cc/1321)|<a href="sql/lcm_p1321_restaurant_growth_mysql.sql"><img src=".github/icons/mysql-original.svg" height="25"></a>|
|**1327**|🟩 Easy|🛢️|[List The Products Ordered In A Period](https://lcid.cc/1327)|<a href="sql/lce_p1327_list_the_products_ordered_in_a_period_mysql.sql"><img src=".github/icons/mysql-original.svg" height="25"></a>|
Expand Down Expand Up @@ -175,6 +178,7 @@ The following diagram illustrates the action flow of using these [scripts](scrip
|**1978**|🟩 Easy|🛢️|[Employees Whose Manager Left The Company](https://lcid.cc/1978)|<a href="sql/lce_p1978_employees_whose_manager_left_the_company_sqlserver.sql"><img src=".github/icons/sqlserver-original.svg" height="25"></a>|
|**1995**|🟩 Easy|⚙️|[Count Special Quadruplets](https://lcid.cc/1995)|<a href="python/lce_p1995_count_special_quadruplets.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**2042**|🟩 Easy|⚙️|[Check If Numbers Are Ascending In A Sentence](https://lcid.cc/2042)|<a href="python/lce_p2042_check_if_numbers_are_ascending_in_a_sentence.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**2044**|🟨 Medium|⚙️|[Count Number Of Maximum Bitwise-or Subsets](https://lcid.cc/2044)|<a href="python/lcm_p2044_count_number_of_maximum_bitwise-or_subsets.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**2073**|🟩 Easy|⚙️|[Time Needed To Buy Tickets](https://lcid.cc/2073)|<a href="python/lce_p2073_time_needed_to_buy_tickets.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**2109**|🟨 Medium|⚙️|[Adding Spaces To A String](https://lcid.cc/2109)|<a href="java/lcm_p2109_adding_spaces_to_a_string.java"><img src=".github/icons/java-original.svg" height="25"></a>|
|**2124**|🟩 Easy|⚙️|[Check If All As Appears Before All Bs](https://lcid.cc/2124)|<a href="python/lce_p2124_check_if_all_as_appears_before_all_bs.py"><img src=".github/icons/python-original.svg" height="25"></a>|
Expand Down Expand Up @@ -234,6 +238,7 @@ The following diagram illustrates the action flow of using these [scripts](scrip
|**3163**|🟨 Medium|⚙️|[String Compression III](https://lcid.cc/3163)|<a href="java/lcm_p3163_string_compression_iii.java"><img src=".github/icons/java-original.svg" height="25"></a>|
|**3173**|🟩 Easy|⚙️|[Bitwise Or Of Adjacent Elements](https://lcid.cc/3173)|<a href="python/lce_p3173_bitwise_or_of_adjacent_elements.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**3174**|🟩 Easy|⚙️|[Clear Digits](https://lcid.cc/3174)|<a href="python/lce_p3174_clear_digits.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**3211**|🟨 Medium|⚙️|[Generate Binary Strings Without Adjacent Zeros](https://lcid.cc/3211)|<a href="python/lcm_p3211_generate_binary_strings_without_adjacent_zeros.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**3220**|🟨 Medium|🛢️|[Odd And Even Transactions](https://lcid.cc/3220)|<a href="sql/lcm_p3220_odd_and_even_transactions_mysql.sql"><img src=".github/icons/mysql-original.svg" height="25"></a>|
|**3223**|🟨 Medium|⚙️|[Minimum Length Of String After Operations](https://lcid.cc/3223)|<a href="python/lcm_p3223_minimum_length_of_string_after_operations.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**3300**|🟩 Easy|⚙️|[Minimum Element After Replacement With Digit Sum](https://lcid.cc/3300)|<a href="python/lce_p3300_minimum_element_after_replacement_with_digit_sum.py"><img src=".github/icons/python-original.svg" height="25"></a>|
Expand All @@ -254,6 +259,8 @@ The following diagram illustrates the action flow of using these [scripts](scrip
|**3536**|🟩 Easy|⚙️|[Maximum Product Of Two Digits](https://lcid.cc/3536)|<a href="python/lce_p3536_maximum_product_of_two_digits.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**3541**|🟩 Easy|⚙️|[Find Most Frequent Vowel And Consonant](https://lcid.cc/3541)|<a href="python/lce_p3541_find_most_frequent_vowel_and_consonant.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**3550**|🟩 Easy|⚙️|[Smallest Index With Digit Sum Equal To Index](https://lcid.cc/3550)|<a href="python/lce_p3550_smallest_index_with_digit_sum_equal_to_index.py"><img src=".github/icons/python-original.svg" height="25"></a>|


|**3616**|🟨 Medium|⚙️|[Number Of Student Replacements](https://lcid.cc/3616)|<a href="python/lcm_p3616_number_of_student_replacements.py"><img src=".github/icons/python-original.svg" height="25"></a>|
|**3631**|🟨 Medium|⚙️|[Sort Threats By Severity And Exploitability](https://lcid.cc/3631)|<a href="python/lcm_p3631_sort_threats_by_severity_and_exploitability.py"><img src=".github/icons/python-original.svg" height="25"></a>|


#### <div align="right"> [🔝Return to top](#reetkode) </div>
File renamed without changes.
63 changes: 63 additions & 0 deletions python/lch_p1255_maximum_score_words_formed_by_letters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"""
LCH 1255. Maximum Score Words Formed by Letters

Given a list of words, list of single letters (might be repeating) and score of every character.

Return the maximum score of any valid set of words formed by using the given letters (words[i] cannot be used two or more times).

It is not necessary to use all characters in letters and each letter can only be used once. Score of letters 'a', 'b', 'c', ... ,'z' is given by score[0], score[1], ... , score[25] respectively

Constraints:
- 1 <= words.length <= 14
- 1 <= words[i].length <= 15
- 1 <= letters.length <= 100
- letters[i].length == 1
- score.length == 26
- 0 <= score[i] <= 10
- words[i], letters[i] contains only lower case English letters.

Topics:
- Array
- String
- Dynamic Programming
- Backtracking
- Bit Manipulation
- Bitmask
"""


class Solution:
def recurse(self, words: List[str], letter_freq: List[int], score: List[int], start: int, curr_score: int) -> int:
max_score = curr_score

for i in range(start, len(words)):
word = words[i]
word_letter_freq = [0] * 26
for ch in word: word_letter_freq[ord(ch) - ord('a')] += 1

can_create = True
temp_score = 0
temp_letter_freq = list(letter_freq)

for j in range(26):
if word_letter_freq[j] > temp_letter_freq[j]:
can_create = False
break

temp_score += (word_letter_freq[j] * score[j])
temp_letter_freq[j] -= word_letter_freq[j]

if can_create:
max_score = max(max_score, self.recurse(words, temp_letter_freq, score, i + 1, curr_score + temp_score))

return max_score

def maxScoreWords(self, words: List[str], letters: List[str], score: List[int]) -> int:
letter_freq = [0] * 26
for letter in letters: letter_freq[ord(letter) - ord('a')] += 1

return self.recurse(words, letter_freq, score, 0, 0)


# Time Complexity: O(n * 2^n) - 11 ms -> 71.76%
# Space Complexity: O(1) - 17.81 MB -> 73.01%
43 changes: 43 additions & 0 deletions python/lcm_p0230_kth_smallest_element_in_a_bst.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""
LCM 230. Kth Smallest Element in a BST

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.

Constraints:
- The number of nodes in the tree is n.
- 1 <= k <= n <= 10^4
- 0 <= Node.val <= 10^4

Topics:
- Tree
- Depth-First Search
- Binary Search Tree
- Binary Tree
"""


# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def dfs(self, node: Optional[TreeNode], arr: list[int]) -> list[int]:
if node.left:
self.dfs(node.left, arr)

arr.append(node.val)

if node.right:
self.dfs(node.right, arr)

return arr

def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
arr = self.dfs(root, [])
return arr[k - 1]


# Time Complexity: O(n) - 4 ms -> 16.15%
# Space Complexity: O(n) - 21.20 MB -> 27.36%
51 changes: 51 additions & 0 deletions python/lcm_p0366_find_leaves_of_binary_tree.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""
LCM 366. Find Leaves of Binary Tree (Premium)

Given the root of a binary tree, collect a tree's nodes as if you were doing this:
- Collect all the leaf nodes.
- Remove all the leaf nodes.
- Repeat until the tree is empty.

Constraints:
- The number of nodes in the tree is in the range [1, 100].
- -100 <= Node.val <= 100

Topics:
- Tree
- Depth-First Search
- Binary Tree
"""


# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
# group nodes based on the maximum depth of their left and right subtrees
def findLeaves(self, root: Optional[TreeNode]) -> List[List[int]]:
mapper = {}

def dfs(node: Optional[TreeNode], level: int) -> int:
if not node:
return level

left = dfs(node.left, level)
right = dfs(node.right, level)
level = max(left, right)

if level not in mapper:
mapper[level] = [node.val]
else:
mapper[level].append(node.val)

return level + 1

dfs(root, 0)
return list(mapper.values())


# Time Complexity: O(n) - 0 ms -> 100.00%
# Space Complexity: O(n) - 17.28 MB -> 42.81%
44 changes: 44 additions & 0 deletions python/lcm_p2044_count_number_of_maximum_bitwise-or_subsets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""
LCM 2044. Count Number of Maximum Bitwise-OR Subsets

Given an integer array nums, find the maximum possible bitwise OR of a subset of nums and return the number of different non-empty subsets with the maximum bitwise OR.

An array a is a subset of an array b if a can be obtained from b by deleting some (possibly zero) elements of b.
Two subsets are considered different if the indices of the elements chosen are different.

The bitwise OR of an array a is equal to a[0] OR a[1] OR ... OR a[a.length - 1] (0-indexed).

Constraints:
- 1 <= nums.length <= 16
- 1 <= nums[i] <= 10^5

Topics:
- Array
- Backtracking
- Bit Manipulation
- Enumeration
"""


class Solution:
def countMaxOrSubsets(self, nums: List[int]) -> int:
max_bitwise_or = reduce(lambda x, y: x | y, nums)
n = len(nums)

def backtrack(prev: int, start_idx: int) -> int:
count = 0

for i in range(start_idx, n):
curr = prev | nums[i]
if curr == max_bitwise_or:
count += 1

count += backtrack(curr, i + 1)

return count

return backtrack(0, 0)


# Time Complexity: O(2^n) - 271 ms -> 38.30%
# Space Complexity: O(1) - 17.71 MB -> 72.24%
39 changes: 39 additions & 0 deletions python/lcm_p3211_generate_binary_strings_without_adjacent_zeros.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""
LCM 3211. Generate Binary Strings Without Adjacent Zeros

You are given a positive integer n.

A binary string x is valid if all substrings of x of length 2 contain at least one "1".

Return all valid strings with length n, in any order.

Constraints:
- 1 <= n <= 18

Topics:
- String
- Backtracking
- Bit Manipulation
"""


class Solution:
def dfs(self, size: int, s: str, lst: list) -> List[str]:
if size == len(s):
lst.append(s)
return

for i in range(2):
if i == 0 and s and s[-1] == "0":
continue

self.dfs(size, s + str(i), lst)

return lst

def validStrings(self, n: int) -> List[str]:
return self.dfs(n, "", [])


# Time Complexity: O(2^n) - 63 ms -> 26.49%
# Space Complexity: O(2^n) - 19.08 MB -> 83.41%
Loading