Crack TCS 2026 with these Real PYQ coding questions — arrays, strings, logic, and more. Full explanations included. Bookmark this now.

   


Why These 20 Questions?

Every question here has appeared in TCS NQT drives between 2023–2025, sourced from real candidate reports and Campusmonk Final Strike sessions. Each includes a full problem statement, example, approach, Java solution, and complexity.


Q1. Best Time to Buy and Sell Stock


🟠 Medium | Arrays / Greedy

You are given an array prices[] where prices[i] is the stock price on day i. Choose one day to buy and a future day to sell. Return the maximum profit. Return 0 if no profit is possible.

Example

Input: prices = [7, 1, 5, 3, 6, 4] Output: 5 Buy on Day 2 (price=1), Sell on Day 5 (price=6). Profit = 5.

Input: prices = [7, 6, 4, 3, 1] Output: 0

Approach

Track the minimum price seen so far. At every index compute profit = price – minPrice. Update maxProfit. Single pass, no nested loops.

Solution

int maxProfit(int[] prices) {
    int minPrice = Integer.MAX_VALUE, maxProfit = 0;
    for (int price : prices) {
        if (price < minPrice) minPrice = price;
        else maxProfit = Math.max(maxProfit, price - minPrice);
    }
    return maxProfit;
}

Time: O(n) | Space: O(1)


Q2. Product of Array Except Self


🟠 Medium | Arrays / Prefix Product

Given nums[], return array answer[] where answer[i] equals the product of all elements except nums[i]. Must be O(n). Division is NOT allowed.

Example

Input: nums = [1, 2, 3, 4] Output: [24, 12, 8, 6]

Approach

Pass 1 left to right — fill result with left prefix products. Pass 2 right to left — multiply right suffix products using one running variable. No extra array needed.

Solution

int[] productExceptSelf(int[] nums) {
    int n = nums.length;
    int[] result = new int[n];
    result[0] = 1;
    for (int i = 1; i < n; i++)
        result[i] = result[i-1] * nums[i-1];
    int right = 1;
    for (int i = n-1; i >= 0; i--) {
        result[i] *= right;
        right *= nums[i];
    }
    return result;
}

Time: O(n) | Space: O(1)


Q3. First Missing Positive


🔴 Hard | Arrays / Cyclic Sort

Given an unsorted integer array nums[], return the smallest missing positive integer. Must run in O(n) time and O(1) space.

Example

Input: [3, 4, -1, 1] → Output: 2 Input: [7, 8, 9, 11] → Output: 1 Input: [1, 2, 0] → Output: 3

Approach

Use the array itself as a hash map. Place each number x at index x-1 if it is in range [1, n]. Then scan — the first index where nums[i] does not equal i+1 gives the answer.

Solution

int firstMissingPositive(int[] nums) {
    int n = nums.length;
    for (int i = 0; i < n; i++) {
        while (nums[i] > 0 && nums[i] <= n && nums[nums[i]-1] != nums[i]) {
            int tmp = nums[nums[i]-1];
            nums[nums[i]-1] = nums[i];
            nums[i] = tmp;
        }
    }
    for (int i = 0; i < n; i++)
        if (nums[i] != i+1) return i+1;
    return n+1;
}

Time: O(n) | Space: O(1)


Q4. Find the Duplicate Number


🟠 Medium-Hard | Floyd’s Cycle Detection

Array of n+1 integers, values in range [1, n], exactly one number repeats. Find it without modifying the array and using only O(1) extra space.

Example

Input: [1, 3, 4, 2, 2] → Output: 2 Input: [3, 1, 3, 4, 2] → Output: 3

Approach

Treat the array as a linked list where index i points to nums[i]. A duplicate creates a cycle. Phase 1 — slow and fast pointers meet inside the cycle. Phase 2 — reset slow to start, advance both by one step until they meet. That meeting point is the duplicate.

Solution

int findDuplicate(int[] nums) {
    int slow = nums[0], fast = nums[0];
    do {
        slow = nums[slow];
        fast = nums[nums[fast]];
    } while (slow != fast);
    slow = nums[0];
    while (slow != fast) {
        slow = nums[slow];
        fast = nums[fast];
    }
    return slow;
}

