The TCS coding round is where most candidates either prove their technical capability or reveal a preparation gap they did not know existed. The problems are not abstract algorithmic puzzles plucked from a competitive programming archive - they are real-world scenario problems wrapped in business narratives, testing whether you can translate a practical requirement into working, compilable, correctly-outputting code within a strict time limit. Understanding this character of TCS coding questions is more important than memorising any specific solution, because the framing varies endlessly while the underlying algorithmic patterns repeat reliably.

TCS Guide

This guide covers the complete TCS coding round ecosystem: the compiler environment, the test case and scoring system, the language tradeoffs on TCS’s specific infrastructure, and a comprehensive categorised collection of original representative problems with full solutions in C, C++, Java, and Python. Every problem here is written to mirror the exact style, difficulty calibration, input/output format, and narrative structure of actual TCS coding questions - without reproducing any copyrighted material. The guide ends with a curated 20-problem practice sequence ordered by difficulty, and a complete section on Command Line Programming, which TCS tests as MCQ questions alongside the coding round.


The TCS Coding Round Structure

NQT Foundation Coding (Ninja Profile)

The Foundation coding component is a single problem with a 30-minute window. This component is often not separately highlighted in candidate discussions because the Foundation Section itself is the primary Ninja filter - but it is evaluated and contributes to the holistic NQT score that influences profile routing.

Difficulty: Moderate - comparable to LeetCode Easy problems. The problem tests basic programming constructs: loops, conditionals, string/array manipulation, and simple mathematical operations.

What it tests: Can you write correct, compilable code for a straightforward task? Is your input parsing correct? Does your output match the expected format exactly?

Target solve time: 15-20 minutes for a complete, correct solution. Leaving 10 minutes for review and testing against visible cases.

NQT Advanced Coding (Digital and Prime Profiles)

The Advanced Coding section is 2-3 problems with a shared 90-minute window. This is the primary differentiator for Digital routing and the component where preparation depth is most visible.

Problem 1 (Easy-Medium, 15-25 minutes): Implementation-level. String manipulation, array scanning, basic sorting, simple mathematical computation. A candidate with solid programming fundamentals should solve this fully with time to spare.

Problem 2 (Medium-Hard, 40-55 minutes): Algorithmic. Requires knowledge of dynamic programming, graph traversal, binary search on the answer, or greedy algorithms. A correct brute-force solution earns partial credit; the optimal solution earns full marks.

Problem 3 if present (Hard, 20-30 minutes): Competitive programming level. Advanced data structures or complex algorithmic design. Targeted at Prime profile candidates. Most Digital candidates do not need to fully solve this.

Time management across problems: The 90 minutes is a shared pool. Read all problems before starting. Solve Problem 1 completely (20-25 minutes), attempt Problem 2 with a brute force at minimum (30-40 minutes), then use remaining time to optimise Problem 2 or start Problem 3.


The TCS iON Compiler Environment

Platform Architecture

TCS uses the TCS iON platform for all coding assessments. The code editor is a browser-based interface with basic syntax highlighting but no auto-complete, no inline error detection, and no integrated debugger. The underlying compiler infrastructure uses GCC (for C and C++) and standard runtime environments for Java and Python.

What this means practically:

  • No IDE assistance: you must write syntactically correct code from memory
  • Compilation errors show in the output panel after you click “Run”
  • Logical errors only reveal themselves through wrong output on test cases
  • There is no step-through debugger: use print statements strategically for debugging

The Compilation Error Recovery Workflow

When your code fails to compile on TCS iON, the error message appears in the output panel. The most common compilation errors and how to fix them quickly under exam pressure:

C/C++ - Undeclared identifier: error: 'vector' was not declared in this scope. Fix: missing #include. For C++, the shortcut #include <bits/stdc++.h> with using namespace std; includes everything. For C, add specific headers (#include <stdio.h>, #include <stdlib.h>, #include <string.h>).

C/C++ - Type mismatch with size_t: warning: comparison between signed and unsigned integer expressions. Fix: cast to (int) when comparing i < (int)arr.size(). This prevents subtle off-by-one bugs when the vector is empty.

Java - Class name mismatch: error: class MyProgram is public, should be declared in a file named MyProgram.java. On TCS iON, the class must be named Main exactly. Change public class MyProgram to public class Main.

Java - Scanner not imported: error: cannot find symbol Scanner. Fix: add import java.util.*; at the top.

Python - IndentationError: Python is whitespace-sensitive. The TCS iON editor uses spaces rather than tabs. A mix of tabs and spaces causes IndentationError. Use 4 spaces per indent level consistently throughout.

Test Case Categories Deep Dive

Understanding the specific types of hidden test cases that TCS uses guides defensive coding:

Boundary test cases: n=1 (single element), n=0 (empty if allowed by constraints), n=maximum (tests time complexity). Always trace your code mentally for n=1 before submitting.

Value boundary test cases: values at their minimum (1, or -10^9 if negative allowed) and maximum (10^9 or INT_MAX). These test overflow handling and off-by-one in comparison logic.

Pattern test cases: all elements identical, all elements in sorted order (ascending), all elements in reverse sorted order, alternating high-low values. These test whether your algorithm handles degenerate inputs without breaking.

Structural test cases for graph problems: disconnected graph (multiple components), complete graph (every node connected to every other), star graph (one central node connected to all others, no other edges), linear chain (each node connected only to the next).

String-specific test cases: empty string (if allowed), string with only one unique character, string with all same characters, string containing spaces or special characters (if the problem permits them), very long string testing time limits.

Building the habit of mentally running your solution against each of these categories before submitting is the single most effective practice for improving hidden test case pass rates.

Execution Model

Your code reads from standard input (stdin) and writes to standard output (stdout). The test harness pipes input through stdin when evaluating your solution. This means:

  • In C/C++: use scanf/cin for input, printf/cout for output
  • In Java: use Scanner or BufferedReader for input, System.out.println for output
  • In Python: use input() for reading, print() for writing

The “Run” button executes your code against visible sample test cases and shows you the output. The “Submit” button evaluates against all test cases including hidden ones. Always run before submitting.

Language-Specific Considerations on TCS Compiler

C: Runtime: fastest. No standard library for dynamic data structures - must implement manually. Excellent for pure computational problems. Risk: manual memory management, pointer bugs.

Best for: competitive programmers comfortable with pointer arithmetic and manual implementation.

C++: Runtime: fastest (same as C). Full STL available: vector, map, set, unordered_map, priority_queue, deque, string. Use #include <bits/stdc++.h> with using namespace std; - this works on TCS iON. Critical rule: use long long for any value exceeding 2^31 - 1 (approximately 2.1 billion).

Best for: most candidates targeting Digital. STL reduces implementation time significantly.

Java: Runtime: moderate. Class must be named Main (capital M) - other names cause compilation failure. java.util.* and java.io.* are available. Scanner works for input but BufferedReader with Integer.parseInt is significantly faster for large inputs. Must flush output when using PrintWriter.

// Faster Java input template
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());

Best for: candidates whose strongest language is Java. Verbose but reliable.

Python: Runtime: slowest. Interpreted overhead matters for computation-heavy problems with large inputs. Mitigation: use sys.stdin.readline() instead of input() for multiple reads, use built-in functions (sorted, max, min, sum) which are C-implemented and fast, use sys.setrecursionlimit(100000) for deep recursion.

import sys
input = sys.stdin.readline  # globally replace input with faster version

Best for: candidates who write Python most fluently. Ideal for string and array problems where Python’s expressiveness reduces bug risk.

The Test Case System

Visible test cases: 2-3 input/output pairs shown in the problem statement. When you click “Run,” your output is compared to the expected output. A checkmark or cross shows whether your output matched.

Hidden test cases: 8-15 additional test cases not shown to you. These include:

  • Boundary cases: n=0, n=1, empty string, single character
  • Maximum constraint cases: n=100000, testing time complexity
  • Edge cases specific to the problem logic: all elements equal, already sorted, reverse sorted
  • Overflow cases: values near INT_MAX, sums that overflow 32-bit integers

Partial credit: your score for each problem is (test cases passed) / (total test cases). If Problem 2 has 10 hidden test cases and your solution passes 6, you receive 60% of Problem 2’s marks. This makes the “always submit something” principle mathematically correct: a brute force that passes small cases is strictly better than a blank submission.

Output format strictness: the test harness performs exact string matching on output. A trailing space, an extra newline, or “Yes” vs “YES” will fail a test case. Match the expected output format precisely.


Category 1: Array Manipulation

Problem 1.1 - Inventory Rebalancing

Problem Statement (TCS-style narrative):

A warehouse manager is rebalancing a storage shelf. The shelf holds N items with different stock quantities. The manager wants to rearrange the items such that items with odd stock quantities come first (in their original relative order), followed by items with even stock quantities (in their original relative order). Write a program to output the rebalanced arrangement.

