NVIDIA C Programming with DSA Interview Questions & Answers
Curated interview practice questions with answers. These are practice scenarios, not a verified list of past interview questions.
About NVIDIA hiring for C Programming with DSA roles
NVIDIA designs GPUs and accelerated computing platforms used in gaming, data centres, AI and automotive. It also develops software like CUDA and AI frameworks. Its India offices in Pune, Bengaluru and Hyderabad work on chip design, verification, system software and AI. It hires for software engineers, verification engineers and test engineers.
For C Programming with DSA roles, this NVIDIA practice set focuses most on Pointers and Memory Management (7), Trees and Graphs (6), Structures, Unions and File Handling (5), Linked Lists (4). It has 1 easy, 24 medium, 5 hard questions, so you can start easy and work up to the harder ones.
Company type
Hardware & semiconductors
Headquarters
Santa Clara, California, USA
Main India offices
Pune, Bengaluru, Hyderabad
NVIDIA C Programming with DSA interview process
Online assessment or technical screening
Technical round 1
Technical round 2
Technical round 3 or manager round
HR round
Typical pattern based on public candidate experiences. Rounds vary by role, team and year.
Solved for NVIDIAStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
✓ 3 questions free • Unlock the rest in seconds
01
Why are self-balancing trees like AVL and red-black trees needed?
A plain BST can degrade to a linked list with O(n) operations when data arrives in sorted order. AVL trees keep the height difference of subtrees at most one using rotations, giving faster lookups. Red-black trees use colour rules with looser balance, so inserts and deletes need fewer rotations. Both guarantee O(log n). Red-black trees are used in the Linux kernel, C++ std::map and Java TreeMap.
02
What is the difference between a structure and a union?
In a structure each member has its own memory, so the size is at least the sum of members plus padding, and all members hold values at once. In a union all members share the same memory, so its size equals the largest member and only one member is meaningful at a time. Unions save memory and are used for variant types and in embedded protocol parsing.
Use a slow pointer moving one step and a fast pointer moving two steps. If the list has a cycle, the fast pointer eventually meets the slow one inside the loop; if fast reaches NULL, there is no cycle. To find the cycle start, reset one pointer to head and move both one step at a time; they meet at the start. It uses O(n) time and O(1) space.
04
Find the majority element that appears more than n/2 times in O(n) time and O(1) space.
Boyer-Moore voting algorithm.
int majority(const int *a, int n) {
int cand = 0, count = 0;
for (int i = 0; i < n; i++) {
if (count == 0) cand = a[i];
count += (a[i] == cand) ? 1 : -1;
}
return cand;
}
If a majority is not guaranteed, make a second pass to count cand and confirm it exceeds n/2.
05
Insert a node at the end of a singly linked list using a double pointer.
A pointer to pointer handles the empty list without special cases.
int append(Node **head, int value) {
Node *n = malloc(sizeof *n);
if (!n) return -1;
n->data = value;
n->next = NULL;
while (*head) head = &(*head)->next;
*head = n;
return 0;
}
Call it as append(&head, 5). Keep a tail pointer if you append often.
A prefix sum array stores pre[i] = sum of elements from index 0 to i-1. Then the sum of any range from l to r is pre[r + 1] - pre[l] in O(1) after O(n) preprocessing. It is used for range sum queries, counting subarrays with a given sum together with a hash map, and 2D versions for matrix region sums.
07
What is the difference between an array and a pointer?
An array is a block of contiguous elements whose size is fixed and known to the compiler; sizeof gives the full array size. A pointer is a variable holding an address; sizeof gives the pointer size. An array name decays to a pointer to its first element in most expressions, but it cannot be reassigned. When passed to a function, an array always becomes a pointer, losing its length.
A monotonic stack keeps elements in increasing or decreasing order by popping elements that break the order before pushing a new one. Each element is pushed and popped at most once, so problems run in O(n). It solves next greater element, daily temperatures, stock span and largest rectangle in a histogram, which would otherwise need nested loops.
09
How would you detect if two linked lists intersect and find the intersection node?
Two lists intersect if they share a node by address, not just value. Compute both lengths, advance the longer list by the difference, then move both together until the pointers are equal. A neat trick is to walk pointer a through list A then B, and pointer b through B then A; they meet at the intersection or both reach NULL. Both are O(m + n) time and O(1) space.
10
Write a C program that counts lines, words and characters in a file.
Read character by character with fgetc.
FILE *fp = fopen(path, "r");
if (!fp) { perror("fopen"); return 1; }
long lines = 0, words = 0, chars = 0;
int c, inWord = 0;
while ((c = fgetc(fp)) != EOF) {
chars++;
if (c == '\n') lines++;
if (isspace(c)) inWord = 0;
else if (!inWord) { inWord = 1; words++; }
}
fclose(fp);
printf("%ld %ld %ld\n", lines, words, chars);
c is int so EOF can be distinguished from valid bytes.
11
Allocate and free a dynamic 2D array of rows by cols in C.
A single block is cache friendly and easy to free.
int (*grid)[cols] = malloc(rows * sizeof *grid);
if (!grid) return -1;
grid[2][3] = 5;
free(grid);
// array of row pointers alternative
int **m = malloc(rows * sizeof *m);
for (int i = 0; i < rows; i++)
m[i] = calloc(cols, sizeof **m);
for (int i = 0; i < rows; i++) free(m[i]);
free(m);
The first form uses a variable length array type.
Alignment means placing data at addresses that are multiples of its size or required boundary, such as 4 for int. CPUs read aligned data faster, and some architectures fault on misaligned access. Compilers add padding in structs to align members. You can check alignment with _Alignof and request it with _Alignas or aligned_alloc in C11.
Situation: a C based telemetry agent grew by 200 MB a day on customer servers. Task: find and fix the leak quickly. Action: I reproduced it with recorded traffic under Valgrind and found that an error path returned early without freeing a parsed message buffer. I restructured the function with a single cleanup label and added a leak check job to CI. Result: memory stayed flat for weeks after the patch.
14
What is a trie and when is it better than a hash table?
A trie is a tree where each edge represents a character, so words sharing a prefix share a path. Lookup and insert take O(L) for a word of length L, independent of how many words are stored. It beats a hash table for prefix queries such as autocomplete, spell checking and longest prefix matching in IP routing. The trade-off is higher memory use from many child pointers.
15
How would you check whether a binary tree is a valid BST?
Comparing each node only with its children is wrong, because a deeper node can break the rule. Pass a valid range down: the left child must be in (min, node value) and the right child in (node value, max), starting with the full range of long long. Alternatively, do an in-order traversal and check values are strictly increasing. Both are O(n).
A flexible array member is a last struct member declared with empty brackets, such as struct Packet { size_t len; char data[]; };. You allocate the struct and its data in one malloc call: malloc(sizeof(struct Packet) + n). It keeps the header and payload together, improving cache use and needing only one free. It was standardised in C99.
Adding an integer to a pointer moves it by that many elements, not bytes, so p + 1 on an int pointer advances by sizeof(int). Subtracting two pointers into the same array gives the number of elements between them as ptrdiff_t. Arithmetic is valid only within an array or one past its end; going further is undefined behaviour. Void pointer arithmetic is not allowed in standard C.
Bit fields let struct members use a specified number of bits, such as unsigned int ready : 1; unsigned int mode : 3;, which saves memory for flags. They are common in embedded code and protocol headers. However, bit ordering, padding and whether plain int bit fields are signed are implementation defined, so for portable hardware register or wire format access, explicit masks and shifts are safer.
19
Write BFS on a graph stored as an adjacency matrix.
Use a queue and a visited array.
void bfs(int n, int adj[n][n], int start) {
int visited[n], queue[n], front = 0, rear = 0;
for (int i = 0; i < n; i++) visited[i] = 0;
visited[start] = 1;
queue[rear++] = start;
while (front < rear) {
int u = queue[front++];
printf("%d ", u);
for (int v = 0; v < n; v++) {
if (adj[u][v] && !visited[v]) {
visited[v] = 1;
queue[rear++] = v;
}
}
}
}
20
Describe a time you had to make a trade-off between memory and speed.
Situation: a C routing service on a small server ran out of memory with an adjacency matrix for 50,000 nodes. Task: fit within 512 MB without slowing queries much. Action: I switched to compact adjacency lists stored in flat arrays, known as CSR format, and kept a small cache for frequent routes. Result: memory fell from 10 GB worth of matrix to 60 MB and queries stayed under 20 ms.
21
Your linked list program crashes when deleting the last node. What do you check?
Check that the previous node's next pointer is set to NULL after freeing the last node, that the tail pointer is updated if you keep one and that you do not access the node after free. Also handle the case of a one-node list where head itself must become NULL, which requires passing a pointer to the head pointer. Run the code under AddressSanitizer to find invalid accesses.
Strict aliasing says an object may be accessed only through an lvalue of its own type, a compatible type or a character type. Reading a float through an int pointer breaks the rule and is undefined behaviour, and optimisers at -O2 may reorder or drop such accesses. To reinterpret bytes safely, use memcpy into a variable of the other type, or a union, which GCC supports for type punning.
23
What is the difference between greedy algorithms and dynamic programming?
A greedy algorithm makes the best local choice at each step and never revisits it, which works only when the greedy choice property holds, as in activity selection, Huffman coding and Dijkstra. Dynamic programming considers all relevant subproblem choices and combines them, so it works where greedy fails, such as 0/1 knapsack or coin change with arbitrary denominations. Greedy is faster when provably correct.
24
Find the length of the longest substring without repeating characters in C.
Sliding window with last seen positions.
int longestUnique(const char *s) {
int last[256];
for (int i = 0; i < 256; i++) last[i] = -1;
int best = 0, start = 0;
for (int i = 0; s[i]; i++) {
unsigned char c = s[i];
if (last[c] >= start) start = last[c] + 1;
last[c] = i;
if (i - start + 1 > best) best = i - start + 1;
}
return best;
}
For abcabcbb it returns 3.
25
After calling realloc, the program sometimes crashes. What could be wrong?
realloc may move the block and returns the new address, so old pointers to the block become invalid. Writing ptr = realloc(ptr, n) also leaks the original memory if realloc fails and returns NULL. Store the result in a temporary pointer, check for NULL, then assign. Make sure no other pointers still refer to the old location after a successful move.
26
A recursive tree traversal crashes on a very large, skewed tree. How do you fix it?
A skewed tree has height close to n, so recursion depth becomes huge and overflows the call stack. Convert the traversal to an iterative version using an explicit stack allocated on the heap, or use Morris traversal for in-order with O(1) extra space. Long term, use a self-balancing tree so height stays around log n.
27
A program that writes logs with fprintf loses the last lines when it crashes. Why, and how do you fix it?
stdio streams are buffered, so fprintf stores data in memory and writes it to disk only when the buffer fills, the file closes or fflush is called. A crash loses whatever is still in the buffer. Call fflush after important log lines, set line buffering with setvbuf(fp, NULL, _IOLBF, 0) or write critical messages to unbuffered stderr. For durability on disk, add fsync on POSIX systems.
28
Evaluate a postfix expression of single digit numbers using a stack.
Push digits and apply operators to the top two values.
int evalPostfix(const char *s) {
int st[100], top = -1;
for (; *s; s++) {
if (isdigit((unsigned char)*s)) st[++top] = *s - '0';
else if (strchr("+-*/", *s)) {
int b = st[top--], a = st[top--];
switch (*s) {
case '+': st[++top] = a + b; break;
case '-': st[++top] = a - b; break;
case '*': st[++top] = a * b; break;
case '/': st[++top] = a / b; break;
}
}
}
return st[top];
}
23*5+ evaluates to 11.
29
A hash table becomes slow as more data is inserted. What is wrong?
The load factor has grown, so chains get long or open addressing probes become long, turning O(1) into nearly O(n). Another cause is a poor hash function clustering keys into few buckets. Fix it by resizing to roughly double capacity and rehashing when the load factor crosses a threshold, and by using a better hash function. Measure the longest chain to confirm.
30
Implement a circular queue with enqueue and dequeue in C.
Use modulo arithmetic and a count.
#define CAP 8
typedef struct { int a[CAP]; int front, rear, count; } Queue;
int enqueue(Queue *q, int x) {
if (q->count == CAP) return -1;
q->a[q->rear] = x;
q->rear = (q->rear + 1) % CAP;
q->count++;
return 0;
}
int dequeue(Queue *q, int *x) {
if (q->count == 0) return -1;
*x = q->a[q->front];
q->front = (q->front + 1) % CAP;
q->count--;
return 0;
}
Tips to crack the NVIDIA C Programming with DSA interview
Revise C and C++, operating systems and computer architecture, which are core to most NVIDIA engineering roles.
Learn GPU and CUDA basics, including parallel programming, threads, blocks and the GPU memory hierarchy.
Read about NVIDIA's data centre and AI platforms to understand where much of its current work is focused.
Keep a one-minute story ready for every project on your CV: problem, your part, tools, result.
Practise the hard questions on this page aloud; NVIDIA interviewers usually ask follow-ups on your first answer.
Frequently asked questions
How many rounds are there in the NVIDIA C Programming with DSA interview?
Candidates usually go through 5 stages: Online assessment or technical screening; Technical round 1; Technical round 2; Technical round 3 or manager round; HR round. The exact rounds change with the role, team, location and your experience, so confirm the process with the recruiter.
Which topics should I prepare for the NVIDIA C Programming with DSA interview?
This practice set leans on Pointers and Memory Management (7), Trees and Graphs (6), Structures, Unions and File Handling (5), Linked Lists (4). Revise those first, then practise explaining one or two of your own projects end to end, because most NVIDIA interviewers ask you to walk through real work.
Are these the exact questions asked at NVIDIA?
No. These are curated practice questions that match the skills and difficulty usually tested in hardware & semiconductors interviews like NVIDIA's. They are not a leaked or verified list of past questions.
Where does NVIDIA hire C Programming with DSA professionals in India?
NVIDIA has large teams in Pune, Bengaluru, Hyderabad. Openings and locations change often, so check the NVIDIA careers page and filter by city and experience.
C Programming with DSA questions for similar companies