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.
