diff --git a/3sum/sounmind.js b/3sum/sounmind.js deleted file mode 100644 index 72530da0c..000000000 --- a/3sum/sounmind.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @param {number[]} nums - * @return {number[][]} - */ -var threeSum = function (nums) { - const sorted = nums.sort((a, b) => a - b); - const result = []; - - for (let i = 0; i < sorted.length; i++) { - const fixedNumber = sorted[i]; - const previousFixedNumber = sorted[i - 1]; - - if (fixedNumber === previousFixedNumber) { - continue; - } - - let [leftEnd, rightEnd] = [i + 1, sorted.length - 1]; - - while (leftEnd < rightEnd) { - const sum = fixedNumber + sorted[leftEnd] + sorted[rightEnd]; - - if (sum === 0) { - result.push([sorted[leftEnd], sorted[rightEnd], sorted[i]]); - - while ( - sorted[leftEnd + 1] === sorted[leftEnd] || - sorted[rightEnd - 1] === sorted[rightEnd] - ) { - if (sorted[leftEnd + 1] === sorted[leftEnd]) { - leftEnd += 1; - } - - if (sorted[rightEnd - 1] === sorted[rightEnd]) { - rightEnd -= 1; - } - } - - leftEnd += 1; - rightEnd -= 1; - } else if (sum < 0) { - leftEnd += 1; - } else { - rightEnd -= 1; - } - } - } - - return result; -}; - -/** - * Time Complexity: O(n^2) - * The algorithm involves sorting the input array, which takes O(n log n) time. - * The main part of the algorithm consists of a loop that runs O(n) times, and within that loop, there is a two-pointer technique that runs in O(n) time. - * Thus, the overall time complexity is O(n log n) + O(n^2), which simplifies to O(n^2). - * - * Space Complexity: O(n) - * The space complexity is O(n) due to the space needed for the sorted array and the result array. - * Although the sorting algorithm may require additional space, typically O(log n) for the in-place sort in JavaScript, the dominant term is O(n) for the result storage. - */ diff --git a/3sum/sounmind.py b/3sum/sounmind.py new file mode 100644 index 000000000..68ad78f21 --- /dev/null +++ b/3sum/sounmind.py @@ -0,0 +1,51 @@ +from typing import List + + +class Solution: + def threeSum(self, nums: List[int]) -> List[List[int]]: + zero_sum_triplets = [] + nums.sort() # Sort to handle duplicates and enable two-pointer approach + + for first_index in range(len(nums) - 2): + # Skip duplicate values for the first position + if first_index > 0 and nums[first_index] == nums[first_index - 1]: + continue + + # Use two-pointer technique to find complementary pairs + second_index = first_index + 1 + third_index = len(nums) - 1 + + while second_index < third_index: + current_sum = nums[first_index] + nums[second_index] + nums[third_index] + + if current_sum == 0: + # Found a valid triplet + zero_sum_triplets.append( + [nums[first_index], nums[second_index], nums[third_index]] + ) + + # Skip duplicates for second and third positions + while ( + second_index < third_index + and nums[second_index] == nums[second_index + 1] + ): + second_index += 1 + while ( + second_index < third_index + and nums[third_index] == nums[third_index - 1] + ): + third_index -= 1 + + # Move both pointers inward + # (In a balanced state where sum=0, moving only one pointer would unbalance it) + second_index += 1 + third_index -= 1 + + elif current_sum < 0: + # Current sum is too small, need a larger value + second_index += 1 + else: + # Current sum is too large, need a smaller value + third_index -= 1 + + return zero_sum_triplets diff --git a/climbing-stairs/sounmind.js b/climbing-stairs/sounmind.js deleted file mode 100644 index 100275ff7..000000000 --- a/climbing-stairs/sounmind.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -var climbStairs = function (n) { - if (n <= 2) { - return n; - } - - let [firstStair, secondStair] = [1, 2]; - let thirdStair; - - for (let i = 3; i <= n; i++) { - thirdStair = firstStair + secondStair; - - [firstStair, secondStair] = [secondStair, thirdStair]; - } - - return thirdStair; -}; - -// Time Complexity: O(n) -// Reason: The function uses a loop that iterates from 3 to n, -// which means it runs in linear time with respect to n. - -// Space Complexity: O(1) -// Reason: The function uses a fixed amount of extra space -// (a few integer variables: first, second, and third). -// It does not use any additional data structures -// that grow with the input size n. diff --git a/climbing-stairs/sounmind.py b/climbing-stairs/sounmind.py new file mode 100644 index 000000000..db649a1b4 --- /dev/null +++ b/climbing-stairs/sounmind.py @@ -0,0 +1,51 @@ +class Solution: + def climbStairs(self, n: int) -> int: + """ + Climbing Stairs Problem: You are climbing a staircase with n steps. + Each time you can either climb 1 or 2 steps. How many distinct ways can you climb to the top? + + This is essentially a Fibonacci sequence problem: + - To reach step n, you can either: + 1. Take a single step from step (n-1) + 2. Take a double step from step (n-2) + - Therefore, the total ways to reach step n = ways to reach (n-1) + ways to reach (n-2) + + Time Complexity: O(n) - We need to calculate each step once + Space Complexity: O(1) - We only store two previous values regardless of input size + """ + # Base cases: There's only 1 way to climb 1 step and 2 ways to climb 2 steps + if n == 1: + return 1 + if n == 2: + return 2 + + # Initialize variables with base cases + # For staircase with 1 step, there's only 1 way to climb + ways_to_reach_n_minus_2 = 1 + + # For staircase with 2 steps, there are 2 ways to climb (1+1 or 2) + ways_to_reach_n_minus_1 = 2 + + # Variable to store the current calculation + ways_to_reach_current_step = 0 + + # Start calculating from step 3 up to step n + for _ in range(3, n + 1): + # To reach current step, we can either: + # 1. Take a single step after reaching step (n-1) + # 2. Take a double step after reaching step (n-2) + # So the total ways = ways to reach (n-1) + ways to reach (n-2) + ways_to_reach_current_step = ( + ways_to_reach_n_minus_1 + ways_to_reach_n_minus_2 + ) + + # Shift our window of calculations forward: + # The previous (n-1) step now becomes the (n-2) step for the next iteration + ways_to_reach_n_minus_2 = ways_to_reach_n_minus_1 + + # The current step calculation becomes the (n-1) step for the next iteration + ways_to_reach_n_minus_1 = ways_to_reach_current_step + + # After the final iteration, both ways_to_reach_n_minus_1 and ways_to_reach_current_step + # have the same value (the answer for step n) + return ways_to_reach_n_minus_1 # Could also return ways_to_reach_current_step diff --git a/product-of-array-except-self/sounmind.js b/product-of-array-except-self/sounmind.js deleted file mode 100644 index ee8289f9d..000000000 --- a/product-of-array-except-self/sounmind.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @param {number[]} nums - * @return {number[]} - */ -var productExceptSelf = function (nums) { - const length = nums.length; - const result = Array(length).fill(1); - - let leftProduct = 1; - for (let i = 0; i < length; i++) { - result[i] = leftProduct; - leftProduct *= nums[i]; - } - - let rightProduct = 1; - for (let i = length - 1; i >= 0; i--) { - result[i] *= rightProduct; - rightProduct *= nums[i]; - } - - return result; -}; - -/** - * Time Complexity: O(n) - * The algorithm iterates through the nums array twice (two separate loops), each taking O(n) time. - * Hence, the overall time complexity is O(2n), which simplifies to O(n). - * - * Space Complexity: O(1) - * The algorithm uses a constant amount of extra space for the leftProduct and rightProduct variables. - * The result array is not considered extra space as it is required for the output. - * Therefore, the extra space complexity is O(1). - */ diff --git a/product-of-array-except-self/sounmind.py b/product-of-array-except-self/sounmind.py new file mode 100644 index 000000000..62db12e59 --- /dev/null +++ b/product-of-array-except-self/sounmind.py @@ -0,0 +1,21 @@ +from typing import List + + +class Solution: + def productExceptSelf(self, nums: List[int]) -> List[int]: + array_length = len(nums) + products_except_self = [1] * array_length + + # First pass: multiply by all elements to the left + left_product = 1 + for i in range(array_length): + products_except_self[i] = left_product + left_product *= nums[i] + + # Second pass: multiply by all elements to the right + right_product = 1 + for i in range(array_length - 1, -1, -1): + products_except_self[i] *= right_product + right_product *= nums[i] + + return products_except_self