diff --git a/g0001_0100/s0034_find_first_and_last_position_of_element_in_sorted_array/readme.md b/g0001_0100/s0034_find_first_and_last_position_of_element_in_sorted_array/readme.md
new file mode 100644
index 0000000..9f5c72c
--- /dev/null
+++ b/g0001_0100/s0034_find_first_and_last_position_of_element_in_sorted_array/readme.md
@@ -0,0 +1,102 @@
+34\. Find First and Last Position of Element in Sorted Array
+
+Medium
+
+Given an array of integers `nums` sorted in non-decreasing order, find the starting and ending position of a given `target` value.
+
+If `target` is not found in the array, return `[-1, -1]`.
+
+You must write an algorithm with `O(log n)` runtime complexity.
+
+**Example 1:**
+
+**Input:** nums = [5,7,7,8,8,10], target = 8
+
+**Output:** [3,4] 
+
+**Example 2:**
+
+**Input:** nums = [5,7,7,8,8,10], target = 6
+
+**Output:** [-1,-1] 
+
+**Example 3:**
+
+**Input:** nums = [], target = 0
+
+**Output:** [-1,-1] 
+
+**Constraints:**
+
+*   <code>0 <= nums.length <= 10<sup>5</sup></code>
+*   <code>-10<sup>9</sup> <= nums[i] <= 10<sup>9</sup></code>
+*   `nums` is a non-decreasing array.
+*   <code>-10<sup>9</sup> <= target <= 10<sup>9</sup></code>
+
+To solve this problem efficiently with a runtime complexity of O(log n), we can use binary search to find the starting and ending positions of the target value in the sorted array. Here are the steps:
+
+### Approach:
+
+1. **Binary Search for Starting Position:**
+   - Use binary search to find the starting position of the target value.
+   - When the target value is found, continue searching towards the left to find the leftmost occurrence.
+   - Update the left boundary to narrow down the search space.
+
+2. **Binary Search for Ending Position:**
+   - Use binary search to find the ending position of the target value.
+   - When the target value is found, continue searching towards the right to find the rightmost occurrence.
+   - Update the right boundary to narrow down the search space.
+
+3. **Handle Missing Target:**
+   - If the target value is not found, return [-1, -1].
+
+### Python Code:
+
+```python
+class Solution:
+    def searchRange(self, nums, target):
+        def search_boundary(nums, target, is_left):
+            left, right = 0, len(nums) - 1
+            boundary = -1
+
+            while left <= right:
+                mid = (left + right) // 2
+
+                if nums[mid] == target:
+                    boundary = mid
+                    if is_left:
+                        right = mid - 1
+                    else:
+                        left = mid + 1
+                elif nums[mid] < target:
+                    left = mid + 1
+                else:
+                    right = mid - 1
+
+            return boundary
+
+        left_boundary = search_boundary(nums, target, is_left=True)
+        right_boundary = search_boundary(nums, target, is_left=False)
+
+        return [left_boundary, right_boundary]
+
+# Example Usage:
+solution = Solution()
+
+# Example 1:
+nums1 = [5, 7, 7, 8, 8, 10]
+target1 = 8
+print(solution.searchRange(nums1, target1))  # Output: [3, 4]
+
+# Example 2:
+nums2 = [5, 7, 7, 8, 8, 10]
+target2 = 6
+print(solution.searchRange(nums2, target2))  # Output: [-1, -1]
+
+# Example 3:
+nums3 = []
+target3 = 0
+print(solution.searchRange(nums3, target3))  # Output: [-1, -1]
+```
+
+This code defines a `Solution` class with a `searchRange` method to find the starting and ending positions of the target value in the given array. The example usage demonstrates how to create an instance of the `Solution` class and call the `searchRange` method with different inputs.
\ No newline at end of file
diff --git a/g0001_0100/s0035_search_insert_position/readme.md b/g0001_0100/s0035_search_insert_position/readme.md
new file mode 100644
index 0000000..f531793
--- /dev/null
+++ b/g0001_0100/s0035_search_insert_position/readme.md
@@ -0,0 +1,104 @@
+35\. Search Insert Position
+
+Easy
+
+Given a sorted array of distinct integers and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.
+
+You must write an algorithm with `O(log n)` runtime complexity.
+
+**Example 1:**
+
+**Input:** nums = [1,3,5,6], target = 5
+
+**Output:** 2 
+
+**Example 2:**
+
+**Input:** nums = [1,3,5,6], target = 2
+
+**Output:** 1 
+
+**Example 3:**
+
+**Input:** nums = [1,3,5,6], target = 7
+
+**Output:** 4 
+
+**Example 4:**
+
+**Input:** nums = [1,3,5,6], target = 0
+
+**Output:** 0 
+
+**Example 5:**
+
+**Input:** nums = [1], target = 0
+
+**Output:** 0 
+
+**Constraints:**
+
+*   <code>1 <= nums.length <= 10<sup>4</sup></code>
+*   <code>-10<sup>4</sup> <= nums[i] <= 10<sup>4</sup></code>
+*   `nums` contains **distinct** values sorted in **ascending** order.
+*   <code>-10<sup>4</sup> <= target <= 10<sup>4</sup></code>
+
+To solve this problem efficiently with a runtime complexity of O(log n), we can use binary search to find the insertion position of the target value in the sorted array. Here are the steps:
+
+### Approach:
+
+1. **Binary Search:**
+   - Implement binary search to find the insertion position of the target value.
+   - If the target value is found, return its index.
+   - If the target value is not found, binary search will determine the index where the target would be inserted to maintain the sorted order.
+
+### Python Code:
+
+```python
+class Solution:
+    def searchInsert(self, nums, target):
+        left, right = 0, len(nums) - 1
+
+        while left <= right:
+            mid = (left + right) // 2
+
+            if nums[mid] == target:
+                return mid
+            elif nums[mid] < target:
+                left = mid + 1
+            else:
+                right = mid - 1
+
+        # If the target is not found, return the insertion position (left).
+        return left
+
+# Example Usage:
+solution = Solution()
+
+# Example 1:
+nums1 = [1, 3, 5, 6]
+target1 = 5
+print(solution.searchInsert(nums1, target1))  # Output: 2
+
+# Example 2:
+nums2 = [1, 3, 5, 6]
+target2 = 2
+print(solution.searchInsert(nums2, target2))  # Output: 1
+
+# Example 3:
+nums3 = [1, 3, 5, 6]
+target3 = 7
+print(solution.searchInsert(nums3, target3))  # Output: 4
+
+# Example 4:
+nums4 = [1, 3, 5, 6]
+target4 = 0
+print(solution.searchInsert(nums4, target4))  # Output: 0
+
+# Example 5:
+nums5 = [1]
+target5 = 0
+print(solution.searchInsert(nums5, target5))  # Output: 0
+```
+
+This code defines a `Solution` class with a `searchInsert` method to find the insertion position of the target value in the given sorted array. The example usage demonstrates how to create an instance of the `Solution` class and call the `searchInsert` method with different inputs.
\ No newline at end of file
diff --git a/g0001_0100/s0039_combination_sum/readme.md b/g0001_0100/s0039_combination_sum/readme.md
new file mode 100644
index 0000000..1985e77
--- /dev/null
+++ b/g0001_0100/s0039_combination_sum/readme.md
@@ -0,0 +1,104 @@
+39\. Combination Sum
+
+Medium
+
+Given an array of **distinct** integers `candidates` and a target integer `target`, return _a list of all **unique combinations** of_ `candidates` _where the chosen numbers sum to_ `target`_._ You may return the combinations in **any order**.
+
+The **same** number may be chosen from `candidates` an **unlimited number of times**. Two combinations are unique if the frequency of at least one of the chosen numbers is different.
+
+It is **guaranteed** that the number of unique combinations that sum up to `target` is less than `150` combinations for the given input.
+
+**Example 1:**
+
+**Input:** candidates = [2,3,6,7], target = 7
+
+**Output:** [[2,2,3],[7]]
+
+**Explanation:**
+
+    2 and 3 are candidates, and 2 + 2 + 3 = 7. Note that 2 can be used multiple times.
+    7 is a candidate, and 7 = 7.
+    These are the only two combinations. 
+
+**Example 2:**
+
+**Input:** candidates = [2,3,5], target = 8
+
+**Output:** [[2,2,2,2],[2,3,3],[3,5]] 
+
+**Example 3:**
+
+**Input:** candidates = [2], target = 1
+
+**Output:** [] 
+
+**Example 4:**
+
+**Input:** candidates = [1], target = 1
+
+**Output:** [[1]] 
+
+**Example 5:**
+
+**Input:** candidates = [1], target = 2
+
+**Output:** [[1,1]] 
+
+**Constraints:**
+
+*   `1 <= candidates.length <= 30`
+*   `1 <= candidates[i] <= 200`
+*   All elements of `candidates` are **distinct**.
+*   `1 <= target <= 500`
+
+To solve the Combination Sum problem, you can use backtracking. Here are the steps you can follow:
+
+1. **Define the function**: Create a function, let's name it `combinationSum`, that takes `candidates`, `target`, and any other necessary parameters.
+
+2. **Sort the candidates**: Sort the `candidates` array. Sorting helps in pruning the search space during backtracking.
+
+3. **Initialize variables**: Initialize an empty list to store the result combinations. 
+
+4. **Define a helper function**: Create a recursive helper function, let's name it `backtrack`, that takes the current combination, the current index of the candidate being considered, and the remaining target.
+
+5. **Base case**: If the target is 0, add the current combination to the result list.
+
+6. **Iterate through candidates**: Start iterating from the current index to the end of the `candidates` array.
+
+7. **Check the sum condition**: For each candidate, check if adding it to the current combination keeps the sum less than or equal to the target. If so, recursively call the `backtrack` function with the updated combination, the current index, and the reduced target.
+
+8. **Backtrack**: After the recursive call returns, remove the last element from the current combination to backtrack.
+
+9. **Call the helper function**: Call the `backtrack` function initially with an empty combination, starting index 0, and the target.
+
+10. **Return the result**: Return the list of combinations obtained.
+
+Here's a Python code snippet implementing the above steps:
+
+```python
+class Solution:
+    def combinationSum(self, candidates, target):
+        def backtrack(start, target, path):
+            if target == 0:
+                result.append(path)
+                return
+            for i in range(start, len(candidates)):
+                if candidates[i] > target:
+                    break
+                backtrack(i, target - candidates[i], path + [candidates[i]])
+
+        result = []
+        candidates.sort()
+        backtrack(0, target, [])
+        return result
+
+# Test cases
+solution = Solution()
+print(solution.combinationSum([2,3,6,7], 7)) # Output: [[2, 2, 3], [7]]
+print(solution.combinationSum([2,3,5], 8))   # Output: [[2, 2, 2, 2], [2, 3, 3], [5, 3]]
+print(solution.combinationSum([2], 1))        # Output: []
+print(solution.combinationSum([1], 1))        # Output: [[1]]
+print(solution.combinationSum([1], 2))        # Output: [[1, 1]]
+```
+
+This implementation efficiently finds all unique combinations that sum up to the target.
\ No newline at end of file
diff --git a/g0001_0100/s0041_first_missing_positive/readme.md b/g0001_0100/s0041_first_missing_positive/readme.md
new file mode 100644
index 0000000..207330a
--- /dev/null
+++ b/g0001_0100/s0041_first_missing_positive/readme.md
@@ -0,0 +1,87 @@
+41\. First Missing Positive
+
+Hard
+
+Given an unsorted integer array `nums`, return the smallest missing positive integer.
+
+You must implement an algorithm that runs in `O(n)` time and uses constant extra space.
+
+**Example 1:**
+
+**Input:** nums = [1,2,0]
+
+**Output:** 3 
+
+**Example 2:**
+
+**Input:** nums = [3,4,-1,1]
+
+**Output:** 2 
+
+**Example 3:**
+
+**Input:** nums = [7,8,9,11,12]
+
+**Output:** 1 
+
+**Constraints:**
+
+*   <code>1 <= nums.length <= 5 * 10<sup>5</sup></code>
+*   <code>-2<sup>31</sup> <= nums[i] <= 2<sup>31</sup> - 1</code>
+
+To solve the "First Missing Positive" problem efficiently with O(n) time complexity and constant extra space, you can use the cyclic sort algorithm. Here's a step-by-step approach:
+
+### Approach:
+
+1. **Cyclic Sort:**
+   - Perform cyclic sort on the given array `nums`.
+   - Iterate through each number in the array and place it in its correct position if it is a positive integer and within the range of the array size.
+   - Ignore negative numbers and numbers greater than the size of the array.
+   - After cyclic sort, the array should contain positive integers starting from 1 to n, where n is the size of the array.
+
+2. **Find the First Missing Positive:**
+   - Iterate through the sorted array.
+   - The first index where the value is not equal to its index plus one is the smallest missing positive integer.
+   - If all numbers are in their correct positions, the smallest missing positive integer is the next integer after the array size.
+
+### Python Code:
+
+```python
+class Solution:
+    def firstMissingPositive(self, nums):
+        n = len(nums)
+        i = 0
+
+        while i < n:
+            # If the number is positive and within the range of the array size,
+            # and it's not already in its correct position, swap it to its correct position.
+            if 1 <= nums[i] <= n and nums[i] != nums[nums[i] - 1]:
+                nums[nums[i] - 1], nums[i] = nums[i], nums[nums[i] - 1]
+            else:
+                i += 1
+
+        # Iterate through the sorted array to find the first missing positive integer.
+        for i in range(n):
+            if nums[i] != i + 1:
+                return i + 1
+
+        # If all numbers are in their correct positions, return the next positive integer.
+        return n + 1
+
+# Example Usage:
+solution = Solution()
+
+# Example 1:
+nums1 = [1, 2, 0]
+print(solution.firstMissingPositive(nums1))  # Output: 3
+
+# Example 2:
+nums2 = [3, 4, -1, 1]
+print(solution.firstMissingPositive(nums2))  # Output: 2
+
+# Example 3:
+nums3 = [7, 8, 9, 11, 12]
+print(solution.firstMissingPositive(nums3))  # Output: 1
+```
+
+This code defines a `Solution` class with a `firstMissingPositive` method to find the smallest missing positive integer in the given unsorted array `nums`. The example usage demonstrates how to create an instance of the `Solution` class and call the `firstMissingPositive` method with different inputs.
\ No newline at end of file
diff --git a/g0001_0100/s0042_trapping_rain_water/readme.md b/g0001_0100/s0042_trapping_rain_water/readme.md
new file mode 100644
index 0000000..dd4b12e
--- /dev/null
+++ b/g0001_0100/s0042_trapping_rain_water/readme.md
@@ -0,0 +1,88 @@
+42\. Trapping Rain Water
+
+Hard
+
+Given `n` non-negative integers representing an elevation map where the width of each bar is `1`, compute how much water it can trap after raining.
+
+**Example 1:**
+
+![](https://assets.leetcode.com/uploads/2018/10/22/rainwatertrap.png)
+
+**Input:** height = [0,1,0,2,1,0,1,3,2,1,2,1]
+
+**Output:** 6
+
+**Explanation:** The above elevation map (black section) is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. 
+
+**Example 2:**
+
+**Input:** height = [4,2,0,3,2,5]
+
+**Output:** 9 
+
+**Constraints:**
+
+*   `n == height.length`
+*   <code>1 <= n <= 2 * 10<sup>4</sup></code>
+*   <code>0 <= height[i] <= 10<sup>5</sup></code>
+
+To solve the "Trapping Rain Water" problem efficiently, you can use a two-pointer approach. Here are the steps to solve the problem:
+
+### Approach:
+
+1. **Initialize Pointers:**
+   - Initialize two pointers `left` and `right` at the two ends of the array `height`.
+
+2. **Initialize Variables:**
+   - Initialize variables `max_left` and `max_right` to keep track of the maximum height encountered from the left and right sides, respectively.
+   - Initialize a variable `water` to store the total trapped water.
+
+3. **Iterate Through Array:**
+   - While `left` pointer is less than `right` pointer, do the following:
+     - If `height[left]` is less than or equal to `height[right]`:
+       - Update `max_left` to the maximum of `max_left` and `height[left]`.
+       - Add `max_left - height[left]` to `water`.
+       - Increment `left` pointer.
+     - Else:
+       - Update `max_right` to the maximum of `max_right` and `height[right]`.
+       - Add `max_right - height[right]` to `water`.
+       - Decrement `right` pointer.
+
+4. **Return Result:**
+   - After the loop ends, return the total trapped water.
+
+### Python Code:
+
+```python
+class Solution:
+    def trap(self, height):
+        n = len(height)
+        left, right = 0, n - 1
+        max_left = max_right = 0
+        water = 0
+        
+        while left < right:
+            if height[left] <= height[right]:
+                max_left = max(max_left, height[left])
+                water += max_left - height[left]
+                left += 1
+            else:
+                max_right = max(max_right, height[right])
+                water += max_right - height[right]
+                right -= 1
+                
+        return water
+
+# Example Usage:
+solution = Solution()
+
+# Example 1:
+height1 = [0,1,0,2,1,0,1,3,2,1,2,1]
+print(solution.trap(height1))  # Output: 6
+
+# Example 2:
+height2 = [4,2,0,3,2,5]
+print(solution.trap(height2))  # Output: 9
+```
+
+This code defines a `Solution` class with a `trap` method to compute how much water can be trapped after raining in the given elevation map represented by the array `height`. The example usage demonstrates how to create an instance of the `Solution` class and call the `trap` method with different inputs.
\ No newline at end of file
diff --git a/g0001_0100/s0045_jump_game_ii/readme.md b/g0001_0100/s0045_jump_game_ii/readme.md
new file mode 100644
index 0000000..15e864f
--- /dev/null
+++ b/g0001_0100/s0045_jump_game_ii/readme.md
@@ -0,0 +1,78 @@
+45\. Jump Game II
+
+Medium
+
+Given an array of non-negative integers `nums`, you are initially positioned at the first index of the array.
+
+Each element in the array represents your maximum jump length at that position.
+
+Your goal is to reach the last index in the minimum number of jumps.
+
+You can assume that you can always reach the last index.
+
+**Example 1:**
+
+**Input:** nums = [2,3,1,1,4]
+
+**Output:** 2
+
+**Explanation:** The minimum number of jumps to reach the last index is 2. Jump 1 step from index 0 to 1, then 3 steps to the last index. 
+
+**Example 2:**
+
+**Input:** nums = [2,3,0,1,4]
+
+**Output:** 2 
+
+**Constraints:**
+
+*   <code>1 <= nums.length <= 10<sup>4</sup></code>
+*   `0 <= nums[i] <= 1000`
+
+To solve the "Jump Game II" problem efficiently, you can use a greedy approach. Here are the steps to solve the problem:
+
+### Approach:
+
+1. **Initialize Variables:**
+   - Initialize variables `max_reach` to store the farthest index that can be reached from the current position.
+   - Initialize variables `steps` to store the minimum number of jumps needed to reach the current position.
+   - Initialize variables `last_jump` to store the index where the last jump was made.
+
+2. **Iterate Through Array:**
+   - Iterate through the array `nums` up to the second last index.
+   - For each index `i`:
+     - Update `max_reach` to the maximum of `max_reach` and `i + nums[i]`.
+     - If `i` reaches the `last_jump` index, update `last_jump` to `max_reach` and increment `steps`.
+
+3. **Return Result:**
+   - After the loop ends, return the `steps` variable, which contains the minimum number of jumps needed to reach the last index.
+
+### Python Code:
+
+```python
+class Solution:
+    def jump(self, nums):
+        n = len(nums)
+        max_reach = last_jump = steps = 0
+        
+        for i in range(n - 1):
+            max_reach = max(max_reach, i + nums[i])
+            if i == last_jump:
+                last_jump = max_reach
+                steps += 1
+                
+        return steps
+
+# Example Usage:
+solution = Solution()
+
+# Example 1:
+nums1 = [2,3,1,1,4]
+print(solution.jump(nums1))  # Output: 2
+
+# Example 2:
+nums2 = [2,3,0,1,4]
+print(solution.jump(nums2))  # Output: 2
+```
+
+This code defines a `Solution` class with a `jump` method to compute the minimum number of jumps needed to reach the last index in the given array `nums`. The example usage demonstrates how to create an instance of the `Solution` class and call the `jump` method with different inputs.
\ No newline at end of file
diff --git a/g0001_0100/s0046_permutations/readme.md b/g0001_0100/s0046_permutations/readme.md
new file mode 100644
index 0000000..2d16555
--- /dev/null
+++ b/g0001_0100/s0046_permutations/readme.md
@@ -0,0 +1,92 @@
+46\. Permutations
+
+Medium
+
+Given an array `nums` of distinct integers, return _all the possible permutations_. You can return the answer in **any order**.
+
+**Example 1:**
+
+**Input:** nums = [1,2,3]
+
+**Output:** [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] 
+
+**Example 2:**
+
+**Input:** nums = [0,1]
+
+**Output:** [[0,1],[1,0]] 
+
+**Example 3:**
+
+**Input:** nums = [1]
+
+**Output:** [[1]] 
+
+**Constraints:**
+
+*   `1 <= nums.length <= 6`
+*   `-10 <= nums[i] <= 10`
+*   All the integers of `nums` are **unique**.
+
+To solve the "Permutations" problem, you can use backtracking. Here are the steps to solve the problem:
+
+### Approach:
+
+1. **Define Backtracking Function:**
+   - Define a backtracking function `backtrack` to generate permutations recursively.
+   - The function should take three parameters:
+     - `path`: The current permutation being generated.
+     - `nums`: The input array of distinct integers.
+     - `result`: A list to store all permutations.
+
+2. **Base Case:**
+   - If the length of `path` equals the length of `nums`, append a copy of `path` to `result` and return.
+
+3. **Recursive Step:**
+   - Iterate through each element `num` in `nums`.
+   - If `num` is not in `path`, append `num` to `path`.
+   - Recur with the updated `path`.
+
+4. **Generate Permutations:**
+   - Call the backtracking function `backtrack` with an empty list `path`, the input array `nums`, and an empty list `result`.
+
+5. **Return Result:**
+   - After generating all permutations, return the `result` list.
+
+### Python Code:
+
+```python
+class Solution:
+    def permute(self, nums):
+        def backtrack(path, nums, result):
+            if len(path) == len(nums):
+                result.append(path[:])
+                return
+            
+            for num in nums:
+                if num not in path:
+                    path.append(num)
+                    backtrack(path, nums, result)
+                    path.pop()
+        
+        result = []
+        backtrack([], nums, result)
+        return result
+
+# Example Usage:
+solution = Solution()
+
+# Example 1:
+nums1 = [1,2,3]
+print(solution.permute(nums1))  # Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
+
+# Example 2:
+nums2 = [0,1]
+print(solution.permute(nums2))  # Output: [[0,1],[1,0]]
+
+# Example 3:
+nums3 = [1]
+print(solution.permute(nums3))  # Output: [[1]]
+```
+
+This code defines a `Solution` class with a `permute` method to generate all possible permutations of the given array `nums`. The example usage demonstrates how to create an instance of the `Solution` class and call the `permute` method with different inputs.
\ No newline at end of file
diff --git a/g0001_0100/s0048_rotate_image/readme.md b/g0001_0100/s0048_rotate_image/readme.md
new file mode 100644
index 0000000..476b4a5
--- /dev/null
+++ b/g0001_0100/s0048_rotate_image/readme.md
@@ -0,0 +1,106 @@
+48\. Rotate Image
+
+Medium
+
+You are given an `n x n` 2D `matrix` representing an image, rotate the image by **90** degrees (clockwise).
+
+You have to rotate the image [**in-place**](https://en.wikipedia.org/wiki/In-place_algorithm), which means you have to modify the input 2D matrix directly. **DO NOT** allocate another 2D matrix and do the rotation.
+
+**Example 1:**
+
+![](https://assets.leetcode.com/uploads/2020/08/28/mat1.jpg)
+
+**Input:** matrix = [[1,2,3],[4,5,6],[7,8,9]]
+
+**Output:** [[7,4,1],[8,5,2],[9,6,3]] 
+
+**Example 2:**
+
+![](https://assets.leetcode.com/uploads/2020/08/28/mat2.jpg)
+
+**Input:** matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
+
+**Output:** [[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]] 
+
+**Example 3:**
+
+**Input:** matrix = [[1]]
+
+**Output:** [[1]] 
+
+**Example 4:**
+
+**Input:** matrix = [[1,2],[3,4]]
+
+**Output:** [[3,1],[4,2]] 
+
+**Constraints:**
+
+*   `matrix.length == n`
+*   `matrix[i].length == n`
+*   `1 <= n <= 20`
+*   `-1000 <= matrix[i][j] <= 1000`
+
+To solve the "Rotate Image" problem, you can perform the rotation in-place by swapping elements of the matrix. Here are the steps to solve the problem:
+
+### Approach:
+
+1. **Transpose the Matrix:**
+   - Transpose the matrix by swapping `matrix[i][j]` with `matrix[j][i]` for all `i` and `j` where `i < j`.
+
+2. **Reverse Each Row:**
+   - Reverse each row of the transposed matrix to get the final rotated matrix.
+
+### Python Code:
+
+```python
+class Solution:
+    def rotate(self, matrix):
+        n = len(matrix)
+        
+        # Transpose the matrix
+        for i in range(n):
+            for j in range(i + 1, n):
+                matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
+        
+        # Reverse each row
+        for i in range(n):
+            matrix[i] = matrix[i][::-1]
+
+# Example Usage:
+solution = Solution()
+
+# Example 1:
+matrix1 = [
+    [1,2,3],
+    [4,5,6],
+    [7,8,9]
+]
+solution.rotate(matrix1)
+print(matrix1)  # Output: [[7,4,1],[8,5,2],[9,6,3]]
+
+# Example 2:
+matrix2 = [
+    [5,1,9,11],
+    [2,4,8,10],
+    [13,3,6,7],
+    [15,14,12,16]
+]
+solution.rotate(matrix2)
+print(matrix2)  # Output: [[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]
+
+# Example 3:
+matrix3 = [[1]]
+solution.rotate(matrix3)
+print(matrix3)  # Output: [[1]]
+
+# Example 4:
+matrix4 = [
+    [1,2],
+    [3,4]
+]
+solution.rotate(matrix4)
+print(matrix4)  # Output: [[3,1],[4,2]]
+```
+
+This code defines a `Solution` class with a `rotate` method to rotate the given matrix by 90 degrees clockwise. The example usage demonstrates how to create an instance of the `Solution` class and call the `rotate` method with different input matrices.
\ No newline at end of file
diff --git a/g0001_0100/s0049_group_anagrams/readme.md b/g0001_0100/s0049_group_anagrams/readme.md
new file mode 100644
index 0000000..1083406
--- /dev/null
+++ b/g0001_0100/s0049_group_anagrams/readme.md
@@ -0,0 +1,86 @@
+49\. Group Anagrams
+
+Medium
+
+Given an array of strings `strs`, group **the anagrams** together. You can 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:** strs = ["eat","tea","tan","ate","nat","bat"]
+
+**Output:** [["bat"],["nat","tan"],["ate","eat","tea"]] 
+
+**Example 2:**
+
+**Input:** strs = [""]
+
+**Output:** [[""]] 
+
+**Example 3:**
+
+**Input:** strs = ["a"]
+
+**Output:** [["a"]] 
+
+**Constraints:**
+
+*   <code>1 <= strs.length <= 10<sup>4</sup></code>
+*   `0 <= strs[i].length <= 100`
+*   `strs[i]` consists of lowercase English letters.
+
+To solve the "Group Anagrams" problem, you can use a hash table to group the anagrams together based on their sorted representations. Here are the steps to solve the problem:
+
+### Approach:
+
+1. **Initialize a Hash Table:**
+   - Initialize an empty dictionary to store the groups of anagrams. The keys of the dictionary will be the sorted representations of the words, and the values will be lists containing the original words.
+
+2. **Iterate Through the Strings:**
+   - Iterate through each string in the given array `strs`.
+
+3. **Sort Each String:**
+   - For each string, sort its characters alphabetically to get its sorted representation.
+
+4. **Group Anagrams:**
+   - Use the sorted representation as the key in the dictionary and append the original word to the corresponding list in the dictionary.
+
+5. **Return the Groups:**
+   - Return the values of the dictionary, which contain the groups of anagrams.
+
+### Python Code:
+
+```python
+from collections import defaultdict
+
+class Solution:
+    def groupAnagrams(self, strs):
+        # Initialize a dictionary to store groups of anagrams
+        groups = defaultdict(list)
+        
+        # Group anagrams based on their sorted representations
+        for word in strs:
+            sorted_word = ''.join(sorted(word))
+            groups[sorted_word].append(word)
+        
+        # Return the groups of anagrams
+        return list(groups.values())
+
+# Example Usage:
+solution = Solution()
+
+# Example 1:
+strs1 = ["eat","tea","tan","ate","nat","bat"]
+print(solution.groupAnagrams(strs1))  # Output: [["eat","tea","ate"],["tan","nat"],["bat"]]
+
+# Example 2:
+strs2 = [""]
+print(solution.groupAnagrams(strs2))  # Output: [[""]]
+
+# Example 3:
+strs3 = ["a"]
+print(solution.groupAnagrams(strs3))  # Output: [["a"]]
+```
+
+This code defines a `Solution` class with a `groupAnagrams` method to group the anagrams together. The example usage demonstrates how to create an instance of the `Solution` class and call the `groupAnagrams` method with different input arrays of strings.
\ No newline at end of file
diff --git a/g0001_0100/s0051_n_queens/readme.md b/g0001_0100/s0051_n_queens/readme.md
new file mode 100644
index 0000000..bc3bbbf
--- /dev/null
+++ b/g0001_0100/s0051_n_queens/readme.md
@@ -0,0 +1,99 @@
+51\. N-Queens
+
+Hard
+
+The **n-queens** puzzle is the problem of placing `n` queens on an `n x n` chessboard such that no two queens attack each other.
+
+Given an integer `n`, return _all distinct solutions to the **n-queens puzzle**_. You may return the answer in **any order**.
+
+Each solution contains a distinct board configuration of the n-queens' placement, where `'Q'` and `'.'` both indicate a queen and an empty space, respectively.
+
+**Example 1:**
+
+![](https://assets.leetcode.com/uploads/2020/11/13/queens.jpg)
+
+**Input:** n = 4
+
+**Output:** [[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
+
+**Explanation:** There exist two distinct solutions to the 4-queens puzzle as shown above 
+
+**Example 2:**
+
+**Input:** n = 1
+
+**Output:** [["Q"]] 
+
+**Constraints:**
+
+*   `1 <= n <= 9`
+
+To solve the N-Queens problem, which involves placing N queens on an N x N chessboard without attacking each other, you can use backtracking. Here are the steps to solve the problem:
+
+### Approach:
+
+1. **Initialize the Chessboard:**
+   - Initialize an empty N x N chessboard grid.
+
+2. **Backtracking Function:**
+   - Define a backtracking function to recursively explore all possible queen placements.
+
+3. **Base Case:**
+   - If all queens are placed (i.e., row index equals N), add the current configuration to the list of solutions.
+
+4. **Try Placing Queen:**
+   - For the current row, try placing the queen in each column (0 to N-1).
+   - If placing the queen at the current position is safe (i.e., not attacking any other queen), mark the cell as a queen ('Q') and recursively move to the next row.
+
+5. **Backtrack:**
+   - After exploring all possibilities from the current position, backtrack by removing the queen from the current position and try the next column.
+
+6. **Return Solutions:**
+   - Return the list of all distinct solutions found.
+
+### Python Code:
+
+```python
+class Solution:
+    def solveNQueens(self, n):
+        def is_safe(row, col):
+            # Check for queens in the same column
+            for i in range(row):
+                if board[i][col] == 'Q':
+                    return False
+            
+            # Check for queens in the upper-left diagonal
+            for i, j in zip(range(row-1, -1, -1), range(col-1, -1, -1)):
+                if board[i][j] == 'Q':
+                    return False
+            
+            # Check for queens in the upper-right diagonal
+            for i, j in zip(range(row-1, -1, -1), range(col+1, n)):
+                if board[i][j] == 'Q':
+                    return False
+            
+            return True
+        
+        def backtrack(row):
+            if row == n:
+                solutions.append([''.join(row) for row in board])
+                return
+            
+            for col in range(n):
+                if is_safe(row, col):
+                    board[row][col] = 'Q'
+                    backtrack(row + 1)
+                    board[row][col] = '.'
+        
+        board = [['.' for _ in range(n)] for _ in range(n)]
+        solutions = []
+        backtrack(0)
+        return solutions
+
+# Example Usage:
+solution = Solution()
+print(solution.solveNQueens(4))  # Output: [[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
+print(solution.solveNQueens(1))  # Output: [["Q"]]
+```
+
+This code defines a `Solution` class with a `solveNQueens` method to find all distinct solutions to the N-Queens puzzle. The example usage demonstrates how to create an instance of the `Solution` class and call the `solveNQueens` method with different values of `n`.
\ No newline at end of file
