Skip to content
Laviyx Learn

Try

C course menu

C Coding Interview Challenges with Solutions

Classic C coding interview problems with full, tested solutions and complexity analysis: reverse a string in place, implement strcpy and atoi, find duplicates, remove duplicates from a sorted array, second largest element, reverse a linked list, detect a cycle, rotate an array, binary search, and count words.

Advanced18 min readUpdated
On this page

These problems are favourites in C interviews because they test pointers, strings and memory together. For each one, think about edge cases (empty input, one element, NULL) and state the time and space complexity before you open the solution.

Challenge 1: Reverse a string in place#

Reverse a string without using another array.

Show solution

Swap characters from both ends, moving towards the middle. O(n) time, O(1) extra space.

C
#include <stdio.h>
#include <string.h>

void reverse(char *s) {
    if (s == NULL) return;
    size_t n = strlen(s);
    if (n < 2) return;
    for (char *l = s, *r = s + n - 1; l < r; l++, r--) {
        char t = *l;
        *l = *r;
        *r = t;
    }
}

int main(void) {
    char a[] = "interview";
    char b[] = "";
    reverse(a);
    reverse(b);
    printf("[%s] [%s]\n", a, b);
    return 0;
}
Output
[weivretni] []

Challenge 2: Implement strcpy and strcat#

Show solution
C
#include <stdio.h>

char *my_strcpy(char *dst, const char *src) {
    char *start = dst;
    while ((*dst++ = *src++) != '\0') { }
    return start;
}

char *my_strcat(char *dst, const char *src) {
    char *p = dst;
    while (*p) p++;                 /* find the end of dst */
    my_strcpy(p, src);
    return dst;
}

int main(void) {
    char buf[32];
    my_strcpy(buf, "embedded");
    my_strcat(buf, " systems");
    printf("%s\n", buf);
    return 0;
}
Output
embedded systems

Mention that, like the standard versions, these assume the destination is big enough, which is why snprintf is safer in real code.

Challenge 3: Implement atoi#

Convert a string to an int: skip leading spaces, handle an optional sign, stop at the first non-digit, and clamp to INT_MAX/INT_MIN on overflow.

Show solution

Check for overflow before multiplying, so no signed overflow ever happens. O(n) time.

C
#include <limits.h>
#include <stdio.h>

int my_atoi(const char *s) {
    while (*s == ' ' || *s == '\t') s++;
    int sign = 1;
    if (*s == '+' || *s == '-') {
        if (*s == '-') sign = -1;
        s++;
    }
    int result = 0;
    while (*s >= '0' && *s <= '9') {
        int digit = *s - '0';
        if (result > (INT_MAX - digit) / 10) {
            return sign == 1 ? INT_MAX : INT_MIN;
        }
        result = result * 10 + digit;
        s++;
    }
    return sign * result;
}

int main(void) {
    const char *tests[] = {"42", "   -17abc", "+0", "99999999999", "-2147483648", "abc"};
    for (int i = 0; i < 6; i++) printf("\"%s\" -> %d\n", tests[i], my_atoi(tests[i]));
    return 0;
}
Output
"42" -> 42
"   -17abc" -> -17
"+0" -> 0
"99999999999" -> 2147483647
"-2147483648" -> -2147483648
"abc" -> 0

-2147483648 clamps to INT_MIN, which happens to be the right value: its magnitude does not fit in a positive int.

Challenge 4: Find the first repeated character#

Return the first character in a string that appears again later, or '\0' if none repeats.

Show solution

A 256-entry table of "seen" flags gives O(n) time and O(1) space (the table size does not depend on the input):

C
#include <stdio.h>

char first_repeat(const char *s) {
    unsigned char seen[256] = {0};
    for (; *s; s++) {
        unsigned char c = (unsigned char)*s;
        if (seen[c]) return *s;
        seen[c] = 1;
    }
    return '\0';
}

int main(void) {
    const char *tests[] = {"programming", "abcdef", "abca"};
    for (int i = 0; i < 3; i++) {
        char c = first_repeat(tests[i]);
        printf("%s: %c\n", tests[i], c ? c : '-');
    }
    return 0;
}
Output
programming: r
abcdef: -
abca: a

Challenge 5: Remove duplicates from a sorted array#

Remove duplicates in place and return the new length.

Show solution

Two indexes: write marks the end of the unique part. O(n) time, O(1) space.

C
#include <stdio.h>

int dedupe(int *a, int n) {
    if (n == 0) return 0;
    int write = 1;
    for (int read = 1; read < n; read++) {
        if (a[read] != a[write - 1]) a[write++] = a[read];
    }
    return write;
}

int main(void) {
    int a[] = {1, 1, 2, 3, 3, 3, 7, 9, 9};
    int n = dedupe(a, 9);
    for (int i = 0; i < n; i++) printf("%d ", a[i]);
    printf("(length %d)\n", n);
    return 0;
}
Output
1 2 3 7 9 (length 5)