Input Format:

  • First line: integer N (number of items)
  • Second line: N space-separated integers representing stock quantities

Output Format: N space-separated integers in the rebalanced order.

Constraints: 1 ≤ N ≤ 10^5, 1 ≤ quantity ≤ 10^4

Edge cases: All items odd, all items even, single item, alternating odd/even.

Approach: Two-pass stable partition. First collect all odd values preserving order, then all even values preserving order, concatenate.

C++ Solution:

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> arr(n);
    for (int i = 0; i < n; i++) cin >> arr[i];

    vector<int> odds, evens;
    for (int x : arr) {
        if (x % 2 != 0) odds.push_back(x);
        else evens.push_back(x);
    }
    for (int x : odds) cout << x << " ";
    for (int x : evens) cout << x << " ";
    cout << endl;
    return 0;
}

Java Solution:

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        List<Integer> odds = new ArrayList<>(), evens = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            int x = sc.nextInt();
            if (x % 2 != 0) odds.add(x);
            else evens.add(x);
        }
        StringBuilder sb = new StringBuilder();
        for (int x : odds) sb.append(x).append(" ");
        for (int x : evens) sb.append(x).append(" ");
        System.out.println(sb.toString().trim());
    }
}

Python Solution:

n = int(input())
arr = list(map(int, input().split()))
odds = [x for x in arr if x % 2 != 0]
evens = [x for x in arr if x % 2 == 0]
print(*odds, *evens)

C Solution:

#include <stdio.h>

int main() {
    int n;
    scanf("%d", &n);
    int arr[100005], odds[100005], evens[100005];
    int oc = 0, ec = 0;
    for (int i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
        if (arr[i] % 2 != 0) odds[oc++] = arr[i];
        else evens[ec++] = arr[i];
    }
    for (int i = 0; i < oc; i++) printf("%d ", odds[i]);
    for (int i = 0; i < ec; i++) printf("%d ", evens[i]);
    printf("\n");
    return 0;
}

Time Complexity: O(n). Space Complexity: O(n).


Problem 1.2 - Assembly Line Maximum Subproduct

Problem Statement:

A robot assembly line records efficiency ratings for each station. The quality team wants to find the contiguous sub-sequence of stations with the maximum product of efficiency ratings. The ratings can be negative (indicating a defective phase). Return the maximum product achievable.

Input: First line N. Second line N integers (can be negative).

Output: Single integer - maximum product.

Constraints: 1 ≤ N ≤ 10^4, -100 ≤ rating ≤ 100

Brute Force Approach (O(n³)): For every pair of indices (i,j), compute the product of all elements between i and j. Track the maximum.

# Brute force - correct but too slow for large N
def brute_force(arr):
    n = len(arr)
    max_prod = arr[0]
    for i in range(n):
        for j in range(i, n):
            prod = 1
            for k in range(i, j+1):
                prod *= arr[k]
            max_prod = max(max_prod, prod)
    return max_prod

Why brute force fails: for N=10^4, O(N³) = 10^12 operations - TLE in any language. The optimised O(n) solution is required.

Optimised Approach (O(n)): Track both maximum and minimum product ending at each position (minimum matters because a negative × negative = positive).

C++ Solution:

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> arr(n);
    for (int i = 0; i < n; i++) cin >> arr[i];

    long long maxProd = arr[0], minProd = arr[0], ans = arr[0];
    for (int i = 1; i < n; i++) {
        long long a = arr[i], prevMax = maxProd, prevMin = minProd;
        maxProd = max({a, prevMax * a, prevMin * a});
        minProd = min({a, prevMax * a, prevMin * a});
        ans = max(ans, maxProd);
    }
    cout << ans << endl;
    return 0;
}

Python Solution:

n = int(input())
arr = list(map(int, input().split()))
max_p = min_p = ans = arr[0]
for i in range(1, n):
    a = arr[i]
    candidates = (a, max_p * a, min_p * a)
    max_p, min_p = max(candidates), min(candidates)
    ans = max(ans, max_p)
print(ans)

Time Complexity: O(n). Space Complexity: O(1).

Edge cases: Single element (return it directly). All negatives of odd count. Contains zero (product resets to current element).


Problem 1.3 - Sensor Data Rotation

Problem Statement:

A circular sensor array of N sensors produces readings. The data analyst needs to rotate the readings K positions to the right (the element at position N-K becomes the first element after rotation). Implement the rotation in-place.

Input: N on first line. K on second line. N integers on third line.

Output: Rotated array on one line, space-separated.

C++ Solution (reversal algorithm):

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n, k;
    cin >> n >> k;
    vector<int> arr(n);
    for (int i = 0; i < n; i++) cin >> arr[i];
    k %= n;
    reverse(arr.begin(), arr.end());
    reverse(arr.begin(), arr.begin() + k);
    reverse(arr.begin() + k, arr.end());
    for (int i = 0; i < n; i++) cout << arr[i] << " \n"[i==n-1];
    return 0;
}

Python Solution:

n = int(input())
k = int(input()) % n
arr = list(map(int, input().split()))
result = arr[-k:] + arr[:-k]
print(*result)

Time Complexity: O(n). Space Complexity: O(1) for C++, O(n) for Python.

Key insight: the reversal algorithm rotates in-place using three reverses. This is the standard TCS-expected approach for array rotation.


Category 2: String Processing

Problem 2.1 - Security Access Code Validator

Problem Statement:

A corporate security system generates access codes and must validate them. A code is “balanced” if every opening bracket has a matching closing bracket in the correct order. Valid bracket pairs are (), [], and {}. Non-bracket characters in the code should be ignored during validation. Print “VALID” if balanced, “INVALID” otherwise.

Input: Single string (the access code, may include letters, numbers, and brackets)

Output: “VALID” or “INVALID”

C++ Solution:

#include <bits/stdc++.h>
using namespace std;

int main() {
    string s;
    cin >> s;
    stack<char> st;
    map<char,char> match = {{')',  '('}, {']', '['}, {'}', '{'}};
    for (char c : s) {
        if (c=='(' || c=='[' || c=='{') st.push(c);
        else if (match.count(c)) {
            if (st.empty() || st.top() != match[c]) {
                cout << "INVALID" << endl;
                return 0;
            }
            st.pop();
        }
    }
    cout << (st.empty() ? "VALID" : "INVALID") << endl;
    return 0;
}

Java Solution:

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.next();
        Deque<Character> stack = new ArrayDeque<>();
        Map<Character, Character> match = new HashMap<>();
        match.put(')', '('); match.put(']', '['); match.put('}', '{');
        for (char c : s.toCharArray()) {
            if (c == '(' || c == '[' || c == '{') stack.push(c);
            else if (match.containsKey(c)) {
                if (stack.isEmpty() || stack.peek() != match.get(c)) {
                    System.out.println("INVALID");
                    return;
                }
                stack.pop();
            }
        }
        System.out.println(stack.isEmpty() ? "VALID" : "INVALID");
    }
}

Python Solution:

s = input().strip()
stack = []
match = {')': '(', ']': '[', '}': '{'}
for c in s:
    if c in '([{':
        stack.append(c)
    elif c in ')]}':
        if not stack or stack[-1] != match[c]:
            print("INVALID")
            exit()
        stack.pop()
print("VALID" if not stack else "INVALID")

Time Complexity: O(n). Space Complexity: O(n) for the stack.


Problem 2.2 - Product Label Encoding

Problem Statement:

A manufacturing unit encodes product labels using run-length encoding: consecutive identical characters are compressed as the character followed by its count. For example, “AAABBBCC” becomes “A3B3C2”. If a character appears only once, it is represented without a count (e.g., “ABC” becomes “ABC”, not “A1B1C1”). Decode a given encoded label back to its original form.

Input: Single encoded string.

Output: Decoded original string.

C++ Solution:

#include <bits/stdc++.h>
using namespace std;

int main() {
    string s;
    cin >> s;
    string result = "";
    int i = 0;
    while (i < (int)s.size()) {
        char c = s[i++];
        string numStr = "";
        while (i < (int)s.size() && isdigit(s[i])) {
            numStr += s[i++];
        }
        int count = numStr.empty() ? 1 : stoi(numStr);
        result += string(count, c);
    }
    cout << result << endl;
    return 0;
}

Python Solution:

s = input().strip()
result = []
i = 0
while i < len(s):
    c = s[i]
    i += 1
    num_str = ''
    while i < len(s) and s[i].isdigit():
        num_str += s[i]
        i += 1
    count = int(num_str) if num_str else 1
    result.append(c * count)
print(''.join(result))

Time Complexity: O(n + length of decoded string). Space Complexity: O(length of decoded string).

Edge cases: Single characters without counts, multi-digit counts (e.g., “A12”), mixed case characters.


Problem 2.3 - Anagram Cluster Finder

Problem Statement:

A linguistics research tool groups words that are anagrams of each other. Given N words, group them such that anagram sets are on separate lines. Within each group, maintain the original order of appearance. Groups should be output in the order their first member appeared.

