Print All Distinct Elements in an Array in C
Three C programs to print all distinct elements in an array: nested-loop O(N²), sorting, and count-array, with complexity trade-offs and placement interview tips.
Printing distinct elements from a C array appears in AMCAT and CoCubes coding rounds; three approaches cover the full range of difficulty, from simple nested loops to O(N) count arrays.
All three are worth knowing. The nested-loop O(N²) is the easiest to explain in an interview. Sorting O(N log N) is the general-purpose choice. Count-array O(N) is the fastest option when values are non-negative integers in a bounded range.
What does “distinct” mean here?
Two definitions appear in placement resources, and confusing them costs marks.
The standard definition: print each unique value exactly once, regardless of how many times it appears in the input. For input [2, 3, 4, 5, 6, 1, 2, 3, 4], output is 2 3 4 5 6 1 (each value once, in insertion order).
The stricter definition: print only values with frequency exactly 1. Same input, output 5 6 1 (values 2, 3, and 4 appear more than once, so they are excluded). Legacy code from older placement prep sites often implements this stricter version, and the output differs from standard deduplication.
Verification from first principles for the stricter variant, input [2, 3, 4, 5, 6, 1, 2, 3, 4]:
- value 1 appears at index 5 only — frequency 1, print
- value 2 appears at indices 0 and 6 — frequency 2, skip
- value 3 appears at indices 1 and 7 — frequency 2, skip
- value 4 appears at indices 2 and 8 — frequency 2, skip
- value 5 appears at index 3 only — frequency 1, print
- value 6 appears at index 4 only — frequency 1, print
- Stricter output:
5 6 1
This article focuses on the standard deduplication problem across three C approaches. The count-array code in Approach 3 shows a one-line change to produce the stricter frequency-1 variant.
Approach 1: Nested loops — O(N²) time, O(1) space
For each element at position i, scan all positions before it. If the same value already appeared, skip; otherwise print. This preserves insertion order.
#include <stdio.h>
void printDistinct(int arr[], int n) {
for (int i = 0; i < n; i++) {
int alreadySeen = 0;
for (int j = 0; j < i; j++) {
if (arr[j] == arr[i]) {
alreadySeen = 1;
break;
}
}
if (!alreadySeen) {
printf("%d ", arr[i]);
}
}
printf("\n");
}
int main() {
int arr[] = {2, 3, 4, 5, 6, 1, 2, 3, 4};
int n = sizeof(arr) / sizeof(arr[0]);
printDistinct(arr, n);
return 0;
}
Output: 2 3 4 5 6 1
Trace for the value 2:
- At index 0: inner loop runs 0 times (no preceding elements), not seen, prints
2. - At index 6: inner loop checks indices 0 through 5, finds
arr[0] == 2, setsalreadySeen = 1, skips.
Time: O(N²) because the outer loop runs N times and the inner loop runs up to N-1 times each. Space: O(1) because no extra memory is allocated.
This nested-traversal pattern appears in sibling problems such as finding symmetric pairs in an array and finding the equilibrium index, where one pass depends on the position of another.
Approach 2: Sort then scan — O(N log N) time, O(1) space
Sort the array first, then walk through it once. Whenever a value differs from the previous one, print it. Sorting uses the C standard library qsort from <stdlib.h>.
#include <stdio.h>
#include <stdlib.h>
int compare(const void *a, const void *b) {
return (*(int *)a - *(int *)b);
}
void printDistinctSorted(int arr[], int n) {
qsort(arr, n, sizeof(int), compare);
printf("%d ", arr[0]);
for (int i = 1; i < n; i++) {
if (arr[i] != arr[i - 1]) {
printf("%d ", arr[i]);
}
}
printf("\n");
}
int main() {
int arr[] = {2, 3, 4, 5, 6, 1, 2, 3, 4};
int n = sizeof(arr) / sizeof(arr[0]);
printDistinctSorted(arr, n);
return 0;
}
Output: 1 2 3 4 5 6
After sorting, the array becomes [1, 2, 2, 3, 3, 4, 4, 5, 6]. Print arr[0] = 1. Then: arr[1]=2 differs from arr[0]=1, print 2; arr[2]=2 equals arr[1]=2, skip; arr[3]=3 differs from arr[2]=2, print 3; and so on. Output is in ascending order, not insertion order. If preserving the original sequence is a requirement, this approach does not qualify.
Time: O(N log N) dominated by qsort. Space: O(1) extra because sorting is in-place.
Approach 3: Count array — O(N) time, O(K) space
For non-negative integers in a known range [0, MAX], allocate a frequency array of size MAX + 1, mark which values appear, then print every index with a non-zero count. This is a read-only variant of the counting sort algorithm.
#include <stdio.h>
#include <string.h>
#define MAX_VAL 999
void printDistinctCount(int arr[], int n) {
int freq[MAX_VAL + 1];
memset(freq, 0, sizeof(freq));
for (int i = 0; i < n; i++) {
if (arr[i] >= 0 && arr[i] <= MAX_VAL) {
freq[arr[i]]++;
}
}
for (int i = 0; i <= MAX_VAL; i++) {
if (freq[i] > 0) {
printf("%d ", i);
}
}
printf("\n");
}
int main() {
int arr[] = {2, 3, 4, 5, 6, 1, 2, 3, 4};
int n = sizeof(arr) / sizeof(arr[0]);
printDistinctCount(arr, n);
return 0;
}
Output: 1 2 3 4 5 6
Frequency array after the first loop:
freq[1] = 1,freq[2] = 2,freq[3] = 2,freq[4] = 2,freq[5] = 1,freq[6] = 1, all others zero.
Every index with a count above zero prints, so output is in ascending order.
To get the frequency-1 (stricter) variant, change if (freq[i] > 0) to if (freq[i] == 1). Output becomes 1 5 6.
Space: O(K) where K is MAX_VAL + 1. For the space complexity comparison across all three approaches, see the table below. The trade-off is clear: O(K) extra memory in exchange for a linear-time scan.
The index-marking technique here is structurally similar to the pattern in replacing all 0s in an integer, where positions are flagged during one pass before a second pass acts on them.
Complexity comparison
| Approach | Time | Space | Preserves insertion order |
|---|---|---|---|
| Nested loops | O(N²) | O(1) | Yes |
| Sort then scan | O(N log N) | O(1) | No — ascending order |
| Count array | O(N) | O(K), K = value range | No — ascending order |
For small arrays (N below 50), all three complete in under a millisecond and the difference is irrelevant. As N grows, the nested-loop approach does quadratically more work: at N = 5000, the nested-loop runs roughly 25 million inner-loop comparisons, while the count-array runs one linear pass.
The count-array has a different constraint: if MAX_VAL is large (say, values up to 10 million), the frequency array consumes significant memory. For arrays with a wide or unbounded value range, the sorting approach is the better default.
Placement interview context
Distinct-elements questions test three skills: array traversal, duplicate detection, and knowing your time-space trade-off before being asked. These appear in AMCAT coding sections and CoCubes assessments for CSE and IT roles at companies like Wipro, TCS, Cognizant, and Capgemini.
The expected interview flow:
- Write and run Approach 1 (nested loops) first. It is the safest choice under time pressure.
- State the time complexity aloud: “This is O(N²) because of the nested loops.”
- If the interviewer asks to optimise, offer Approach 3 for bounded inputs or Approach 2 for general inputs.
- Explain the order trade-off: “Sorting changes the output order; if you need insertion-order output, the nested-loop version is required.”
That exchange (writing a correct solution, stating its complexity, then offering a structured optimisation) is what separates strong candidates from average ones in screening rounds.
The same logic-first discipline matters when working with AI tools. Knowing which algorithm to reach for (and why) before coding is exactly the habit that carries into prompting and building with language model APIs. If you want to explore that side of engineering, TinkerLLM is a practical starting point at ₹299; the array-thinking discipline this article covers applies directly to working with AI components.
Primary sources
Frequently asked questions
What is the difference between distinct and unique elements in an array?
In most placement-test contexts they mean the same thing: print each value that appears in the array exactly once, ignoring duplicates. Some older sources define distinct as elements with frequency exactly 1, which produces a different output — this article covers both interpretations.
Which approach should I use in a placement coding round?
Nested-loop O(N²) is easiest to write under time pressure and earns full marks for correctness. If the interviewer asks to optimise, move to sorting O(N log N) or count-array O(N). Always state the time-space trade-off in your explanation.
Does the nested-loop approach preserve insertion order?
Yes. It checks each element against those that came before it, so values print in the order they first appear in the original array.
What if the array contains negative integers — does the count-array approach work?
Not directly. The basic count-array requires non-negative integers in a known range. For arrays with negative values or a very large value range, use the sorting method or a proper hash-based structure instead.
How does sorting change the output compared to the original array?
Sorting rearranges the array in ascending order, so distinct values print in ascending order rather than insertion order. If preserving the original sequence matters, use the nested-loop approach.
A self-paced playground for building with LLMs.
TinkerLLM is FACE Prep's sister property. A guided environment for shipping real LLM applications, the kind of project that earns a paragraph on your resume, not a line.
Try TinkerLLM (₹299 launch)