diff --git a/leetcode/maximum_product_of_three_numbers/maximum_product_of_three_numbers.py b/leetcode/maximum_product_of_three_numbers/maximum_product_of_three_numbers.py new file mode 100644 index 0000000..7bdab56 --- /dev/null +++ b/leetcode/maximum_product_of_three_numbers/maximum_product_of_three_numbers.py @@ -0,0 +1,33 @@ +from typing import List + + +class Solution: + def maximumProduct(self, nums: List[int]) -> int: + """ + 628. Maximum Product of Three Numbers + + After sorting, the max product of three numbers is the larger of: + 1) three largest values (all positive, or least-negative if all negative) + 2) two smallest (most negative) * largest (neg*neg*pos can dominate) + + Time: O(n log n) + Space: O(1) extra if sort is in-place (O(n) depending on sort impl) + """ + nums.sort() + return max( + nums[-1] * nums[-2] * nums[-3], + nums[0] * nums[1] * nums[-1], + ) + + +if __name__ == "__main__": + s = Solution() + assert s.maximumProduct([1, 2, 3]) == 6 + assert s.maximumProduct([1, 2, 3, 4]) == 24 + assert s.maximumProduct([-1, -2, -3]) == -6 + assert s.maximumProduct([-4, -3, -2, -1, 60]) == 720 + assert s.maximumProduct([-100, -98, -1, 2, 3, 4]) == 39200 + assert s.maximumProduct([-1, -2, 1, 2, 3]) == 6 + assert s.maximumProduct([0, 0, 0]) == 0 + assert s.maximumProduct([-5, 0, 1, 2]) == 0 + print("ok") diff --git a/leetcode/maximum_product_of_two_elements_in_an_array/maximum_product_of_two_elements_in_an_array.py b/leetcode/maximum_product_of_two_elements_in_an_array/maximum_product_of_two_elements_in_an_array.py new file mode 100644 index 0000000..65fa24c --- /dev/null +++ b/leetcode/maximum_product_of_two_elements_in_an_array/maximum_product_of_two_elements_in_an_array.py @@ -0,0 +1,13 @@ +from typing import List + + +class Solution: + def maxProduct(self, nums: List[int]) -> int: + # (a-1)*(b-1) is maximized by the two largest values (nums[i] >= 1). + max1 = max2 = 0 + for num in nums: + if num > max1: + max2, max1 = max1, num + elif num > max2: + max2 = num + return (max1 - 1) * (max2 - 1) diff --git a/leetcode/number_of_unique_xor_triplets_ii/number_of_unique_xor_triplets_ii.py b/leetcode/number_of_unique_xor_triplets_ii/number_of_unique_xor_triplets_ii.py new file mode 100644 index 0000000..622e1c6 --- /dev/null +++ b/leetcode/number_of_unique_xor_triplets_ii/number_of_unique_xor_triplets_ii.py @@ -0,0 +1,35 @@ +from typing import List + + +class Solution: + def uniqueXorTriplets(self, nums: List[int]) -> int: + """ + Count distinct values of nums[i] ^ nums[j] ^ nums[k] over i <= j <= k. + + Key insight: index reuse (i==j or j==k) only produces values already in + the array. Every triple of values (a, b, c) from the distinct set U is + achievable, so the answer is |{a ^ b ^ c : a, b, c in U}|. + + nums[i] <= 1500 => XOR results fit in [0, 2047]. Build all pairwise XORs, + then XOR each with every value in U. + """ + # Presence of values; range is small + present = [False] * 2048 + for x in nums: + present[x] = True + vals = [x for x in range(2048) if present[x]] + + # All pairwise XORs a ^ b for a, b in U (includes a ^ a == 0) + pair = [False] * 2048 + for i, a in enumerate(vals): + for b in vals[i:]: + pair[a ^ b] = True + pair_vals = [x for x in range(2048) if pair[x]] + + # All triple XORs (a ^ b) ^ c + trip = [False] * 2048 + for p in pair_vals: + for c in vals: + trip[p ^ c] = True + + return sum(trip) diff --git a/leetcode/shift_2d_grid/shift_2d_grid.py b/leetcode/shift_2d_grid/shift_2d_grid.py new file mode 100644 index 0000000..d82c177 --- /dev/null +++ b/leetcode/shift_2d_grid/shift_2d_grid.py @@ -0,0 +1,54 @@ +from typing import List + + +class Solution: + def shiftGrid(self, grid: List[List[int]], k: int) -> List[List[int]]: + """ + 1260. Shift 2D Grid + + Treat the m x n grid as a flattened 1D array of length m*n. + One shift is a right-rotate by 1 in that array (last -> first). + After k shifts, element at flat index i moves to (i + k) % (m*n). + + Time: O(m * n) + Space: O(m * n) for the result + """ + m, n = len(grid), len(grid[0]) + total = m * n + k %= total + ans = [[0] * n for _ in range(m)] + for i in range(m): + for j in range(n): + ni, nj = divmod((i * n + j + k) % total, n) + ans[ni][nj] = grid[i][j] + return ans + + +if __name__ == "__main__": + s = Solution() + assert s.shiftGrid([[1, 2, 3], [4, 5, 6], [7, 8, 9]], 1) == [ + [9, 1, 2], + [3, 4, 5], + [6, 7, 8], + ] + assert s.shiftGrid([[3, 8, 1, 9], [19, 7, 2, 5], [4, 6, 11, 10], [12, 0, 21, 13]], 4) == [ + [12, 0, 21, 13], + [3, 8, 1, 9], + [19, 7, 2, 5], + [4, 6, 11, 10], + ] + assert s.shiftGrid([[1, 2, 3], [4, 5, 6], [7, 8, 9]], 9) == [ + [1, 2, 3], + [4, 5, 6], + [7, 8, 9], + ] + assert s.shiftGrid([[1], [2], [3], [4], [5], [6], [7]], 23) == [ + [6], + [7], + [1], + [2], + [3], + [4], + [5], + ] + print("ok")