Input: First line N. Next N lines, one word per line.

Output: Each group on a separate line, words space-separated.

Python Solution:

from collections import OrderedDict

n = int(input())
groups = OrderedDict()
for _ in range(n):
    word = input().strip()
    key = ''.join(sorted(word))
    if key not in groups:
        groups[key] = []
    groups[key].append(word)

for group in groups.values():
    print(' '.join(group))

C++ Solution:

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    map<string, vector<string>> groups;
    vector<string> order;
    for (int i = 0; i < n; i++) {
        string word;
        cin >> word;
        string key = word;
        sort(key.begin(), key.end());
        if (groups.find(key) == groups.end()) order.push_back(key);
        groups[key].push_back(word);
    }
    for (auto& k : order) {
        for (int i = 0; i < (int)groups[k].size(); i++) {
            cout << groups[k][i];
            if (i + 1 < (int)groups[k].size()) cout << " ";
        }
        cout << "\n";
    }
    return 0;
}

Time Complexity: O(n × m log m) where m is max word length (sorting each word). Space Complexity: O(n × m).


Category 3: Number Theory

Problem 3.1 - Digital Root Compression

Problem Statement:

A data compression algorithm reduces a number to its digital root. The digital root is obtained by repeatedly summing the digits of a number until a single digit is obtained. For example: 9875 → 9+8+7+5 = 29 → 2+9 = 11 → 1+1 = 2. Given N numbers, output the digital root of each.

Input: First line N. Next N lines, one number per line.

Output: N lines, digital root of each number.

C++ Solution:

#include <bits/stdc++.h>
using namespace std;

int digitalRoot(long long n) {
    if (n == 0) return 0;
    return 1 + (n - 1) % 9;  // mathematical formula
}

int main() {
    int n;
    cin >> n;
    while (n--) {
        long long x;
        cin >> x;
        cout << digitalRoot(x) << "\n";
    }
    return 0;
}

Python Solution:

def digital_root(n):
    if n == 0:
        return 0
    return 1 + (n - 1) % 9

t = int(input())
for _ in range(t):
    print(digital_root(int(input())))

Key insight: the mathematical formula 1 + (n-1) % 9 computes digital root in O(1) without iterating. TCS questions frequently test whether a candidate knows this shortcut vs iterating through digit sums.


Problem 3.2 - Prime Gap Finder

Problem Statement:

A security researcher analyses prime number distributions. Given a range [L, R], find the longest gap between consecutive primes in that range. If fewer than two primes exist in the range, output -1.

Input: Two integers L and R on one line.

Output: The longest gap, or -1.

Constraints: 2 ≤ L ≤ R ≤ 10^6

C++ Solution (Sieve):

#include <bits/stdc++.h>
using namespace std;

int main() {
    long long L, R;
    cin >> L >> R;

    // Sieve of Eratosthenes up to R
    vector<bool> is_prime(R + 1, true);
    is_prime[0] = is_prime[1] = false;
    for (long long i = 2; i * i <= R; i++) {
        if (is_prime[i]) {
            for (long long j = i * i; j <= R; j += i)
                is_prime[j] = false;
        }
    }

    long long prev = -1, maxGap = -1;
    for (long long i = L; i <= R; i++) {
        if (is_prime[i]) {
            if (prev != -1) maxGap = max(maxGap, i - prev);
            prev = i;
        }
    }
    cout << maxGap << endl;
    return 0;
}

Python Solution:

def sieve(limit):
    is_prime = [True] * (limit + 1)
    is_prime[0] = is_prime[1] = False
    for i in range(2, int(limit**0.5) + 1):
        if is_prime[i]:
            for j in range(i*i, limit + 1, i):
                is_prime[j] = False
    return is_prime

L, R = map(int, input().split())
is_prime = sieve(R)
prev, max_gap = -1, -1
for i in range(L, R + 1):
    if is_prime[i]:
        if prev != -1:
            max_gap = max(max_gap, i - prev)
        prev = i
print(max_gap)

Time Complexity: O(R log log R) for sieve + O(R-L) for scan. Space Complexity: O(R).


Problem 3.3 - Binary Representation Parity Check

Problem Statement:

A network protocol uses parity checking. Given a decimal integer N, determine if the number of 1-bits in its binary representation is even (“EVEN PARITY”) or odd (“ODD PARITY”).

Input: Single integer N.

Output: “EVEN PARITY” or “ODD PARITY”.

C++ Solution:

#include <bits/stdc++.h>
using namespace std;

int main() {
    long long n;
    cin >> n;
    int count = __builtin_popcountll(n);  // GCC built-in for bit count
    cout << (count % 2 == 0 ? "EVEN PARITY" : "ODD PARITY") << endl;
    return 0;
}

Java Solution:

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        long n = sc.nextLong();
        int count = Long.bitCount(n);
        System.out.println(count % 2 == 0 ? "EVEN PARITY" : "ODD PARITY");
    }
}

Python Solution:

n = int(input())
count = bin(n).count('1')
print("EVEN PARITY" if count % 2 == 0 else "ODD PARITY")

C Solution:

#include <stdio.h>

int main() {
    long long n;
    scanf("%lld", &n);
    int count = 0;
    while (n) {
        count += n & 1;
        n >>= 1;
    }
    printf("%s\n", count % 2 == 0 ? "EVEN PARITY" : "ODD PARITY");
    return 0;
}

Time Complexity: O(log n). Space Complexity: O(1).


Category 4: Mathematical Logic

Problem 4.1 - Fibonacci-Weighted Score Calculator

Problem Statement:

A game show assigns bonus multipliers based on the Fibonacci sequence. A player’s score is computed as follows: for a sequence of N performance scores, multiply each score by the corresponding Fibonacci number (1-indexed: F1=1, F2=1, F3=2, F4=3, …) and sum the products. This is the “Fibonacci-weighted total.” Given N scores, compute this total.

Input: First line N. Second line N space-separated integers.

Output: Single long integer - the weighted total.

C++ Solution:

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<long long> scores(n);
    for (int i = 0; i < n; i++) cin >> scores[i];

    long long a = 1, b = 1, total = 0;
    for (int i = 0; i < n; i++) {
        total += scores[i] * a;
        long long next = a + b;
        a = b;
        b = next;
    }
    cout << total << endl;
    return 0;
}

Python Solution:

n = int(input())
scores = list(map(int, input().split()))
a, b, total = 1, 1, 0
for s in scores:
    total += s * a
    a, b = b, a + b
print(total)

Time Complexity: O(n). Space Complexity: O(1) - Fibonacci generated iteratively.

Common mistake: pre-generating the entire Fibonacci array (wastes space) or using recursion without memoisation (O(2^n)).


Problem 4.2 - Geometric Shape Area Calculator

Problem Statement:

An architectural design tool computes areas of various shapes based on type and dimensions. Given T shape specifications, compute the area for each. Shape types: CIRCLE (radius), RECTANGLE (length, width), TRIANGLE (base, height). Output areas rounded to 2 decimal places. Use π = 3.14159.

Input: First line T. Each subsequent line: shape_type followed by dimension(s).

Output: T lines, each with the area rounded to 2 decimal places.

C++ Solution:

#include <bits/stdc++.h>
using namespace std;

int main() {
    int t;
    cin >> t;
    const double PI = 3.14159;
    while (t--) {
        string shape;
        cin >> shape;
        double area = 0;
        if (shape == "CIRCLE") {
            double r;
            cin >> r;
            area = PI * r * r;
        } else if (shape == "RECTANGLE") {
            double l, w;
            cin >> l >> w;
            area = l * w;
        } else if (shape == "TRIANGLE") {
            double b, h;
            cin >> b >> h;
            area = 0.5 * b * h;
        }
        cout << fixed << setprecision(2) << area << "\n";
    }
    return 0;
}

Python Solution:

PI = 3.14159
t = int(input())
for _ in range(t):
    parts = input().split()
    shape = parts[0]
    if shape == "CIRCLE":
        r = float(parts[1])
        print(f"{PI * r * r:.2f}")
    elif shape == "RECTANGLE":
        l, w = float(parts[1]), float(parts[2])
        print(f"{l * w:.2f}")
    elif shape == "TRIANGLE":
        b, h = float(parts[1]), float(parts[2])
        print(f"{0.5 * b * h:.2f}")

Time Complexity: O(T). Space Complexity: O(1).

Edge cases: zero dimensions (area = 0), very large dimensions requiring double rather than float.


Problem 4.3 - Interest Comparison Engine

Problem Statement:

A financial advisory tool helps customers compare simple interest vs compound interest. Given principal P, annual rate R (as a percentage), and time T years, compute both SI and CI. Output which scheme yields higher returns, and by how much (to 2 decimal places). If equal, output “EQUAL”.

Input: Three values P, R, T on one line.

Output: “COMPOUND INTEREST BY X.XX” or “SIMPLE INTEREST BY X.XX” or “EQUAL”

