diff --git a/CPP/algorithms/arrays/Count_Distinct_Subarrays_Divisible_By_K.cpp b/CPP/algorithms/arrays/Count_Distinct_Subarrays_Divisible_By_K.cpp new file mode 100644 index 00000000..c18745f2 --- /dev/null +++ b/CPP/algorithms/arrays/Count_Distinct_Subarrays_Divisible_By_K.cpp @@ -0,0 +1,114 @@ +/* +Problem Name: Count Distinct Subarrays Divisible by K in Sorted Array +Problem Link: https://leetcode.com/problems/count-distinct-subarrays-divisible-by-k-in-sorted-array/ +Platform: LeetCode +Language: C++ +Author: Aditya Shimoga +Date: 30th October 2025 + +Description: +----------------------------------- +Given a sorted array nums and an integer k, find the number of distinct subarrays +whose sum is divisible by k. + +Key Insight: +----------------------------------- +- For any subarray [l, r], sum(l..r) is divisible by k ⇔ prefixSum[r] % k == prefixSum[l-1] % k. +- To count valid subarrays efficiently, we maintain a frequency map of prefix sums modulo k. +- Since the array is sorted and may contain repeated elements, we process contiguous "blocks" + of equal numbers separately. This ensures we don’t count identical subarrays multiple times. +- For each block: + 1. Calculate all valid subarrays ending in this block using prefix remainders from previous blocks. + 2. Update the remainder frequency map after processing the block. + +Complexity: +----------------------------------- +Time Complexity: O(N) +Space Complexity: O(K) , depending on distinct remainders +*/ + +#include +using namespace std; + +class Solution { +public: + long long numGoodSubarrays(vector& nums, int k) { + long long divisor = 1LL * k; + long long prefixSum = 0LL, resultCount = 0LL; + int n = nums.size(); + + map remainderFreq; // Tracks frequency of prefix sums modulo k + + int i = 0; + while (i < n) { + int j = i; + int currentValue = nums[i]; + long long tempPrefixSum = prefixSum; + + // Step 1: Count valid subarrays ending within the current block + while (j < n && nums[j] == currentValue) { + prefixSum += nums[j]; + int remainder = prefixSum % divisor; + + // Subarray from start (remainder == 0) + if (remainder == 0) resultCount++; + + // Subarray ending here matches an earlier prefix remainder + if (remainderFreq.count(remainder)) + resultCount += 1LL * remainderFreq[remainder]; + + j++; + } + + // Step 2: Update frequency map for this block + j = i; + while (j < n && nums[j] == currentValue) { + tempPrefixSum += nums[j]; + int remainder = tempPrefixSum % divisor; + remainderFreq[remainder]++; + j++; + } + + // Move to next distinct value block + i = j; + } + + return resultCount; + } +}; + +/* +Example: +Input: +nums = [1,1,2,2,3], k = 3 + +Output: +Number of distinct subarrays divisible by 3 = 4 + +Explanation: +Subarrays divisible 3: [3], [1,2], [1,1,2,2],[1,1,2,2,3] +*/ + +int main() { + Solution solver; + + // Test Case 1 + vector nums1 = {1, 1, 2, 2, 3}; + int k1 = 3; + long long result1 = solver.numGoodSubarrays(nums1, k1); + cout << "Test Case 1:" << endl; + cout << "Input: nums = [1,1,2,2,3], k = 3" << endl; + cout << "Output: " << result1 << endl; + cout << "Expected: 4" << endl << endl; + + // Test Case 2 + vector nums2 = {2, 2, 2, 4, 4}; + int k2 = 4; + long long result2 = solver.numGoodSubarrays(nums2, k2); + cout << "Test Case 2:" << endl; + cout << "Input: nums = [2,2,2,4,4], k = 4" << endl; + cout << "Output: " << result2 << endl; + cout << "Expected: 6" << endl; + + return 0; +} diff --git a/CPP/patterns/Pattern/NumberSpiral_CSES1071.cpp b/CPP/patterns/Pattern/NumberSpiral_CSES1071.cpp new file mode 100644 index 00000000..7beee062 --- /dev/null +++ b/CPP/patterns/Pattern/NumberSpiral_CSES1071.cpp @@ -0,0 +1,88 @@ +/* +Number Spiral (CSES Problem 1071) +Language: C++ +Problem Description: +You are given coordinates (y, x) in an infinite grid that forms a "number spiral". +The spiral starts at (1, 1) = 1 and moves right and upward in square layers. + +Your task: For each pair (y, x), determine the number located at that cell. + +Example (small spiral visualization): + + 1 2 9 10 25 + 4 3 8 11 24 + 5 6 7 12 23 + 16 15 14 13 22 + 17 18 19 20 21 + +So, for coordinate (y=2, x=3), the answer is 8. + +Algorithm: +1. Each layer corresponds to the maximum of x and y. +2. The square of (layer - 1) gives the value before the current layer starts. +3. Depending on whether the layer number is even or odd: + - Even layer → spiral moves upward. + - Odd layer → spiral moves rightward. +4. Using conditional formulas, compute the number directly in O(1). + +Time Complexity: O(1) +Space Complexity: O(1) +*/ + +#include +using namespace std; + +/* +solve(x, y) +Computes the value at coordinates (y, x) in the number spiral. + +Parameters: +x -> Column index (1-based) +y -> Row index (1-based) + +Returns: +The number located at position (y, x) +*/ +long long solve(long long x, long long y) { + if (x == 1LL && y == 1LL) return 1LL; + + // Layer = max(x, y) + long long layer = max(x, y) - 1LL; + long long baseValue = layer * layer; // Value before this layer starts + + // Even layer → starts bottom-right, moves upward + // Odd layer → starts top-left, moves rightward + if (layer % 2LL == 0LL) { + if (y == layer + 1LL) + return baseValue + x; // On bottom row of even layer + else + return baseValue + x + layer + 1LL - y; // Moving upward + } else { + if (x == layer + 1LL) + return baseValue + y; // On right column of odd layer + else + return baseValue + y + layer + 1LL - x; // Moving leftward + } +} + +int main() { + + // Example test cases for verification + cout << "Example Test Cases:" << endl; + + cout << "Test 1 -> y=2, x=3 | Expected: 8 | Got: " << solve(3, 2) << endl; + cout << "Test 2 -> y=1, x=1 | Expected: 1 | Got: " << solve(1, 1) << endl; + cout << "Test 3 -> y=4, x=2 | Expected: 15 | Got: " << solve(2, 4) << endl; + cout << "Test 4 -> y=5, x=5 | Expected: 21 | Got: " << solve(5, 5) << endl; + + return 0; +} + +/* +Expected Output: +Example Test Cases: +Test 1 -> y=2, x=3 | Expected: 8 | Got: 8 +Test 2 -> y=1, x=1 | Expected: 1 | Got: 1 +Test 3 -> y=4, x=2 | Expected: 15 | Got: 15 +Test 4 -> y=5, x=5 | Expected: 21 | Got: 21 +*/