Time: O(n) | Space: O(1)


Q5. Find All Duplicates in an Array


🟠 Medium | Index Marking

Given array of length n where all integers are in [1, n], each appearing once or twice. Return all integers that appear twice. O(n) time, O(1) space.

Example

Input: [4, 3, 2, 7, 8, 2, 3, 1] → Output: [2, 3]

Approach

For each number x, go to index abs(x)-1 and negate the value there. If it is already negative, abs(x) has appeared before and is a duplicate. The sign acts as a visited marker.

Solution

List<Integer> findDuplicates(int[] nums) {
    List<Integer> result = new ArrayList<>();
    for (int num : nums) {
        int idx = Math.abs(num) - 1;
        if (nums[idx] < 0) result.add(Math.abs(num));
        else nums[idx] = -nums[idx];
    }
    return result;
}

Time: O(n) | Space: O(1)


Q6. Find Pivot Index


🟠 Medium | Arrays / Prefix Sum

Find the leftmost index where the sum of all elements to its left equals the sum of all elements to its right. Return -1 if none exists.

Example

Input: [1, 7, 3, 6, 5, 6] → Output: 3 Left sum = 1+7+3 = 11. Right sum = 5+6 = 11.

Approach

Compute total sum once. Walk left to right. At each index, rightSum = total – leftSum – nums[i]. If leftSum equals rightSum, return that index.

Solution

int pivotIndex(int[] nums) {
    int total = 0;
    for (int n : nums) total += n;
    int leftSum = 0;
    for (int i = 0; i < nums.length; i++) {
        if (leftSum == total - leftSum - nums[i]) return i;
        leftSum += nums[i];
    }
    return -1;
}

Time: O(n) | Space: O(1)


Q7. Pairs of Songs With Total Duration Divisible by 60


🟠 Medium | Hashing / Modular Arithmetic

Given song durations in seconds, return the count of pairs (i, j) where i < j and (time[i] + time[j]) % 60 == 0.

Example

Input: [30, 20, 150, 100, 40] → Output: 3 Pairs: (30,150)=180, (20,100)=120, (20,40)=60 — all divisible by 60.

Approach

This is Two Sum with mod 60. For each song, compute remainder = time % 60. The complement needed is (60 – remainder) % 60. Check how many previous songs have that complement remainder.

Solution

int numPairsDivisibleBy60(int[] time) {
    int[] count = new int[60];
    int pairs = 0;
    for (int t : time) {
        int rem = t % 60;
        pairs += count[(60 - rem) % 60];
        count[rem]++;
    }
    return pairs;
}

Time: O(n) | Space: O(1)


Q8. Partition Labels


🟠 Medium | Greedy / Strings

Partition string s into as many parts as possible so each letter appears in at most one part. Return a list of the sizes of each partition.

Example

Input: “ababcbacadefegdehijhklij” → Output: [9, 7, 8] Partitions: “ababcbaca”, “defegde”, “hijhklij”

Approach

Record the last occurrence index of every character. Walk through the string expanding the current partition end whenever a character’s last occurrence is beyond the current end. When i equals end, the partition is complete.

Solution

List<Integer> partitionLabels(String s) {
    int[] last = new int[26];
    for (int i = 0; i < s.length(); i++)
        last[s.charAt(i)-'a'] = i;
    List<Integer> result = new ArrayList<>();
    int start = 0, end = 0;
    for (int i = 0; i < s.length(); i++) {
        end = Math.max(end, last[s.charAt(i)-'a']);
        if (i == end) { result.add(end-start+1); start = end+1; }
    }
    return result;
}

Time: O(n) | Space: O(1)


Q9. Minimum Steps to Make Two Strings Anagram II


🔴 Hard | Hashing / Strings

You can append any character to either string s or t in one step. Return the minimum number of steps to make s and t anagrams of each other.

Example

Input: s = “leetcode”, t = “coats” → Output: 7 Append “as” to s (2 steps) + append “leede” to t (5 steps) = 7.

Approach