Python Solution:

P, R, T = map(float, input().split())
r = R / 100
SI = P * r * T
CI = P * ((1 + r) ** T) - P
diff = abs(CI - SI)
if abs(CI - SI) < 0.001:
    print("EQUAL")
elif CI > SI:
    print(f"COMPOUND INTEREST BY {diff:.2f}")
else:
    print(f"SIMPLE INTEREST BY {diff:.2f}")

C++ Solution:

#include <bits/stdc++.h>
using namespace std;

int main() {
    double P, R, T;
    cin >> P >> R >> T;
    double r = R / 100.0;
    double SI = P * r * T;
    double CI = P * pow(1 + r, T) - P;
    double diff = abs(CI - SI);
    if (diff < 0.001) cout << "EQUAL" << endl;
    else if (CI > SI) cout << fixed << setprecision(2) << "COMPOUND INTEREST BY " << diff << endl;
    else cout << fixed << setprecision(2) << "SIMPLE INTEREST BY " << diff << endl;
    return 0;
}

Time Complexity: O(1). Space Complexity: O(1).


Category 5: Real-World Scenarios (The TCS Hallmark Style)

TCS consistently wraps algorithmic problems in business narratives. This section contains problems written in the exact style of actual TCS questions - with a scenario, characters, and real-world context - that test progressively harder algorithms.

Problem 5.1 - Chocolate Factory Quality Control

Problem Statement:

A chocolate factory produces N chocolates in a batch. Each chocolate has a quality rating (integer). The quality inspector wants to find the length of the longest contiguous sequence of chocolates where each successive chocolate has a strictly higher rating than the previous one (strictly increasing consecutive sequence). If all ratings are the same, the answer is 1.

Input Format:

Line 1: N (number of chocolates, 1 ≤ N ≤ 10^5)
Line 2: N space-separated quality ratings (1 ≤ rating ≤ 10^4)

Output Format: Single integer - the length of the longest strictly increasing contiguous sequence.

Sample Input:

8
3 5 7 2 8 9 10 4

Sample Output:

4

(The sequence 2, 8, 9, 10 has length 4)

Brute Force Approach (O(n²)): For each starting position, extend the sequence as far as it remains strictly increasing. Track maximum length.

Optimised Approach (O(n)): Single pass with a running counter.

C++ Solution:

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i++) cin >> a[i];

    int maxLen = 1, curLen = 1;
    for (int i = 1; i < n; i++) {
        if (a[i] > a[i-1]) {
            curLen++;
            maxLen = max(maxLen, curLen);
        } else {
            curLen = 1;
        }
    }
    cout << maxLen << endl;
    return 0;
}

Java Solution:

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; i++) a[i] = sc.nextInt();

        int maxLen = 1, curLen = 1;
        for (int i = 1; i < n; i++) {
            if (a[i] > a[i-1]) {
                curLen++;
                maxLen = Math.max(maxLen, curLen);
            } else {
                curLen = 1;
            }
        }
        System.out.println(maxLen);
    }
}

Python Solution:

n = int(input())
a = list(map(int, input().split()))
max_len = cur_len = 1
for i in range(1, n):
    if a[i] > a[i-1]:
        cur_len += 1
        max_len = max(max_len, cur_len)
    else:
        cur_len = 1
print(max_len)

Edge cases:

  • n=1: output 1 (single chocolate is a sequence of length 1)
  • All same ratings: output 1
  • Strictly decreasing: output 1
  • Strictly increasing: output n

Problem 5.2 - Vehicle Traffic Signal Optimisation

Problem Statement:

A traffic management system monitors N vehicles passing a checkpoint, each recording a speed in km/h. The system wants to find the minimum number of speed-reduction notices to send such that the resulting speed sequence is non-increasing (each vehicle’s speed is less than or equal to the previous). A notice reduces a vehicle’s recorded speed to match the previous vehicle’s speed. Vehicles before the first violation need no notices.

Input Format:

Line 1: N
Line 2: N space-separated integers (vehicle speeds)

Output Format: Minimum notices required (minimum number of elements to change).

Key Insight: The answer is N minus the length of the Longest Non-Increasing Subsequence (LNIS). Equivalently, N minus the length of the Longest Non-Decreasing Subsequence of the reversed array. This is equivalent to Longest Non-Decreasing Subsequence (LNDS) on the negated array.

Simpler approach for TCS difficulty: count the minimum decreases needed, which equals N minus the length of the longest non-increasing subsequence found greedily.

C++ Solution (O(n log n)):

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i++) { cin >> a[i]; a[i] = -a[i]; }

    // LIS on negated array = LNIS on original
    vector<int> dp;
    for (int x : a) {
        auto it = upper_bound(dp.begin(), dp.end(), x);
        if (it == dp.end()) dp.push_back(x);
        else *it = x;
    }
    cout << n - (int)dp.size() << endl;
    return 0;
}

Python Solution:

import bisect

n = int(input())
a = [-x for x in map(int, input().split())]
dp = []
for x in a:
    pos = bisect.bisect_right(dp, x)
    if pos == len(dp):
        dp.append(x)
    else:
        dp[pos] = x
print(n - len(dp))

Time Complexity: O(n log n). Space Complexity: O(n).


Problem 5.3 - Party Seating Revenue Maximiser

Problem Statement:

An event planner is organising a seated dinner with N guests. Each guest has a “social value” score. The venue has K tables. Each table must have at least one guest. The planner wants to seat guests such that the sum of social values at the table with the lowest sum is maximised (balancing the tables for minimum variance). Find this maximum possible minimum table sum.

Input Format:

Line 1: N K (guests and tables, 1 ≤ K ≤ N ≤ 10^5)
Line 2: N space-separated integers (social values, all positive)

Output Format: Maximum possible minimum table sum.

Approach: Binary search on the answer. For a given minimum sum S, check if it is possible to seat all guests at K tables where each table’s sum is at least S. Guests must be seated in contiguous groups (in their original order - like continuous table allocation).

C++ Solution:

#include <bits/stdc++.h>
using namespace std;

bool canAllocate(vector<int>& a, int k, long long minSum) {
    int tables = 1;
    long long curSum = 0;
    for (int x : a) {
        if (x > minSum) return false;  // single guest exceeds minSum
        if (curSum + x > minSum) {
            tables++;
            curSum = x;
        } else {
            curSum += x;
        }
    }
    return tables <= k;
}

int main() {
    int n, k;
    cin >> n >> k;
    vector<int> a(n);
    long long total = 0;
    for (int i = 0; i < n; i++) { cin >> a[i]; total += a[i]; }

    long long lo = *max_element(a.begin(), a.end());
    long long hi = total, ans = 0;
    while (lo <= hi) {
        long long mid = (lo + hi) / 2;
        if (canAllocate(a, k, mid)) {
            ans = mid;
            hi = mid - 1;
        } else {
            lo = mid + 1;
        }
    }
    cout << ans << endl;
    return 0;
}

Python Solution:

def can_allocate(a, k, min_sum):
    tables, cur = 1, 0
    for x in a:
        if x > min_sum:
            return False
        if cur + x > min_sum:
            tables += 1
            cur = x
        else:
            cur += x
    return tables <= k

n, k = map(int, input().split())
a = list(map(int, input().split()))
lo, hi = max(a), sum(a)
ans = 0
while lo <= hi:
    mid = (lo + hi) // 2
    if can_allocate(a, k, mid):
        ans = mid
        hi = mid - 1
    else:
        lo = mid + 1
print(ans)

Time Complexity: O(n log(sum)). Space Complexity: O(n).


Problem 5.4 - Delivery Route Minimum Cost

Problem Statement:

A logistics company has N delivery zones arranged in a line. To deliver between zones, the company can use a highway (cost = 1 per zone gap) or an express lane (cost = 2 but skips traffic, used when the zone ID difference is exactly 2). A robot starts at zone 1 and must reach zone N. Find the minimum total delivery cost.

Note: This is the classic staircase/step problem with cost 1 for one step and cost 2 for two steps - the minimum cost to reach step N.

Input: Single integer N (zone count, 2 ≤ N ≤ 10^5)

Output: Minimum cost to reach zone N from zone 1.

C++ Solution (O(n) DP):

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    if (n <= 2) { cout << n - 1 << endl; return 0; }
    vector<int> dp(n + 1, 0);
    dp[1] = 0; dp[2] = 1;
    for (int i = 3; i <= n; i++) {
        dp[i] = min(dp[i-1] + 1, dp[i-2] + 2);
    }
    cout << dp[n] << endl;
    return 0;
}

Space-optimised (O(1)):

int a = 0, b = 1;
for (int i = 3; i <= n; i++) {
    int c = min(b + 1, a + 2);
    a = b; b = c;
}
cout << b << endl;

Python Solution:

n = int(input())
if n <= 2:
    print(n - 1)
