Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions CPP/algorithms/arrays/Count_Distinct_Subarrays_Divisible_By_K.cpp
Original file line number Diff line number Diff line change
@@ -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 <bits/stdc++.h>
using namespace std;

class Solution {
public:
long long numGoodSubarrays(vector<int>& nums, int k) {
long long divisor = 1LL * k;
long long prefixSum = 0LL, resultCount = 0LL;
int n = nums.size();

map<int, int> 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<int> 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<int> 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;
}
88 changes: 88 additions & 0 deletions CPP/patterns/Pattern/NumberSpiral_CSES1071.cpp
Original file line number Diff line number Diff line change
@@ -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 <bits/stdc++.h>
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
*/