Use one frequency array of size 26. Increment for every character in s, decrement for every character in t. Each entry now shows the imbalance for that character. Sum of all absolute values is the answer.

Solution

int minSteps(String s, String t) {
    int[] freq = new int[26];
    for (char c : s.toCharArray()) freq[c-'a']++;
    for (char c : t.toCharArray()) freq[c-'a']--;
    int steps = 0;
    for (int f : freq) steps += Math.abs(f);
    return steps;
}

Time: O(|s|+|t|) | Space: O(1)


Q10. Sort Characters by Frequency


🟠 Medium | Hashing / Bucket Sort

Given a string s, sort it in decreasing order based on character frequency.

Example

Input: “tree” → Output: “eert” Input: “Aabb” → Output: “bbAa”

Approach

Count character frequencies using a HashMap. Use bucket sort — create an array of lists indexed by frequency. Build the result string from the highest frequency bucket downward.

Solution

String frequencySort(String s) {
    Map<Character,Integer> freq = new HashMap<>();
    for (char c : s.toCharArray()) freq.put(c, freq.getOrDefault(c,0)+1);
    List<Character>[] buckets = new List[s.length()+1];
    for (char c : freq.keySet()) {
        int f = freq.get(c);
        if (buckets[f]==null) buckets[f]=new ArrayList<>();
        buckets[f].add(c);
    }
    StringBuilder sb = new StringBuilder();
    for (int i=s.length(); i>=1; i--)
        if (buckets[i]!=null)
            for (char c : buckets[i])
                for (int j=0; j<i; j++) sb.append(c);
    return sb.toString();
}

Time: O(n) | Space: O(n)


Q11. Insert Delete GetRandom O(1)


🔴 Hard | HashMap + ArrayList Design

Design RandomizedSet with insert(val), remove(val), and getRandom() — all running in average O(1) time.

Example

insert(1)→true, remove(2)→false, insert(2)→true getRandom()→1 or 2, remove(1)→true, getRandom()→2

Approach

HashMap stores value to index mapping. ArrayList stores all values. For O(1) delete, swap the target element with the last element, update the map for the swapped element, then remove the last. No shifting required.

Solution

class RandomizedSet {
    Map<Integer,Integer> map = new HashMap<>();
    List<Integer> list = new ArrayList<>();
    Random rand = new Random();

    boolean insert(int val) {
        if (map.containsKey(val)) return false;
        list.add(val); map.put(val, list.size()-1);
        return true;
    }
    boolean remove(int val) {
        if (!map.containsKey(val)) return false;
        int idx=map.get(val), last=list.get(list.size()-1);
        list.set(idx,last); map.put(last,idx);
        list.remove(list.size()-1); map.remove(val);
        return true;
    }
    int getRandom() { return list.get(rand.nextInt(list.size())); }
}

Time: O(1) avg all operations | Space: O(n)


Q12. Design Stack with Increment Operation


🔴 Hard | Stack / Lazy Propagation

Design CustomStack(maxSize) supporting push(x), pop() returning top or -1 if empty, and increment(k, val) adding val to bottom k elements. All operations must be O(1).

Example

push(1), push(2), push(3) → [1, 2, 3] increment(2, 100) → [101, 102, 3] pop()→3, pop()→202, pop()→201, pop()→-1

Approach

Use a lazy increment array inc[]. When increment(k, val) is called, store val at inc[min(k-1, top)] only — one operation, not k. When pop() is called, the element picks up its pending increment from inc[top] and passes it down to inc[top-1] before resetting.

Solution

class CustomStack {
    int[] stack, inc; int top=-1, maxSize;
    CustomStack(int maxSize) {
        this.maxSize=maxSize; stack=new int[maxSize]; inc=new int[maxSize];
    }
    void push(int x) { if(top<maxSize-1) stack[++top]=x; }
    int pop() {
        if(top<0) return -1;
        int val=stack[top]+inc[top];
        if(top>0) inc[top-1]+=inc[top];
        inc[top--]=0;
        return val;
    }
    void increment(int k, int val) {
        int idx=Math.min(k-1,top);
        if(idx>=0) inc[idx]+=val;
    }
}