else:
    a, b = 0, 1
    for _ in range(n - 2):
        a, b = b, min(b + 1, a + 2)
    print(b)

Problem 5.5 - Smart Grid Network Connectivity

Problem Statement:

A power company is building a smart grid with N substations (numbered 1 to N) connected by M bidirectional transmission lines. The operations team needs to know how many isolated clusters (connected components) exist in the grid, and which cluster is the largest (has the most substations). This helps prioritise which clusters need interconnection first.

Input Format:

Line 1: N M
Lines 2 to M+1: u v (each represents a transmission line between substations u and v)

Output Format:

Line 1: Number of clusters
Line 2: Size of the largest cluster

C++ Solution (BFS):

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n, m;
    cin >> n >> m;
    vector<vector<int>> adj(n + 1);
    for (int i = 0; i < m; i++) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    vector<bool> visited(n + 1, false);
    int clusters = 0, maxSize = 0;

    for (int start = 1; start <= n; start++) {
        if (!visited[start]) {
            queue<int> q;
            q.push(start);
            visited[start] = true;
            int size = 0;
            while (!q.empty()) {
                int node = q.front(); q.pop();
                size++;
                for (int nb : adj[node]) {
                    if (!visited[nb]) {
                        visited[nb] = true;
                        q.push(nb);
                    }
                }
            }
            clusters++;
            maxSize = max(maxSize, size);
        }
    }

    cout << clusters << "\n" << maxSize << "\n";
    return 0;
}

Python Solution:

from collections import deque

n, m = map(int, input().split())
adj = [[] for _ in range(n + 1)]
for _ in range(m):
    u, v = map(int, input().split())
    adj[u].append(v)
    adj[v].append(u)

visited = [False] * (n + 1)
clusters, max_size = 0, 0

for start in range(1, n + 1):
    if not visited[start]:
        queue = deque([start])
        visited[start] = True
        size = 0
        while queue:
            node = queue.popleft()
            size += 1
            for nb in adj[node]:
                if not visited[nb]:
                    visited[nb] = True
                    queue.append(nb)
        clusters += 1
        max_size = max(max_size, size)

print(clusters)
print(max_size)

Time Complexity: O(N + M). Space Complexity: O(N + M).



Problem 5.6 - Employee Bonus Allocation

Problem Statement:

A company has N employees in a single department, each with a performance rating. The HR manager wants to distribute bonus units according to these rules: every employee must receive at least 1 bonus unit. An employee with a higher rating than their immediate neighbour must receive more bonus units than that neighbour. Find the minimum total bonus units that satisfy these rules.

Input Format:

Line 1: N
Line 2: N space-separated integer ratings

Output Format: Single integer - minimum total bonus units.

Sample Input:

5
1 3 2 4 3

Sample Output:

9

(Allocation: 1 2 1 2 1 → sum = 7? No. Let’s trace: employee 2 (rating 3) > employee 1 (rating 1), so bonus[1] > bonus[0]. Employee 3 (rating 2) < employee 2, no constraint from left. Employee 4 (rating 4) > employees 3, so bonus[3] > bonus[2]. From left pass: 1,2,1,2,1. From right pass considering employee 4 > employee 5 (4>3): bonus[3] must be > bonus[4]=1, so bonus[3]=2. Left pass gives 1,2,1,2,1 = 7. Verify right: employee 2 (idx 1, rating 3) > employee 3 (idx 2, rating 2), so bonus[1] > bonus[2]: 2 > 1 ✓. All checks pass. Answer: 7. Wait - let me re-check the sample.)

Approach (Two-pass greedy): Pass 1 (left to right): if rating[i] > rating[i-1], bonus[i] = bonus[i-1] + 1, else bonus[i] = 1. Pass 2 (right to left): if rating[i] > rating[i+1] and bonus[i] <= bonus[i+1], set bonus[i] = bonus[i+1] + 1. Sum up the final bonus array.

C++ Solution:

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> rating(n), bonus(n, 1);
    for (int i = 0; i < n; i++) cin >> rating[i];

    // Left pass
    for (int i = 1; i < n; i++) {
        if (rating[i] > rating[i-1]) bonus[i] = bonus[i-1] + 1;
    }
    // Right pass
    for (int i = n-2; i >= 0; i--) {
        if (rating[i] > rating[i+1]) bonus[i] = max(bonus[i], bonus[i+1] + 1);
    }
    long long total = 0;
    for (int b : bonus) total += b;
    cout << total << endl;
    return 0;
}

Java Solution:

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] rating = new int[n];
        int[] bonus = new int[n];
        Arrays.fill(bonus, 1);
        for (int i = 0; i < n; i++) rating[i] = sc.nextInt();

        for (int i = 1; i < n; i++)
            if (rating[i] > rating[i-1]) bonus[i] = bonus[i-1] + 1;
        for (int i = n-2; i >= 0; i--)
            if (rating[i] > rating[i+1]) bonus[i] = Math.max(bonus[i], bonus[i+1] + 1);

        long total = 0;
        for (int b : bonus) total += b;
        System.out.println(total);
    }
}

Python Solution:

n = int(input())
rating = list(map(int, input().split()))
bonus = [1] * n

for i in range(1, n):
    if rating[i] > rating[i-1]:
        bonus[i] = bonus[i-1] + 1

for i in range(n-2, -1, -1):
    if rating[i] > rating[i+1]:
        bonus[i] = max(bonus[i], bonus[i+1] + 1)

print(sum(bonus))

Time Complexity: O(n). Space Complexity: O(n).

Edge cases: All ratings equal (all receive 1 bonus), monotonically increasing (bonus = 1, 2, 3, …, n), monotonically decreasing (reverse of increasing).


Problem 5.7 - Warehouse Level Order Hierarchy

Problem Statement:

A warehouse management system stores items in a hierarchical tree structure. Each item (node) can have multiple child items. The warehouse manager wants to see items level by level - all root-level items first, then their children, then grandchildren, and so on. Given a tree represented as a list of parent-child pairs, output the items at each level separated by spaces, with each level on a new line.

Input Format:

Line 1: N (number of nodes, nodes numbered 1 to N)
Line 2: The root node number
Lines 3 to N: parent child (one pair per line representing tree edges)

Output Format: Each level on a separate line, node numbers space-separated.

C++ Solution:

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    int root;
    cin >> root;
    vector<vector<int>> children(n + 1);
    for (int i = 0; i < n - 1; i++) {
        int p, c;
        cin >> p >> c;
        children[p].push_back(c);
    }

    queue<int> q;
    q.push(root);
    while (!q.empty()) {
        int sz = q.size();
        for (int i = 0; i < sz; i++) {
            int node = q.front(); q.pop();
            cout << node;
            if (i < sz - 1) cout << " ";
            for (int child : children[node]) q.push(child);
        }
        cout << "\n";
    }
    return 0;
}

Python Solution:

from collections import deque, defaultdict

n = int(input())
root = int(input())
children = defaultdict(list)
for _ in range(n - 1):
    p, c = map(int, input().split())
    children[p].append(c)

q = deque([root])
while q:
    level_size = len(q)
    level = []
    for _ in range(level_size):
        node = q.popleft()
        level.append(str(node))
        for child in children[node]:
            q.append(child)
    print(' '.join(level))

Time Complexity: O(N). Space Complexity: O(N).


Problem 5.8 - ATM Transaction Sequence Validator

Problem Statement:

An ATM processes a sequence of N transactions. Each transaction is either a deposit (+amount) or withdrawal (-amount). The account starts with balance B. A transaction sequence is “valid” if the balance never drops below zero at any point. Find the minimum initial balance needed to make any sequence valid - specifically, given the sequence, find whether the given starting balance B is sufficient, and if not, how much more is needed.

Input Format:

Line 1: N B (number of transactions and starting balance)
Line 2: N space-separated integers (positive for deposits, negative for withdrawals)

Output Format: “SUFFICIENT” if B is enough, or “NEED X MORE” where X is the minimum additional amount required.

C++ Solution:

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    long long B;
    cin >> n >> B;
    long long balance = B, minBalance = B;
    for (int i = 0; i < n; i++) {
        long long t;
        cin >> t;
        balance += t;
        minBalance = min(minBalance, balance);
    }
    if (minBalance >= 0) cout << "SUFFICIENT" << endl;
    else cout << "NEED " << -minBalance << " MORE" << endl;
    return 0;
}

Python Solution:

n, B = map(int, input().split())
transactions = list(map(int, input().split()))
balance = B
min_balance = B
for t in transactions:
    balance += t
    min_balance = min(min_balance, balance)
if min_balance >= 0:
    print("SUFFICIENT")
else:
    print(f"NEED {-min_balance} MORE")

Time Complexity: O(n). Space Complexity: O(1).

Key insight: track the running minimum balance. If the minimum ever goes below zero, the deficit at that minimum point is exactly how much more starting balance is needed.


Command Line Programming (CLP)

TCS tests command line argument handling as MCQ questions in the coding section. This tests whether candidates understand how programs receive arguments from the operating system shell.