Challenge 6: Second largest element#

Find the second largest distinct value in one pass.

Show solution
C
#include <limits.h>
#include <stdio.h>

int second_largest(const int *a, int n, int *out) {
    int first = INT_MIN, second = INT_MIN, found = 0;
    for (int i = 0; i < n; i++) {
        if (a[i] > first) {
            second = first;
            first = a[i];
        } else if (a[i] < first && a[i] > second) {
            second = a[i];
        }
    }
    for (int i = 0; i < n; i++) if (a[i] == second && second < first) found = 1;
    if (found) *out = second;
    return found;
}

int main(void) {
    int a[] = {12, 35, 1, 10, 34, 35};
    int b[] = {5, 5, 5};
    int r;
    if (second_largest(a, 6, &r)) printf("%d\n", r);
    printf("%s\n", second_largest(b, 3, &r) ? "found" : "no second largest");
    return 0;
}
Output
34
no second largest

The found check handles arrays where every value is the same, and arrays that contain INT_MIN itself.

Challenge 7: Rotate an array to the right by k#

Show solution

The reversal trick: reverse the whole array, then reverse the first k and the rest. O(n) time, O(1) space.

C
#include <stdio.h>

static void rev(int *a, int i, int j) {
    while (i < j) {
        int t = a[i];
        a[i++] = a[j];
        a[j--] = t;
    }
}

void rotate_right(int *a, int n, int k) {
    if (n == 0) return;
    k %= n;
    rev(a, 0, n - 1);
    rev(a, 0, k - 1);
    rev(a, k, n - 1);
}

int main(void) {
    int a[] = {1, 2, 3, 4, 5, 6, 7};
    rotate_right(a, 7, 3);
    for (int i = 0; i < 7; i++) printf("%d ", a[i]);
    printf("\n");
    return 0;
}
Output
5 6 7 1 2 3 4 

Challenge 8: Reverse a linked list#

Show solution

Iteratively turn each next pointer around. O(n) time, O(1) space.

C
#include <stdio.h>
#include <stdlib.h>

typedef struct Node { int v; struct Node *next; } Node;

Node *push(Node *head, int v) {
    Node *n = malloc(sizeof *n);
    if (n == NULL) exit(1);
    n->v = v;
    n->next = head;
    return n;
}

Node *reverse(Node *head) {
    Node *prev = NULL;
    while (head) {
        Node *next = head->next;
        head->next = prev;
        prev = head;
        head = next;
    }
    return prev;
}

void print(const Node *p) {
    for (; p; p = p->next) printf("%d ", p->v);
    printf("\n");
}

int main(void) {
    Node *list = NULL;
    for (int i = 5; i >= 1; i--) list = push(list, i);
    print(list);
    list = reverse(list);
    print(list);
    while (list) { Node *n = list->next; free(list); list = n; }
    return 0;
}
Output
1 2 3 4 5 
5 4 3 2 1 

Challenge 9: Detect a cycle in a linked list#

Show solution

Floyd's "tortoise and hare": a slow pointer moves one node at a time and a fast one moves two. If there is a cycle they meet; otherwise the fast pointer reaches NULL. O(n) time, O(1) space.

C
#include <stdio.h>

typedef struct Node { int v; struct Node *next; } Node;

int has_cycle(const Node *head) {
    const Node *slow = head, *fast = head;
    while (fast && fast->next) {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast) return 1;
    }
    return 0;
}

int main(void) {
    Node n[4];
    for (int i = 0; i < 4; i++) { n[i].v = i; n[i].next = (i < 3) ? &n[i + 1] : NULL; }
    printf("%d\n", has_cycle(&n[0]));
    n[3].next = &n[1];                    /* create a cycle: 3 -> 1 */
    printf("%d\n", has_cycle(&n[0]));
    return 0;
}
Output
0
1

Challenge 10: Count words in a sentence#

Count words separated by any amount of whitespace.

Show solution

Count the transitions from "outside a word" to "inside a word". O(n) time.

C
#include <ctype.h>
#include <stdio.h>

int count_words(const char *s) {
    int count = 0, in_word = 0;
    for (; *s; s++) {
        if (isspace((unsigned char)*s)) {
            in_word = 0;
        } else if (!in_word) {
            in_word = 1;
            count++;
        }
    }
    return count;
}

int main(void) {
    printf("%d\n", count_words("  C is   a   small\tlanguage \n"));
    printf("%d\n", count_words(""));
    return 0;
}
Output
5
0

How to approach a coding interview in C#

  1. Clarify the input: can it be empty or NULL? What are the limits?
  2. Explain your approach and its complexity before writing code.
  3. Write small helper functions with clear names; check every malloc.
  4. Test out loud with a normal case and edge cases (empty, one element, duplicates, overflow).
  5. Free what you allocate, and mention what you would improve with more time.

Finished this lesson?