Time: O(1) per operation | Space: O(maxSize)


Q13. Number of Recent Calls


🟠 Medium | Queue / Sliding Window

Implement RecentCounter where ping(t) records a request at time t and returns the count of requests in range [t-3000, t]. All calls have strictly increasing t.

Example

ping(1)→1, ping(100)→2, ping(3001)→3, ping(3002)→3

Approach

Use a Queue. On each ping, add t to the queue. Remove all elements from the front that fall below t-3000. The queue size is the answer.

Solution

class RecentCounter {
    Queue<Integer> q = new LinkedList<>();
    int ping(int t) {
        q.offer(t);
        while (q.peek() < t-3000) q.poll();
        return q.size();
    }
}

Time: O(1) amortized | Space: O(1)


Q14. Maximum Sum of an Hourglass


🟠 Medium | 2D Arrays / Matrix Traversal

Given an m × n integer matrix grid, return the maximum sum of any hourglass shape. An hourglass is: top row of 3 + center element + bottom row of 3. It must be fully contained in the matrix.

Example

Input: [[6,2,1,3],[4,2,1,5],[9,2,8,7],[4,1,2,9]] Output: 30 Hourglass at (0,0): 6+2+1 + 2 + 9+2+8 = 30

Approach

Slide across every valid top-left position where i ≤ m-3 and j ≤ n-3. Compute the 7-element hourglass sum at each position and track the maximum.

Solution

int maxSum(int[][] grid) {
    int m=grid.length, n=grid[0].length, max=Integer.MIN_VALUE;
    for (int i=0; i<=m-3; i++)
        for (int j=0; j<=n-3; j++) {
            int sum = grid[i][j]+grid[i][j+1]+grid[i][j+2]
                    + grid[i+1][j+1]
                    + grid[i+2][j]+grid[i+2][j+1]+grid[i+2][j+2];
            max = Math.max(max, sum);
        }
    return max;
}

Time: O(m×n) | Space: O(1)


Q15. Lucky Numbers in a Matrix


🟠 Medium | Matrix / Row-Column Analysis

Return all elements that are the minimum in their row and the maximum in their column.

Example

Input: [[3,7,8],[9,11,13],[15,16,17]] → Output: [15] 15 is the minimum of row 2 and the maximum of column 0.

Approach

Step 1 — collect all row minimums into a HashSet. Step 2 — for each column find the column maximum. If that maximum exists in the row-min set, it is a lucky number.

Solution

List<Integer> luckyNumbers(int[][] matrix) {
    Set<Integer> rowMins = new HashSet<>();
    for (int[] row : matrix) {
        int mn=row[0]; for(int v:row) mn=Math.min(mn,v); rowMins.add(mn);
    }
    List<Integer> res = new ArrayList<>();
    for (int j=0; j<matrix[0].length; j++) {
        int mx=matrix[0][j];
        for (int[] row:matrix) mx=Math.max(mx,row[j]);
        if (rowMins.contains(mx)) res.add(mx);
    }
    return res;
}

Time: O(m×n) | Space: O(m)


Q16. Sort Students by Kth Score


🟠 Medium | Sorting / 2D Arrays

Given an m × n score matrix and integer k, sort the students (rows) in descending order by their score in the k-th exam column.

Example

Input: score=[[10,6,9,1],[7,5,11,2],[4,8,3,15]], k=2 Output: [[7,5,11,2],[10,6,9,1],[4,8,3,15]] Column 2 values: 11 > 9 > 3

Approach

Use Arrays.sort with a custom comparator that compares row[k] in descending order. One line solution.

Solution

int[][] sortTheStudents(int[][] score, int k) {
    Arrays.sort(score, (a, b) -> b[k] - a[k]);
    return score;
}

Time: O(m log m) | Space: O(1)


Q17. Maximum XOR After Operations


🔴 Hard | Bit Manipulation

Given nums[], operation: nums[i] = nums[i] AND (nums[i] XOR x). This can only clear bits, never set new ones. Return the maximum possible XOR of all elements after any number of operations.

Example

Input: [3, 2, 4, 6] → Output: 7 Key insight: the operation can only remove bits. The maximum achievable XOR equals the bitwise OR of all elements.