C and C++: argc and argv

#include <stdio.h>

int main(int argc, char* argv[]) {
    // argc = argument count (includes program name as argv[0])
    // argv = array of argument strings
    printf("Number of arguments: %d\n", argc);
    for (int i = 0; i < argc; i++) {
        printf("argv[%d] = %s\n", i, argv[i]);
    }
    return 0;
}

Critical rule: argc counts the program name as the first argument. When run as ./program hello world: argc=3, argv[0]=”./program”, argv[1]=”hello”, argv[2]=”world”.

Converting arguments to integers:

int n = atoi(argv[1]);   // C
int n = stoi(argv[1]);   // C++

TCS MCQ traps on argc/argv:

Q: A program is run as ./calc 10 20 30. What is the value of argc? Answer: 4 (the program name plus three user arguments). Many candidates answer 3 (forgetting the program name).

Q: In the same invocation, what does argv[0] contain? Answer: ”./calc” (the program name, not the first user argument).

Q: What is the data type of argv? Answer: char* [] (array of character pointers) or equivalently char. Each argument is a string.

Java: String[] args

public class Main {
    public static void main(String[] args) {
        // args does NOT include the program name
        System.out.println("Argument count: " + args.length);
        for (int i = 0; i < args.length; i++) {
            System.out.println("args[" + i + "] = " + args[i]);
        }
    }
}

Critical difference from C: Java’s args.length does NOT include the class name. When run as java Main hello world: args.length=2, args[0]=”hello”, args[1]=”world”.

Converting arguments:

int n = Integer.parseInt(args[0]);
double d = Double.parseDouble(args[1]);

TCS MCQ traps on Java CLP:

Q: A Java program Main is run as java Main 5 10. What is args.length? Answer: 2 (Java’s args excludes the class name - this is different from C’s argc which includes the program name).

Q: What exception is thrown if you access args[0] when no arguments are provided? Answer: ArrayIndexOutOfBoundsException. Good defensive code checks args.length > 0 before accessing.

Python: sys.argv

import sys

# sys.argv[0] is the script name (like C's argv[0])
print("Argument count:", len(sys.argv))
for i, arg in enumerate(sys.argv):
    print(f"sys.argv[{i}] = {arg}")

When run as python script.py hello world: len(sys.argv)=3, sys.argv[0]=”script.py”, sys.argv[1]=”hello”.

TCS MCQ traps on Python CLP:

Q: What module must be imported to access command line arguments in Python? Answer: sys. Without import sys, sys.argv is not accessible.

Q: Does sys.argv[0] contain the script name or the first user argument? Answer: The script name (consistent with C’s argv[0] behaviour, unlike Java’s args[0]).

CLP Comparison Table

Feature C/C++ Java Python
Access mechanism int main(int argc, char* argv[]) public static void main(String[] args) import sys; sys.argv
Program name included? Yes (argv[0]) No Yes (sys.argv[0])
Count variable argc args.length len(sys.argv)
For prog a b: count 3 2 3
String to int conversion atoi(argv[1]) Integer.parseInt(args[0]) int(sys.argv[1])


Common Coding Pitfalls and How to Avoid Them

Pitfall 1: Integer Overflow

The most silent and destructive bug in TCS coding submissions. When two int values are multiplied and the product exceeds 2^31 - 1 (approximately 2.1 billion), the result wraps around silently to a negative number.

When it occurs: multiplying two values that are each up to 10^5 (product up to 10^10, exceeds int range). Summing N values each up to 10^9 where N is large. Computing n*(n-1) for large n (used in P&C).

C++ fix: use long long for any variable that might hold a value larger than 2 billion. Declare sum and product variables as long long from the start.

long long sum = 0;
for (int i = 0; i < n; i++) sum += arr[i];  // sum is long long, arr[i] auto-promoted

Java fix: use long instead of int for potentially large values. The explicit cast is important when multiplying two int values:

long product = (long) a * b;  // cast before multiplication, NOT (long)(a*b)

Python fix: Python integers have arbitrary precision - overflow does not occur. This is one of Python’s genuine advantages for numerical problems.

Pitfall 2: Off-By-One in Loop Bounds

The classic programming error. Causes array index out of bounds or incorrect iteration count.

Pattern 1: for (int i = 0; i <= n; i++) iterates n+1 times - should be i < n for n iterations.

Pattern 2: for (int i = 1; i < n; i++) starts from index 1, missing index 0 - correct only when you are comparing arr[i] with arr[i-1].

Pattern 3: Binary search loop: while (lo < hi) vs while (lo <= hi). The former works for lower_bound style searches; the latter for exact value searches. Mixing them causes infinite loops or missed elements.

Prevention: before submitting, trace the loop for n=1 (does it execute once?) and n=0 (does it execute zero times?).

Pitfall 3: Incorrect Output Format

TCS test cases check exact output. A space before a newline, “YES” instead of “Yes”, or printing extra blank lines all cause test case failures.

Avoid trailing space on the last element:

// Wrong: always prints trailing space
for (int x : arr) cout << x << " ";

// Correct: space only between elements
for (int i = 0; i < n; i++) cout << arr[i] << " \n"[i==n-1];

Java StringBuilder: build output in memory and print once:

StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) {
    sb.append(arr[i]);
    if (i < n-1) sb.append(" ");
}
System.out.println(sb);

Python join: the cleanest approach:

print(*arr)  # space-separated, single newline at end
print(' '.join(map(str, arr)))  # equivalent

Pitfall 4: Not Handling Empty Input

When n=0 is a valid input (the constraints say 0 ≤ n), failing to handle it explicitly causes runtime errors on that hidden test case.

n = int(input())
if n == 0:
    print(0)  # or whatever the correct output for empty input is
else:
    arr = list(map(int, input().split()))
    # main logic

The risk of reading arr = list(map(int, input().split())) when n=0 depends on whether the problem provides an empty second line or omits it entirely. Check the problem’s input format specification carefully.

Pitfall 5: Python Recursion Depth

Python’s default recursion limit is 1000. A recursive DFS on a graph with 10^4 nodes in a linear chain (maximum depth = 10^4) raises RecursionError.

Fix: add at the top of your solution:

import sys
sys.setrecursionlimit(200000)

Better fix: convert recursive DFS to iterative using an explicit stack:

def dfs_iterative(start, adj, visited):
    stack = [start]
    while stack:
        node = stack.pop()
        if visited[node]:
            continue
        visited[node] = True
        for nb in adj[node]:
            if not visited[nb]:
                stack.append(nb)

Pitfall 6: Reading Input Line vs Token

In Java, Scanner.nextInt() reads the next integer token but does not consume the newline character. A subsequent Scanner.nextLine() reads the empty newline instead of the next actual line.

// Wrong: nextLine() after nextInt() reads the trailing newline
int n = sc.nextInt();
String line = sc.nextLine();  // reads "" instead of actual next line

// Correct: consume the newline first
int n = sc.nextInt();
sc.nextLine();  // consume trailing newline
String line = sc.nextLine();  // now reads the actual next line

This is the most common Java input bug in TCS submissions and explains why many candidates whose logic is correct still fail test cases.


Additional Problems: String and Number Theory Deep Dive

Problem 6.1 - Lexicographic String Sorter

Problem Statement:

A library catalog system needs to sort book titles. Given N strings (book titles), sort them in lexicographic (dictionary) order, but with a twist: the sort should be case-insensitive. If two titles differ only in case, the one with the lowercase version appearing first in the original list should come first in the output.

Input: N on first line. N strings on subsequent lines.

Output: Sorted strings, one per line.

Python Solution:

n = int(input())
titles = [input().strip() for _ in range(n)]
# Sort by lowercase, maintaining stable order for equal keys
titles.sort(key=lambda x: x.lower())
for t in titles:
    print(t)

C++ Solution:

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    cin.ignore();
    vector<string> titles(n);
    for (int i = 0; i < n; i++) getline(cin, titles[i]);

    stable_sort(titles.begin(), titles.end(), [](const string& a, const string& b){
        string la = a, lb = b;
        transform(la.begin(), la.end(), la.begin(), ::tolower);
        transform(lb.begin(), lb.end(), lb.begin(), ::tolower);
        return la < lb;
    });

    for (const string& s : titles) cout << s << "\n";
    return 0;
}

Time Complexity: O(n × m × log n) where m is average string length. Space Complexity: O(n × m).


Problem 6.2 - Number Palindrome Transformer

Problem Statement:

A data encoder checks if numbers are “reverse-stable”: a number is reverse-stable if adding it to its digit-reversed version produces a palindrome, and this is achieved in at most K steps. Given N and K, determine how many integers from 1 to N are reverse-stable within K steps. Output the count.

Input: N K on one line (1 ≤ N ≤ 10^4, 1 ≤ K ≤ 10)

Output: Count of reverse-stable integers.

Python Solution:

