diff --git a/README.md b/README.md index 116bff6..4086f0a 100644 --- a/README.md +++ b/README.md @@ -32,13 +32,15 @@ If you find this repo helpful, please consider giving it a star 🌟 to show you [008. pair product](https://github.com/MoigeMatino/structy.net/tree/main/arrays_and_strings/pair_product) [009. intersection](https://github.com/MoigeMatino/structy.net/tree/main/arrays_and_strings/intersection) [010. five sort](https://github.com/MoigeMatino/structy.net/tree/main/arrays_and_strings/five_sort) -[BONUS: sum of three values](https://github.com/MoigeMatino/Data-Structures-Algorithms-Python/tree/main/arrays_and_strings/sum_of_three_values) [BONUS: three sum](https://github.com/MoigeMatino/Data-Structures-Algorithms-Python/tree/main/arrays_and_strings/three_sum) -[BONUS: longest palindrome](https://github.com/MoigeMatino/Data-Structures-Algorithms-Python/tree/main/arrays_and_strings/longest_palindrome) +[BONUS: happy number](https://github.com/MoigeMatino/data-structures-algorithms-python/tree/main/arrays_and_strings/happy_number) +[BONUS: first bad version](https://github.com/MoigeMatino/data-structures-algorithms-python/tree/main/arrays_and_strings/first_bad_version) [BONUS: circular array loop](https://github.com/MoigeMatino/data-structures-algorithms-python/tree/main/arrays_and_strings/circular_array_loop) +[BONUS: longest palindrome](https://github.com/MoigeMatino/Data-Structures-Algorithms-Python/tree/main/arrays_and_strings/longest_palindrome) +[BONUS: sum of three values](https://github.com/MoigeMatino/Data-Structures-Algorithms-Python/tree/main/arrays_and_strings/sum_of_three_values) [BONUS: find duplicate number](https://github.com/MoigeMatino/data-structures-algorithms-python/tree/main/arrays_and_strings/find_duplicate_number) -[BONUS: first bad version](https://github.com/MoigeMatino/data-structures-algorithms-python/tree/main/arrays_and_strings/first_bad_version) [BONUS: container with most water](https://github.com/MoigeMatino/data-structures-algorithms-python/tree/main/arrays_and_strings/container_with_most_water) +[BONUS: search rotated sorted array](https://github.com/MoigeMatino/data-structures-algorithms-python/tree/main/arrays_and_strings/search_rotated_sorted_array) ## 2. Linked Lists diff --git a/arrays_and_strings/search_rotated_sorted_array/README.md b/arrays_and_strings/search_rotated_sorted_array/README.md new file mode 100644 index 0000000..75f32df --- /dev/null +++ b/arrays_and_strings/search_rotated_sorted_array/README.md @@ -0,0 +1,92 @@ +## **Problem Statement** + +Given a sorted integer array, `nums`, and an integer value, `target`, the array is rotated by some arbitrary number. Search and return the index of `target` in this array. If the `target` does not exist, return `-1`. + + +### Constraints +- All values in nums are unique. +- The values in nums are sorted in ascending order. +- The array may have been rotated by some arbitrary number. +- 1 ≤ nums.length ≤1000≤1000 +- −104 ≤ nums[i] ≤ 104 +- −104 ≤ target ≤ 104 + +## **Examples** + +### Example 1: Target Found in Rotated Array + +**Input:** + +- `nums = [4, 5, 6, 7, 0, 1, 2]` +- `target = 0` + +**Process:** +- The array `[4, 5, 6, 7, 0, 1, 2]` is a sorted array that has been rotated. +- The target value `0` is located at index `4`. + +**Output:** `4` + +**Visualization:** +- Original Sorted Array: [0, 1, 2, 4, 5, 6, 7] +- Rotated Array: [4, 5, 6, 7, 0, 1, 2] +- Target: 0 +- Index of Target: 4 + +### Example 2: Target Not Found + +**Input:** +- `nums = [4, 5, 6, 7, 0, 1, 2]` +- `target = 3` + +**Process:** +- The array `[4, 5, 6, 7, 0, 1, 2]` is a sorted array that has been rotated. +- The target value `3` is not present in the array. + +**Output:** `-1` + +**Visualization:** + +Original Sorted Array: [0, 1, 2, 4, 5, 6, 7] +Rotated Array: [4, 5, 6, 7, 0, 1, 2] +Target: 3 +Index of Target: -1 (not found) + + +### Example 3: Target Found at Beginning + +**Input:** +- `nums = [6, 7, 0, 1, 2, 4, 5]` +- `target = 6` + +**Process:** +- The array `[6, 7, 0, 1, 2, 4, 5]` is a sorted array that has been rotated. +- The target value `6` is located at index `0`. + +**Output:** `0` + +**Visualization:** + +- Original Sorted Array: [0, 1, 2, 4, 5, 6, 7] +- Rotated Array: [6, 7, 0, 1, 2, 4, 5] +- Target: 6 +- Index of Target: 0 + + +### Example 4: Target Found at End + +**Input:** +- `nums = [6, 7, 0, 1, 2, 4, 5]` +- `target = 5` + +**Process:** +- The array `[6, 7, 0, 1, 2, 4, 5]` is a sorted array that has been rotated. +- The target value `5` is located at index `6`. + +**Output:** `6` + +**Visualization:** + +- Original Sorted Array: [0, 1, 2, 4, 5, 6, 7] +- Rotated Array: [6, 7, 0, 1, 2, 4, 5] +- Target: 5 +- Index of Target: 6 \ No newline at end of file diff --git a/arrays_and_strings/search_rotated_sorted_array/__init__.py b/arrays_and_strings/search_rotated_sorted_array/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/arrays_and_strings/search_rotated_sorted_array/search_rotated_sorted_array_v1.py b/arrays_and_strings/search_rotated_sorted_array/search_rotated_sorted_array_v1.py new file mode 100644 index 0000000..8883d99 --- /dev/null +++ b/arrays_and_strings/search_rotated_sorted_array/search_rotated_sorted_array_v1.py @@ -0,0 +1,55 @@ +def search_rotated_sorted_array(nums: list[int], target: int) -> int: + """ + Search for a target value in a rotated sorted array using an iterative binary search. + + Parameters: + nums (list[int]): The rotated sorted array. + target (int): The target value to search for. + + Returns: + int: The index of the target if found, otherwise -1. + + """ + low = 0 + high = len(nums) - 1 + + while low <= high: + mid = low + (high - low) // 2 + + # Check if the mid element is the target + if nums[mid] == target: + return mid + + # Determine if the left half is sorted + if nums[low] <= nums[mid]: + # Check if the target is in the sorted left half + if nums[low] <= target <= nums[mid]: + high = mid - 1 + else: + low = mid + 1 + else: + # Check if the target is in the sorted right half + if nums[mid] <= target <= nums[high]: + low = mid + 1 + else: + high = mid - 1 + + # Target not found + return -1 + +# Approach and Rationale: +# ----------------------- +# - This function uses an iterative binary search approach to find the target in a rotated sorted array. +# - A rotated sorted array is an array that was originally sorted in increasing order but then rotated at some pivot. +# - The key observation is that at least one half of the array (either left or right of the midpoint) is always sorted. +# - By comparing the target with the elements in the sorted half, we can decide which half to continue searching in. +# - This approach reduces the search space by half in each iteration, similar to binary search. + +# Time Complexity: +# ---------------- +# - The time complexity is O(log n), where n is the number of elements in the array. +# - This is because the search space is halved in each iteration, similar to binary search. + +# Space Complexity: +# ----------------- +# - The space complexity is O(1) because the algorithm uses a constant amount of extra space. diff --git a/arrays_and_strings/search_rotated_sorted_array/search_rotated_sorted_array_v2.py b/arrays_and_strings/search_rotated_sorted_array/search_rotated_sorted_array_v2.py new file mode 100644 index 0000000..71fc2f6 --- /dev/null +++ b/arrays_and_strings/search_rotated_sorted_array/search_rotated_sorted_array_v2.py @@ -0,0 +1,53 @@ +def search_rotated_sorted_array(nums: list[int], low: int, high: int, target: int) -> int: + """ + Search for a target value in a rotated sorted array using a modified binary search. + + Parameters: + nums (list[int]): The rotated sorted array. + low (int): The starting index of the search range. + high (int): The ending index of the search range. + target (int): The target value to search for. + + Returns: + int: True if the target is found, False otherwise. + + """ + if low >= high: + return False + + mid = low + (high - low) // 2 + + if nums[mid] == target: + return True + + # Check if the left half is sorted + if nums[low] <= nums[mid]: + # If target is in the sorted left half + if nums[low] <= target <= nums[mid]: + return search_rotated_sorted_array(nums, low, mid - 1, target) + else: + return search_rotated_sorted_array(nums, mid + 1, high, target) + else: + # If target is in the sorted right half + if nums[mid] <= target <= nums[high]: + return search_rotated_sorted_array(nums, mid + 1, high, target) + else: + return search_rotated_sorted_array(nums, low, mid - 1, target) + +# Approach and Rationale: +# ----------------------- +# - The function uses a recursive binary search approach to find the target in a rotated sorted array. +# - A rotated sorted array is an array that was originally sorted in increasing order but then rotated at some pivot. +# - The key observation is that at least one half of the array (either left or right of the midpoint) is always sorted. +# - By comparing the target with the elements in the sorted half, we can decide which half to continue searching in. +# - This approach reduces the search space by half in each recursive call, similar to binary search. + +# Time Complexity: +# ---------------- +# - The time complexity is O(log n), where n is the number of elements in the array. +# - This is because the search space is halved in each recursive call, similar to binary search. + +# Space Complexity: +# ----------------- +# - The space complexity is O(log n) due to the recursive call stack. +# - Each recursive call adds a new layer to the call stack, and the maximum depth of recursion is proportional to log n. diff --git a/arrays_and_strings/three_sum/three_sum.py b/arrays_and_strings/three_sum/three_sum.py index 5109c11..65a048d 100644 --- a/arrays_and_strings/three_sum/three_sum.py +++ b/arrays_and_strings/three_sum/three_sum.py @@ -34,7 +34,7 @@ def three_sum(nums: List[int]) -> List[List[int]]: # If the sum is zero, append the triplet to the result and skip duplicates if current_sum == 0: - triplets.append([nums[i], nums[low], nums[high]]) + triplets.append(([nums[i], nums[low], nums[high])) # Skip duplicates of the low pointer to avoid redundant triplets while low < high and nums[low] == nums[low + 1]: low += 1 diff --git a/linked_lists/palindrome_linked_list/palindrome_linked_list.py b/linked_lists/palindrome_linked_list/palindrome_linked_list.py index 1aad907..2a12780 100644 --- a/linked_lists/palindrome_linked_list/palindrome_linked_list.py +++ b/linked_lists/palindrome_linked_list/palindrome_linked_list.py @@ -81,8 +81,16 @@ def compare_halfs(head1, head2): # The algorithm uses a constant amount of extra space. It only uses a few pointer variables and does not require # any additional data structures that depend on the size of the input list. +# Considerations: +# Since a palindrome reads the same forward and backward, an intuitive way to solve this problem is to use two pointers—one placed at the beginning and +# the other at the end. These pointers move toward the center, comparing the values at each step. While this approach is intuitive, it poses challenges +# when working with singly linked lists. Singly linked lists only have the next pointers, so moving from the end toward the center requires additional steps. +# To overcome this limitation, we solve this problem in three key steps: , , and If both halves of the list match, the linked list is a palindrome. +# Here, reversing half the linked list allows us to use only the next pointers for comparison. + # Approach: # 1. Use the two-pointer technique to find the middle of the linked list. # 2. Reverse the second half of the list. # 3. Compare the first half and the reversed second half to check for palindrome properties. -# This approach efficiently determines if the list is a palindrome without using extra space for storing values. \ No newline at end of file +# This approach efficiently determines if the list is a palindrome without using extra space for storing values. +