Approach

Since no operation can ever introduce a new bit into any element, the maximum XOR of all elements is achieved when each bit that exists in any element is contributed independently. That is simply the OR of all elements.

Solution

int maximumXOR(int[] nums) {
    int result = 0;
    for (int num : nums) result |= num;
    return result;
}

Time: O(n) | Space: O(1)


Q18. Minimum Operations to Reinitialize a Permutation


🔴 Hard | Math / Cycle Detection

Start with perm = [0, 1, 2, …, n-1] where n is even. Each operation: arr[i] = perm[i/2] if i is even, arr[i] = perm[n/2 + (i-1)/2] if i is odd. Return the minimum operations to return perm to its original state.

Example

n=4 → Output: 2 n=6 → Output: 4

Approach

Instead of simulating the full array at each step, just track where index 1 travels after each operation. All positions share the same cycle length. Count how many steps until index 1 returns to itself.

Solution

int reinitializePermutation(int n) {
    int pos=1, steps=0;
    do {
        pos = (pos%2==0) ? pos/2 : n/2+(pos-1)/2;
        steps++;
    } while(pos!=1);
    return steps;
}

Time: O(log n) | Space: O(1)


Q19. Check if Number is Sum of Powers of Three


🟠 Medium | Math / Number Theory

Return true if integer n can be represented as the sum of distinct powers of 3. Otherwise return false.

Example

Input: n=12 → true (3¹ + 3² = 3 + 9) Input: n=91 → true (3⁰ + 3² + 3⁴ = 1 + 9 + 81) Input: n=21 → false

Approach

This is a base-3 representation check. Repeatedly divide n by 3. If any remainder is 2, that power of 3 would need to be used twice which violates the distinct condition. If all remainders are 0 or 1, return true.

Solution

boolean checkPowersOfThree(int n) {
    while (n > 0) {
        if (n % 3 == 2) return false;
        n /= 3;
    }
    return true;
}

Time: O(log₃n) | Space: O(1)


Q20. Arithmetic Subarrays


🟠 Medium | Sorting / Query Processing

Given array nums[] and range queries defined by arrays l[] and r[], for each query check if subarray nums[l[i]..r[i]] can be rearranged into an arithmetic sequence. Return a list of boolean answers.

Example

nums=[4,6,5,9,3,7], l=[0,0,2], r=[2,3,5] Query 0: [4,6,5] → sorted [4,5,6] → diff=1 → true Query 1: [4,6,5,9] → sorted [4,5,6,9] → not uniform → false Query 2: [5,9,3,7] → sorted [3,5,7,9] → diff=2 → true Output: [true, false, true]

Approach

For each query extract the subarray, sort it, then check if all consecutive differences are equal. A valid arithmetic sequence has one uniform common difference throughout.

Solution

List<Boolean> checkArithmeticSubarrays(int[] nums, int[] l, int[] r) {
    List<Boolean> res = new ArrayList<>();
    for (int q=0; q<l.length; q++) {
        int[] sub = Arrays.copyOfRange(nums, l[q], r[q]+1);
        Arrays.sort(sub);
        int diff=sub[1]-sub[0]; boolean ok=true;
        for (int i=2;i<sub.length;i++)
            if(sub[i]-sub[i-1]!=diff){ ok=false; break; }
        res.add(ok);
    }
    return res;
}

Time: O(m × k log k) | Space: O(k)

4-Week Battle Plan

Week Focus Questions
Week 1 Arrays Deep Dive Q1 → Q6
Week 2 Strings + Hashing Q7 → Q10
Week 3 DS Design + Matrix Q11 → Q16
Week 4 Math + Full Mock Q17 → Q20

Pre-Exam Checklist

  • Can you solve Q3 (First Missing Positive) without notes?
  • Do you understand WHY Floyd’s Cycle works in Q4?
  • Can you explain Lazy Propagation in Q12 to someone?
  • Have you done 3 full timed mock sessions?
  • Have you written solutions by hand, not just typed them?

All five checked? You are ready.


Save this. Share it with your batch. One share could change someone’s career.