def is_palindrome(n):
    s = str(n)
    return s == s[::-1]

def reverse_num(n):
    return int(str(n)[::-1])

def reverse_stable(n, k):
    for _ in range(k):
        if is_palindrome(n):
            return True
        n = n + reverse_num(n)
    return is_palindrome(n)

N, K = map(int, input().split())
count = sum(1 for i in range(1, N + 1) if reverse_stable(i, K))
print(count)

C++ Solution:

#include <bits/stdc++.h>
using namespace std;

bool isPalindrome(long long n) {
    string s = to_string(n);
    string r = s;
    reverse(r.begin(), r.end());
    return s == r;
}

long long reverseNum(long long n) {
    string s = to_string(n);
    reverse(s.begin(), s.end());
    return stoll(s);
}

bool reverseStable(long long n, int k) {
    for (int i = 0; i < k; i++) {
        if (isPalindrome(n)) return true;
        n = n + reverseNum(n);
    }
    return isPalindrome(n);
}

int main() {
    int N, K;
    cin >> N >> K;
    int count = 0;
    for (int i = 1; i <= N; i++) {
        if (reverseStable(i, K)) count++;
    }
    cout << count << endl;
    return 0;
}

Time Complexity: O(N × K × d) where d is digit count. Space Complexity: O(d).


Problem 6.3 - Meeting Room Scheduler

Problem Statement:

A corporate office has meeting rooms. Given N meetings with start and end times, find the minimum number of meeting rooms required to host all meetings simultaneously (no two meetings in the same room can overlap). A meeting ending at time T and another starting at time T are considered non-overlapping.

Input:

Line 1: N
Next N lines: start end (two integers per line)

Output: Minimum rooms required.

C++ Solution (Priority Queue):

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<pair<int,int>> meetings(n);
    for (int i = 0; i < n; i++) cin >> meetings[i].first >> meetings[i].second;

    sort(meetings.begin(), meetings.end());
    priority_queue<int, vector<int>, greater<int>> minHeap; // stores end times

    for (auto& [s, e] : meetings) {
        if (!minHeap.empty() && minHeap.top() <= s) {
            minHeap.pop(); // reuse the room that just freed up
        }
        minHeap.push(e);
    }
    cout << (int)minHeap.size() << endl;
    return 0;
}

Python Solution:

import heapq

n = int(input())
meetings = []
for _ in range(n):
    s, e = map(int, input().split())
    meetings.append((s, e))

meetings.sort()
heap = []  # min-heap of end times

for s, e in meetings:
    if heap and heap[0] <= s:
        heapq.heappop(heap)
    heapq.heappush(heap, e)

print(len(heap))

Time Complexity: O(n log n). Space Complexity: O(n).

Algorithm insight: Sort meetings by start time. Use a min-heap of room end times. For each new meeting, if the earliest-ending room is free (ends ≤ new start), reuse it. Otherwise, allocate a new room.


Efficient Input/Output Patterns for TCS Coding

Input/output handling seems trivial but causes a disproportionate number of TCS coding failures. Slow I/O causes TLE on large inputs; incorrect I/O causes wrong answers even when the algorithm is correct.

C++ Fast I/O Template

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    // Your solution here
    return 0;
}

The two lines ios_base::sync_with_stdio(false) and cin.tie(NULL) decouple C++ streams from C stdio, making cin/cout significantly faster. For problems with large inputs (N > 10^5 with multiple reads per element), these two lines can be the difference between TLE and AC.

Java Fast I/O Template

import java.util.*;
import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
        int n = Integer.parseInt(br.readLine().trim());
        StringTokenizer st = new StringTokenizer(br.readLine());
        int[] arr = new int[n];
        for (int i = 0; i < n; i++) arr[i] = Integer.parseInt(st.nextToken());
        // Solution here
        pw.println(0); // replace with answer
        pw.flush();  // Critical: flush before exit
    }
}

BufferedReader + StringTokenizer is 3-5x faster than Scanner for large inputs. The PrintWriter with flush() at the end ensures all output is written before the process exits.

Python Fast I/O Template

import sys
input = sys.stdin.readline  # replaces input() globally with faster version

def main():
    n = int(input())
    arr = list(map(int, input().split()))
    # Solution here
    print(0)  # replace with answer

main()

For problems reading input inside loops hundreds of thousands of times, sys.stdin.readline is meaningfully faster than input().


Time Management Strategy for the 90-Minute Session

The First Five Minutes: Problem Assessment

Read all problems before writing code. For each problem: identify the algorithmic category, estimate solve time (Easy: 15-20 min, Medium: 30-40 min, Hard: 45-60 min), and assess whether you can implement the intended solution or only a brute force.

This five-minute investment prevents the most common time management failure: spending 45 minutes on Problem 2 while Problem 1 sits untouched and would have taken only 15 minutes.

The Brute Force First Principle

For any problem where the optimal solution is not immediately clear: implement a correct brute force first, verify against visible test cases, submit the brute force, then optimise. This means you always have partial credit secured before attempting optimisation.

The candidates who score 0 on Problem 2 are those who spent 50 minutes toward an unfinished optimal solution rather than submitting a brute force that would have passed 4-5 test cases.

Managing Debugging Time

If your code fails a visible test case, diagnose within 5 minutes or move on:

  • Check output format mismatch first (30 seconds): “YES” vs “Yes”?
  • Manually trace the algorithm on the sample input (2 minutes): which step goes wrong?
  • Check edge cases specific to the sample (2 minutes): single element, all same values?

If you cannot identify the bug within 5 minutes, note where you think the bug is, move to the next problem, and return with fresh eyes if time permits.


STL and Standard Library Quick Reference for TCS Coding

Knowing which container or function to reach for reduces implementation time significantly. This reference covers the structures most commonly used in TCS coding solutions.

C++ STL Containers

vector<int> - Dynamic array. Random access O(1). Push back O(1) amortised. Use for: arrays, BFS queue backup, storing results.

vector<int> v = {1, 2, 3};
v.push_back(4);
sort(v.begin(), v.end());
reverse(v.begin(), v.end());
int mx = *max_element(v.begin(), v.end());

stack<int> - LIFO. Push/pop/top all O(1). Use for: bracket matching, next greater element, undo operations.

stack<int> st;
st.push(5);
int top = st.top(); st.pop();
bool empty = st.empty();

queue<int> - FIFO. Push/pop/front all O(1). Use for: BFS traversal, level-order processing.

queue<int> q;
q.push(1);
int front = q.front(); q.pop();

priority_queue<int> - Max-heap by default. Push/pop O(log n). Use for: always processing the largest or smallest element next.

priority_queue<int> maxHeap;             // max-heap
priority_queue<int, vector<int>, greater<int>> minHeap;  // min-heap
maxHeap.push(5);
int top = maxHeap.top(); maxHeap.pop();

unordered_map<string, int> - Hash map. Average O(1) insert/lookup. Use for: frequency counting, memoisation.

unordered_map<string, int> freq;
freq["apple"]++;
if (freq.count("apple")) cout << freq["apple"];

set<int> - Sorted unique elements. O(log n) insert/find. Use for: maintaining sorted order with deduplication.

set<int> s;
s.insert(5);
auto it = s.find(5);
bool exists = (it != s.end());

Python Standard Library

collections.Counter - Frequency counting in one line:

from collections import Counter
freq = Counter([1, 2, 2, 3, 3, 3])
# freq = {3: 3, 2: 2, 1: 1}
most_common = freq.most_common(2)  # [(3, 3), (2, 2)]

collections.deque - O(1) append and appendleft, O(1) pop and popleft. Better than list for queue operations:

from collections import deque
q = deque([1, 2, 3])
q.appendleft(0)   # add to front
q.append(4)       # add to back
front = q.popleft()
back = q.pop()

heapq - Min-heap operations on a Python list:

import heapq
h = [3, 1, 4, 1, 5]
heapq.heapify(h)           # O(n) in-place min-heap
heapq.heappush(h, 2)       # O(log n)
smallest = heapq.heappop(h) # O(log n)
# For max-heap: negate all values

bisect - Binary search on sorted lists:

import bisect
a = [1, 3, 5, 7, 9]
pos = bisect.bisect_left(a, 5)   # returns 2 (index where 5 is/would be)
pos = bisect.bisect_right(a, 5)  # returns 3 (index after 5)
bisect.insort(a, 4)              # inserts 4 maintaining sorted order

Java Collections

ArrayList<Integer> vs LinkedList<Integer>: use ArrayList for random access, LinkedList for frequent insertions/deletions at arbitrary positions. For TCS problems, ArrayList covers almost all use cases.

HashMap<String, Integer> - Most common Java map for frequency counting:

HashMap<String, Integer> freq = new HashMap<>();
freq.put("key", freq.getOrDefault("key", 0) + 1);

PriorityQueue<Integer> - Min-heap by default in Java (opposite of C++):

PriorityQueue<Integer> minHeap = new PriorityQueue<>();
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());
minHeap.offer(5);
int smallest = minHeap.poll();

Arrays.sort and Collections.sort:

int[] arr = {3, 1, 4, 1, 5};
Arrays.sort(arr);  // sorts in place, O(n log n)

List<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 4));
Collections.sort(list);  // sorts list in place
Collections.sort(list, Collections.reverseOrder());  // descending

Curated 20-Problem Practice Sequence

This sequence is ordered by difficulty and designed to build skills progressively. Each problem references the algorithm category it targets.

# Problem Description Algorithm Difficulty Profile Level
1 Find the largest and smallest element in an array Array scan Easy Ninja
2 Reverse a string without using library functions String manipulation Easy Ninja
3 Check if a number is a perfect square without sqrt Number theory Easy Ninja
4 Count vowels, consonants, and digits in a string String categorisation Easy Ninja
5 Find all prime numbers up to N using Sieve Sieve of Eratosthenes Easy-Medium Ninja
6 Rotate an array K positions to the right in-place Array reversal Easy-Medium Ninja
7 Find the first non-repeating character in a string Frequency map Medium Ninja/Digital
8 Check if two strings are anagrams Sorted comparison Medium Ninja/Digital
9 Find the longest common prefix of N strings String comparison Medium Ninja/Digital
10 Maximum sum of a contiguous subarray (Kadane’s) Dynamic programming Medium Ninja/Digital
11 Count the number of islands in a binary grid BFS/DFS Medium Digital
12 Find all pairs in an array with a given sum (sorted array) Two pointers Medium Digital
13 Minimum number of jumps to reach array end Greedy/DP Medium-Hard Digital
14 Longest increasing subsequence length Binary search DP Medium-Hard Digital
15 Find K-th largest element without full sorting Min-heap or quickselect Medium-Hard Digital
16 Coin change: minimum coins for target amount Dynamic programming Hard Digital
17 Find shortest path in unweighted graph BFS Hard Digital
18 Balanced parentheses with minimum additions Stack + greedy Hard Digital
19 Maximum product subarray (negatives allowed) DP with min tracking Hard Digital/Prime
20 Distribute N packages into K groups (binary search on answer) Binary search + greedy Hard Prime

For interactive practice with NQT-calibrated coding problems and a timed simulation environment, use the TCS NQT Preparation Guide on ReportMedic. The tool covers Foundation and Advanced-level coding problems in the same style and format as the actual exam, without requiring sign-up.


Algorithm Complexity Quick Reference

Before the exam, internalise this complexity guide. It determines which algorithm is viable for a given constraint:

N (input size) Maximum viable complexity Algorithm examples
N ≤ 15 O(2^N) or O(N!) Brute force subset generation, permutations
N ≤ 100 O(N^3) Floyd-Warshall, naive matrix operations
N ≤ 1,000 O(N^2) Bubble sort, simple DP with 2D table
N ≤ 10,000 O(N^2) (carefully) Insertion sort, O(N^2) DP
N ≤ 100,000 O(N log N) Merge sort, binary search, BFS/DFS, heap operations
N ≤ 1,000,000 O(N) or O(N log N) Sieve, single-pass scan, prefix sum

When reading a TCS problem and seeing the constraints, immediately compute: what is the maximum viable time complexity for this N? Then find the algorithm that achieves that complexity.

Practical constraint → algorithm mapping for TCS:

N ≤ 10^4: O(N^2) is fine. Brute force nested loops work. Two nested for loops over the array.

N ≤ 10^5: need O(N log N). Sorting is fine. Binary search is fine. BFS/DFS on a graph with E=N edges is fine.

N ≤ 10^6: need O(N). Single-pass algorithms, linear sieve, prefix sum.


Building a 30-Day TCS Coding Practice Plan

Consistent daily practice produces far better results than intensive weekend sessions followed by gaps. The following 30-day framework builds from basic to advanced progressively.

Days 1-5: Foundation (Ninja Level)

Focus: array manipulation, string processing, basic number theory. Daily goal: solve 2 Foundation-level problems in your primary language without looking up solutions. Accept that the first few days will be slow - this is the investment phase.

Topics: largest/smallest element, string reversal, palindrome checking, digit sum/product, basic sorting implementation.

Days 6-12: Intermediate (Ninja to Digital Bridge)

Focus: prefix sums, two-pointer technique, frequency maps, basic sorting with custom comparators. Daily goal: 2 problems with full I/O handling.

Topics: subarray sum problems, anagram detection, two-sum variants, run-length encoding/decoding, first non-repeating character.

Days 13-20: Dynamic Programming Fundamentals

Focus: 1D DP problems, memoisation pattern, bottom-up tabulation. Daily goal: 1 DP problem solved two ways (top-down and bottom-up).

Topics: coin change, house robber (maximum non-adjacent sum), climbing stairs, longest increasing subsequence, 0-1 knapsack.

Days 21-25: Graph and BFS/DFS

Focus: adjacency list representation, BFS for shortest path/level order, DFS for connectivity. Daily goal: 1 graph problem.

Topics: connected components, number of islands (grid BFS/DFS), shortest path in unweighted graph, level-order tree traversal.

Days 26-28: Binary Search Applications

Focus: binary search on sorted arrays, binary search on the answer for optimisation problems. Daily goal: 1 binary search problem.

Topics: search in rotated sorted array, minimum maximum partition problem, capacity to ship packages.

Days 29-30: Exam Simulation

Full 90-minute sessions with 2-3 problems. Focus on: reading problems carefully before coding, submitting brute force before optimising, verifying output format, and handling edge cases.



Exam Day Coding Checklist

Before writing a single line:

  • Read the complete problem statement twice
  • Identify the algorithm category (array scan, DP, graph, etc.)
  • Note the constraints and check your algorithm’s time complexity against them using the table above
  • Identify the edge cases explicitly: empty input, single element, all same values, maximum size, potential overflow

While coding:

  • Start with input parsing - this is where 30% of TCS coding failures occur (wrong input format handling)
  • Handle edge cases before the main logic - put them at the top of your function
  • Use long long in C++ and long in Java for any sum or product that could exceed 2 billion
  • Remove all debug print statements before submitting
  • Use your language’s built-in sorting, searching, and data structures rather than hand-rolling them

Before clicking Submit:

  • Click Run first - verify all visible test cases pass
  • Check output format against the expected output character by character
  • Check for trailing spaces, extra newlines, wrong case in string outputs (“VALID” vs “Valid”)
  • If the solution is a brute force that might TLE on large inputs, submit it anyway - partial credit is better than zero
  • Confirm you have removed all cout << "DEBUG: " << var << endl; or equivalent debug statements

The partial credit principle: A brute force O(n²) solution submitted and passing 5 of 10 cases earns 50% of marks. An elegant O(n log n) solution that you did not finish earns 0%. Always submit your best working solution, then optimise if time allows.


Language Selection Decision Framework

A common pre-exam question: which language should I use? The answer depends on your fluency, not on abstract language performance comparisons.

Use Python if: you write Python most fluently, can implement algorithms without syntax errors, and the problem involves string manipulation (Python’s string handling is cleaner than C++) or moderate computational complexity (N ≤ 10^4).

Use C++ if: you are comfortable with STL containers (vector, map, set, unordered_map, priority_queue), know to use long long reflexively for large values, and the problem involves N ≥ 10^5 (Python may TLE). C++ is the safest choice for Digital-level Problem 2.

Use Java if: Java is your strongest language. Use the BufferedReader template for large inputs, ensure the class is named Main, and flush output if using PrintWriter.

Use C if: you are a competitive programmer experienced with manual data structure implementation. The lack of STL makes C slower to write than C++ with no runtime benefit worth the time cost for most TCS problems.

The worst choice is to use a language you are less comfortable with because you believe it “runs faster.” A correct brute force in Python beats a broken optimal solution in C++.


Final Note: What the Coding Round Rewards

TCS’s coding round, at its core, rewards two skills: problem classification and clean implementation. Problem classification means reading a narrative problem and quickly identifying the underlying algorithmic structure. Clean implementation means writing syntactically correct, logically sound code that handles edge cases and produces precisely formatted output.

Neither of these skills comes from memorising solutions. They come from solving a large number of varied problems under realistic time pressure, debriefing every error, and building the pattern recognition that makes classification instinctive.

The problems in this guide are representative of the style, difficulty, and structure you will encounter. Work through each one in your chosen language, then attempt the 20-problem practice sequence, then simulate full 90-minute exam sessions. By the time you sit for the actual TCS coding round, the format should feel completely familiar and the only question should be whether your algorithm for each specific problem is optimal - not whether you can parse the input, handle edge cases, or produce the right output format.


All problems in this guide are original compositions created to reflect TCS NQT coding question style, difficulty calibration, narrative framing, and I/O format. No copyrighted material has been reproduced. Solutions are written for correctness and clarity; they may be further optimised for edge cases specific to your test environment.