Updated June 2026
Cognizant plans to hire 24,000 to 25,000 freshers in the 2026 campus cycle through its GenC family of programs. The three main tracks, GenC, GenC Elevate, and GenC Next, have meaningfully different assessments and packages. Most candidates treat them as the same process and underprepare the track-specific sections. This page maps the actual 2026 process for each, with real questions from each round and the specific detail on what Cognizant's panels are actually looking for.
The structure here follows the four rounds in order: Communication Assessment, Aptitude and Gamified round, Technical Assessment, and the combined Technical plus HR interview. Each section has real questions, real code, and a note on how each answer tends to land inside Cognizant's interview process.
The Cognizant selection process in 2026
Cognizant runs its campus hiring entirely through a structured multi-stage process administered on AMCAT and HackerRank. The track you are assessed for, GenC, GenC Elevate, or GenC Next, determines which sections you face and how much depth the Technical interview goes to.
The three tracks differ more than most candidates expect going in:
- GenC: Communication, Aptitude, and a combined Technical plus HR interview. Package approximately Rs. 4.0 LPA. Foundational development and support roles. No dedicated coding section in the online test.
- GenC Elevate: Same as GenC plus a coding component. Package approximately Rs. 4.75 to 5.4 LPA (base plus skill bonus). Stronger emphasis on application development.
- GenC Next: Full assessment including 2 coding problems, 2 SQL questions, 10 technical MCQs, and a web development task. Package Rs. 6.75 LPA and above, with high performers reaching Rs. 12 LPA. Full-stack and AI-adjacent roles, generative AI tooling from day one per Cognizant's 2026 hiring mandate.
Eligibility for all tracks: minimum 60% aggregate in 10th, 12th, and degree; no active backlogs at the time of joining; academic gaps not exceeding two years; 2024 to 2026 batch. Eligible degrees include B.E, B.Tech, MCA, M.Sc CS or IT, and BCA. Cognizant explicitly states no service bond for GenC hires ("no bonds" on their careers page), which is different from TCS and Infosys.
AI-graded evaluation of English fluency, grammar, pronunciation, and listening. Covers reading comprehension, sentence correction, and an audio playback section where the recording plays only once. Candidates who perform well here get routed into GenC Next consideration. The listening section is the one that surprises people: you don't get a replay.
Quantitative aptitude (16 questions, 16 min) and logical reasoning (14 questions, 14 min) via AMCAT, followed by a game-based cognitive test with 4 games. The gamified section measures attention, processing speed, and pattern recognition rather than math knowledge. Reaching higher levels in each game improves your score even if you don't complete every game.
2 coding problems in Java, Python, or C# (C++ is not available), 2 SQL queries, 10 technical MCQs covering cloud fundamentals and web concepts, and 1 web scenario task (HTML, CSS, JavaScript). Scored by test cases. No negative marking. The coding platform is HackerRank.
Panel of one interviewer, sometimes two. Opens with your project, moves to OOP and DBMS fundamentals, sometimes includes a live coding problem on screen. HR questions (relocation, career goals, why Cognizant) happen in the same session for most batches. Technical depth varies by cluster and the interviewer's read of your resume.
Aptitude and communication test
The AMCAT-administered aptitude section has 50 questions across three areas and no negative marking. Time per section is fixed: you cannot borrow minutes from verbal and apply them to quant. The gamified round that follows does not have traditional questions, but Cognizant uses the scores and candidates should take it seriously.
Quantitative Aptitude (16 questions, 16 min)
One question per minute on average, which is tight. Topics seen consistently in the 2025 to 2026 cycle: percentages, profit and loss, time-speed-distance, ratios, averages, number systems, and basic probability. The problems are at a level below the NQT but faster-paced because the time budget is tighter per question.
Easy questions
31Profit = 25% of 800 = Rs. 200. Selling price = 800 + 200 = Rs. 1000.
This type of profit/loss calculation appears in nearly every Cognizant AMCAT aptitude round. At 16 minutes for 16 questions, the key is not computing fast, it is identifying the formula immediately and not second-guessing your setup. Practice the template: SP = CP x (1 + profit%/100).
Formula: a_n = a_1 + (n - 1) x d. So a_10 = 5 + (10 - 1) x 3 = 5 + 27 = 32.
Series problems show up both in the quant section and the logical reasoning section. The quant version gives you a formula-solvable setup like this one. The reasoning version gives you a sequence and asks you to find the pattern before applying any formula.
C=3, O=15, G=7, N=14, I=9, Z=26, A=1, N=14, T=20. Code: 3 15 7 14 9 26 1 14 20.
Coding-decoding questions on the AMCAT use several variants: positional codes like this, shift codes (A=D means +3 shift), and reversal codes. Identify the variant from the example given in the question before applying it. Don't assume the same type across questions.
The brute-force is O(n x m): for each element in array A, scan all of array B. The faster approach uses a hash set: load one array into a set, then check each element of the second array against it in O(1) lookups. Total time O(n + m).
def common_elements(arr1, arr2):
set1 = set(arr1)
result = []
for num in arr2:
if num in set1:
result.append(num)
set1.discard(num) # Avoid duplicates in output
return result
# Example
print(common_elements([1, 2, 3, 4, 5], [3, 4, 5, 6, 7]))
# Output: [3, 4, 5]This specific problem was reported in a Cognizant GenC Next technical interview (GeeksforGeeks, April 2025 campus experience). The interviewer also asked the candidate to explain the time complexity of their solution afterward.
Walk through the string and keep a set of characters seen so far. The first character that already exists in the set is the answer. This runs in O(n) time and O(k) space where k is the alphabet size.
public class FirstDuplicate {
public static char findFirstDuplicate(String s) {
java.util.Set<Character> seen = new java.util.HashSet<>();
for (char c : s.toCharArray()) {
if (seen.contains(c)) {
return c;
}
seen.add(c);
}
return ''; // No duplicate found
}
public static void main(String[] args) {
System.out.println(findFirstDuplicate("abcdeabcd")); // 'a'
System.out.println(findFirstDuplicate("programming")); // 'r'
}
}Java is the preferred language for many candidates in the Cognizant coding round because the HackerRank setup for Java works more predictably than the C# template. If you are comfortable in Python, that works equally well here.
Two strings are anagrams if they contain the same characters with the same frequency, in any order. The fastest check: sort both strings and compare, or count character frequency with a hash map and compare the two maps.
def is_anagram(s1, s2):
s1 = s1.replace(" ", "").lower()
s2 = s2.replace(" ", "").lower()
if len(s1) != len(s2):
return False
return sorted(s1) == sorted(s2)
print(is_anagram("listen", "silent")) # True
print(is_anagram("cognizant", "genc")) # FalseThe sort-and-compare approach runs in O(n log n) and is the version most candidates write first on the Cognizant coding platform. The frequency-count version runs in O(n) and is the better answer if the interviewer asks you to optimize it. Have both ready: the sorted() one-liner to ship fast, the hash map version to explain when asked about time complexity.
Exception handling separates normal execution from error recovery. The try block contains code that might throw an exception. The catch block specifies what to do if that exception occurs. The finally block (optional) runs regardless of whether an exception was thrown.
public class ExceptionExample {
public static int divide(int a, int b) {
try {
return a / b;
} catch (ArithmeticException e) {
System.out.println("Error: " + e.getMessage()); // "/ by zero"
return -1;
} finally {
System.out.println("Division attempted.");
}
}
public static void main(String[] args) {
System.out.println(divide(10, 2)); // 5
System.out.println(divide(10, 0)); // -1
}
}The follow-up question is almost always: what is the difference between checked and unchecked exceptions? Checked exceptions (like IOException) must be declared or caught. Unchecked exceptions (like NullPointerException, ArithmeticException) do not need to be declared and extend RuntimeException.
Bubble sort repeatedly steps through the list, compares adjacent elements, and swaps them if they are in the wrong order. After each pass, the largest unsorted element bubbles to its correct position.
#include <stdio.h>
void bubbleSort(int arr[], int n) {
int i, j, temp;
for (i = 0; i < n - 1; i++) {
for (j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main() {
int arr[] = {64, 34, 25, 12, 22, 11, 90};
int n = sizeof(arr) / sizeof(arr[0]);
bubbleSort(arr, n);
for (int i = 0; i < n; i++) printf("%d ", arr[i]);
// Output: 11 12 22 25 34 64 90
return 0;
}Time complexity: O(n^2) in the worst and average case, O(n) in the best case (if the array is already sorted and you add an early-exit flag). Space complexity: O(1). The Cognizant panel usually asks for the time complexity immediately after you write the code. Know it before you finish typing.
An array stores elements in contiguous memory, which gives O(1) access to any index but a fixed size decided at creation. A linked list stores elements as separate nodes connected by pointers, so it grows one node at a time, but reaching the k-th element means walking through k nodes one by one, an O(n) operation.
- Insertion or deletion at the front: O(n) for an array because every later element shifts. O(1) for a linked list because you just relink two pointers.
- Memory: an array's memory is one contiguous block. A linked list's memory is scattered across the heap, and each node carries the overhead of a pointer.
Cognizant interviewers ask for a real use case, not just the theory. A browser's undo history fits a linked list well because entries get added and removed constantly. A lookup table for pin codes fits an array well because the size is fixed and access speed matters more than insertion speed.
Encapsulation: bundling data and methods into one unit and restricting direct access to internal state. A bank account class hides the balance variable and exposes deposit() and withdraw() methods.
Inheritance: a child class inherits properties and methods from a parent. A Car class inherits from a Vehicle class, gaining the move() method without re-implementing it.
Polymorphism: the same method name behaves differently depending on the object. A draw() method on a Shape class draws a circle when called on a Circle object, and draws a rectangle when called on a Rectangle object.
Abstraction: hiding implementation details, showing only what's necessary. A smartphone user taps an app icon without knowing anything about the underlying OS memory management.
Cognizant interviewers specifically ask for real-world examples, not just definitions. Having one concrete example per pillar ready before you go in makes a visible difference to how the answer lands.
Overloading: same method name in the same class, different parameter types or counts. Resolved at compile time (static/early binding). No inheritance required.
Overriding: a child class provides a different implementation of a method that already exists in the parent class. Resolved at runtime (dynamic/late binding). Requires inheritance. The signature must match exactly.
In Java: overloading is how you create a print() method that handles both int and String. Overriding is how a Dog class redefines the speak() method it inherits from Animal to return "Woof" instead of a generic sound.
Public: accessible from any class, any package. Private: accessible only within the same class. This is the strictest level. Protected: accessible within the same package and by subclasses in other packages.
The default modifier (no keyword) is package-private: accessible within the same package only. Cognizant interviewers often ask candidates to rank these from most to least restrictive. The order is: private, default, protected, public.
A constructor is a special method that runs automatically when an object is created. It shares the class name and has no return type, not even void. Its job is to set the object's initial state.
A default constructor takes no arguments and either sets fields to default values or does nothing at all. If you don't write any constructor yourself, Java supplies one for free. A parameterized constructor takes arguments and uses them to set specific field values at creation time. The moment you write a parameterized constructor, the compiler stops generating the free default one, so you have to write your own default constructor explicitly if you still need it.
public class Employee {
String name;
int id;
// Default constructor
public Employee() {
this.name = "Unassigned";
this.id = 0;
}
// Parameterized constructor
public Employee(String name, int id) {
this.name = name;
this.id = id;
}
}This question is a standard opener in the Cognizant Technical round right after the four pillars question, usually as a quick warm-up before the interviewer moves into a live coding problem.
'this' refers to the current object, the instance the method is running on. It's used to distinguish an instance variable from a parameter with the same name, or to call another constructor in the same class.
'super' refers to the immediate parent class. It's used to call the parent's constructor, or to call a parent method that the current class has overridden, when you still need the original version inside the child class.
class Vehicle {
void honk() {
System.out.println("Generic honk");
}
}
class Car extends Vehicle {
void honk() {
super.honk(); // calls Vehicle's honk()
System.out.println("Car honk");
}
}Freshers often mix these up under pressure. The line that keeps them straight: 'this' points inward, at your own object. 'super' points upward, at the class you inherited from.
DDL (Data Definition Language) defines and modifies database structure: CREATE, ALTER, DROP, TRUNCATE. DDL changes are auto-committed in most databases and cannot be rolled back in the same transaction.
DML (Data Manipulation Language) operates on the data inside that structure: SELECT, INSERT, UPDATE, DELETE. DML operations can be wrapped in a transaction and rolled back if something goes wrong.
Cognizant panels ask this directly and also via follow-ups: "can you roll back a DROP statement?" In MySQL, no. In PostgreSQL, yes, if it's inside an explicit transaction.
A primary key uniquely identifies each row in its own table. It cannot be NULL and cannot repeat across rows. A foreign key is a column in one table that points to the primary key of another table, which is what enforces the relationship between the two.
Example: an Orders table has a customer_id foreign key pointing to the id primary key in a Customers table. The database rejects an insert into Orders if that customer_id doesn't already exist in Customers. That rejection is referential integrity working as intended, not a bug.
Cognizant interviewers commonly follow this with a question about composite keys, a primary key made of two or more columns together, which shows up in join tables representing many-to-many relationships.
A process is an independent executing instance of a program with its own memory space (heap, stack, data segment). Processes are isolated: one process cannot directly access another's memory without IPC (inter-process communication).
A thread is a unit of execution inside a process. Threads in the same process share the heap and data segment but have their own stack. Threads are lighter to create and context-switch than processes but need synchronization primitives (locks, semaphores) to avoid race conditions on shared data.
Multithreading comes up in the Cognizant Technical round in both the interview and sometimes the MCQ section. Know the real-world use case: a web server spawns a new thread per request rather than a new process because thread creation overhead is much lower.
Cognizant's 2026 hiring is explicitly oriented toward AI-enabled delivery. The campus mandate includes generative AI familiarity from day one. If your project involved any cloud service (even a free-tier AWS S3 bucket or Google Cloud Vision API), mention it and know what it does. If it didn't, that's fine, but be prepared to say "I haven't used cloud in a project yet, but I understand the concept of X service and how it would apply."
Candidates who have even surface-level exposure to a cloud service or a generative AI API (OpenAI, Gemini, Hugging Face) get visibly better responses from Cognizant Next interviewers in the 2025 to 2026 cycle.
Keep it to 90 seconds. Academic background (brief), one project or skill that's relevant to the role you're applying for, one thing you want to do at Cognizant specifically. Don't read the resume aloud. The interviewer has it in front of them.
A structure that works: "I'm a [degree] graduate from [college]. My final year project was [one sentence on what it did]. I'm strongest in [language/domain]. I'm interested in the GenC Next role specifically because [one specific reason linked to Cognizant's work]."
Avoid: "Cognizant is a great company" or "because of the good package." Both are transparent non-answers and interviewers hear them 30 times a day.
Tie your answer to one specific and true thing: Cognizant's explicit 2026 push into generative AI roles (which you can verify directly on their hiring page), their work in a specific industry vertical that matches your degree, or the GenC Next program's structure that includes formal upskilling. "I saw that Cognizant's 2026 campus hiring is specifically targeting AI-enabled delivery roles, and that aligns with my interest in the work I did on [project]" is a better answer than anything generic.
Cognizant serves US and European clients heavily, which means offshore teams in India frequently work evening to late-night IST shifts. Be honest. If you can genuinely commit to relocation and shifts, say so clearly.
If you have a real constraint (say, a family situation that makes relocation difficult for six months), say so calmly. "I'm open to relocation after settling the joining process, and I can manage night shifts for project needs" is trusted more than a blanket "anything you need." The HR interviewer is logging this for onboarding, not testing resolve.
Pick a direction: technical depth or a people-management path. The Cognizant HR interviewer for a fresher role is not looking for a five-year org chart. They're looking for evidence that you think about growth deliberately.
Something like: "In five years I want to have strong hands-on experience in full-stack development, ideally having led a small workstream on a client project. I'd like to have done at least one of Cognizant's upskilling certifications in cloud or AI by year two." Concrete, aligned with what Cognizant actually offers, and not claiming to be a VP in five years.
For strengths: pick something you can show evidence of, not a personality adjective. "I'm a fast learner" with no example is the same as saying nothing. "I pick up new tools quickly. I taught myself SQL queries in two weeks to complete a project requirement that wasn't in my curriculum" is an evidence-backed claim.
For weaknesses: don't use "I'm a perfectionist" (overused) or a central job skill (don't say "I'm weak at coding" when applying for a developer role). A real developmental area that you're actively working on is the right format. "I tend to over-explain technical concepts when presenting to non-technical stakeholders. I've been working on shortening my explanations and checking in earlier to see if the other person is following."
This isn't a competition against people you've never met, so don't try to guess what other candidates might say. Answer with what you actually bring: one technical skill backed by a real project, plus one trait that fits how Cognizant actually staffs its delivery teams, working within a structured process across a distributed team.
"I'm hardworking and a fast learner" without a supporting example gets forgotten within minutes. "I built the backend for my final year project in Spring Boot in three weeks with no prior framework experience, and I can show you the repo" is the kind of answer an interviewer remembers after the next five candidates.
Never say no. Cognizant HR interviewers read a blank response here as low genuine interest, even after a strong technical round.
Ask something specific that you can't already find on the careers page: which project or client account new GenC hires typically join first, or what the shift schedule looks like in the first three months before you're settled into a team. A sharp, specific question in the last two minutes leaves a stronger impression than repeating "I'm excited to join" one more time.
GenC is the standard entry-level track with a package of approximately Rs. 4.0 LPA. The online test covers communication, aptitude, and reasoning only. No dedicated coding section. GenC Next is the premium track for candidates with stronger programming skills. It adds a 120-minute Technical Assessment with 2 coding problems, 2 SQL queries, 10 tech MCQs, and a web task. Package ranges from Rs. 6.75 LPA up to Rs. 12 LPA for high performers, based on reported offer letters from the 2025 to 2026 cycle. The Technical interview for GenC Next also goes deeper into CS fundamentals.
No. Cognizant explicitly states "no bonds" on its GenC careers page, unlike TCS (1-2 year bond) and Infosys (which has had bond requirements in prior cycles). This is one of the practical differences candidates weigh when comparing Cognizant offers against other IT majors. Verify this on the official Cognizant careers page at the time you receive your offer, as policies can change between hiring cycles.
Based on candidate timelines reported in the 2025 to 2026 cycle, the full process from initial application to Letter of Intent (LOI) takes approximately 3 to 5 weeks. The online assessment rounds happen first, and interview scheduling typically follows within 1 to 2 weeks of assessment results. Some batches have reported faster timelines of 2 to 3 weeks for campus-specific drives.
Python 3 is the safest choice for most candidates because the syntax is cleaner to write under time pressure and the HackerRank input format works predictably. Java is a strong second option and is what many campus candidates use. Critically, C++ is not available in the Cognizant coding environment (confirmed by candidate experiences from April 2025 on GeeksforGeeks). If you've been practicing competitive programming in C++, spend time before the assessment practicing the same problem types in Python or Java.
Based on consistent reports from the 2024 to 2026 cycle: DSA (arrays, strings, linked lists, basic recursion), OOP (all four pillars plus overloading vs overriding), DBMS (ACID, normalization 1NF through 3NF, common SQL queries including GROUP BY and HAVING, joins), OS basics (process vs thread, deadlock conditions), and SQL-specific questions (DDL vs DML, indexing). The web scenario in the Technical Assessment tests basic HTML, CSS, and JavaScript concepts, not framework knowledge.
Cognizant announced a target of approximately 24,000 to 25,000 freshers from the 2026 batch, according to Unstop's campus hiring 2026 guide. The focus for this cycle is explicitly on AI-enabled delivery roles. This is a significant number and the selection rate is higher than at companies like TCS Digital or Wipro Turbo, but the GenC Next track remains competitive because it attracts candidates with stronger technical profiles.
Medium questions
15Filling rate = 1/6 per hour. Draining rate = 1/12 per hour. Net rate = 1/6 - 1/12 = 2/12 - 1/12 = 1/12 per hour. Time to fill = 12 hours.
Pipe and cistern problems appear in most AMCAT quant sections. The mistake candidates make is forgetting to subtract the drain rate. Set up rates first, then compute.
Neither conclusion follows. Draw the Venn diagram: roses sit entirely inside the flowers circle, and "some flowers fade quickly" only guarantees an overlap somewhere inside the flowers circle, not specifically inside the smaller roses circle. Conclusion I assumes that overlap happens to land on roses, which the statement never says. Conclusion II reverses the original statement, since all roses being flowers does not mean all flowers are roses, a classic converse error.
Syllogism questions on the Cognizant AMCAT reasoning section almost always hide one of two traps: assuming a "some" statement applies to a named subset, or reversing an "all" statement. Draw the circles instead of reasoning it out in your head. It takes 15 seconds and removes the guesswork.
She is his sister. The grandfather's only son sits one generation below the grandfather, in the same generation as the man's own father. Since the grandfather has only one son, that son has to be the man's father. The daughter of the man's father is the man's sister.
The trap in this question is trying to guess who the "only son" is before fixing the generations on paper. Write grandfather at the top, his only son one level below, then that son's children one level below that. Once the tree is drawn, the answer reads off directly instead of needing to be worked out twice in your head.
There are three common approaches. The subquery approach works across most SQL dialects:
-- Approach 1: Subquery (works in MySQL, PostgreSQL, SQL Server)
SELECT MAX(salary) AS second_highest
FROM employees
WHERE salary < (SELECT MAX(salary) FROM employees);
-- Approach 2: LIMIT with OFFSET (MySQL / PostgreSQL)
SELECT DISTINCT salary
FROM employees
ORDER BY salary DESC
LIMIT 1 OFFSET 1;
-- Approach 3: DENSE_RANK window function (SQL Server, PostgreSQL)
SELECT salary
FROM (
SELECT salary, DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
FROM employees
) ranked
WHERE rnk = 2;Cognizant's SQL section tests this exact pattern frequently. The interviewer may ask you to handle the case where there is no second-highest salary (i.e., all employees have the same salary). The subquery approach returns NULL in that case, which is the correct behavior.
This tests GROUP BY combined with HAVING, the most frequently tested SQL pattern in Cognizant's technical section.
SELECT department_id, COUNT(*) AS employee_count
FROM employees
GROUP BY department_id
HAVING COUNT(*) > 5
ORDER BY employee_count DESC;The two questions panels follow up with: what is the difference between WHERE and HAVING, and can you use an alias in HAVING? (No, in standard SQL you cannot use a column alias in HAVING because HAVING is evaluated before SELECT in the logical order of operations.)
Group by the column you're checking for duplicates, then filter groups with HAVING COUNT(*) greater than 1.
SELECT email, COUNT(*) AS occurrences
FROM employees
GROUP BY email
HAVING COUNT(*) > 1
ORDER BY occurrences DESC;This is the practical, production version of the same GROUP BY plus HAVING pattern Cognizant tests with the department count question above. The follow-up the panel usually asks: how would you delete the duplicates and keep only one copy? The standard answer ranks duplicate rows with a window function and deletes every rank except 1, or uses a self-join comparing row IDs.
Static binding (early binding) happens at compile time: the compiler knows exactly which function to call based on the declared type. Dynamic binding (late binding) happens at runtime: the actual function called depends on the object's runtime type, not its declared type.
In Java: method overloading is resolved statically; method overriding is resolved dynamically through the virtual method table. The practical implication is that overriding is what makes polymorphism actually work at runtime.
This distinction comes up in Cognizant Technical interviews more than most freshers expect. It's a natural follow-up to any OOP discussion.
An abstract class can have both concrete and abstract methods, instance variables, constructors, and any access modifier on its methods. A class can extend only one abstract class.
An interface (from Java 8 onward) can have abstract methods, default methods, static methods, and constants. A class can implement multiple interfaces. Variables in an interface are implicitly public static final.
When to use which: use an abstract class when sharing common state or behavior across closely related classes. Use an interface to define a contract that unrelated classes can sign up to, like Comparable or Serializable.
This is one of the highest-frequency Cognizant Technical interview questions for freshers. Know both the pre-Java-8 and post-Java-8 answer because the interviewer may ask which Java version you are using.
Atomicity: all operations in a transaction succeed or all fail together. Example: a bank transfer debits Account A and credits Account B. If the debit succeeds but the credit fails, the transaction rolls back the debit. No partial state persists.
Consistency: a transaction brings the database from one valid state to another. Isolation: concurrent transactions don't see each other's incomplete work. Durability: committed transactions survive system failures because they are written to persistent storage.
Cognizant panels usually ask for a concrete atomicity example after you define it. Bank transfer is the clearest one. Have it ready.
Normalization reduces data redundancy and dependency by organizing data into well-structured tables.
- 1NF: each column holds atomic (indivisible) values; no repeating groups; each row is unique. A column storing "Python, Java, C++" in one cell violates 1NF.
- 2NF: satisfies 1NF and every non-key column depends on the whole primary key, not just part of it. Only relevant when the primary key is composite.
- 3NF: satisfies 2NF and no non-key column depends on another non-key column. If City depends on ZipCode and ZipCode depends on StudentID, move City and ZipCode to a separate table.
The follow-up is sometimes BCNF or 4NF. For freshers, 1NF through 3NF is the expected depth. If the interviewer goes further, that's a signal they're evaluating for GenC Next depth.
A clustered index physically reorders the rows on disk to match the index order. There can be only one clustered index per table because the data can only be physically sorted one way. The primary key is the clustered index by default in most RDBMS.
A non-clustered index is a separate structure that stores the index key and a pointer (row locator) to the actual data. A table can have many non-clustered indexes.
Reads using the clustered index are faster because the data rows are co-located. Non-clustered index reads involve an extra lookup step to retrieve the actual row.
INNER JOIN returns only the rows that match in both tables. LEFT JOIN returns every row from the left table, filling in NULL for columns from the right table where there's no match. RIGHT JOIN is the mirror image of LEFT JOIN. FULL OUTER JOIN returns every row from both tables, with NULLs wherever a match is missing on either side.
-- Customers who have placed at least one order
SELECT c.name, o.order_id
FROM customers c
INNER JOIN orders o ON c.id = o.customer_id;
-- Every customer, including those with zero orders
SELECT c.name, o.order_id
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id;Cognizant panels usually pair this question with a scenario: "how would you find customers who have never placed an order?" That's a LEFT JOIN followed by WHERE o.order_id IS NULL, which filters down to only the rows where the join found nothing on the right side.
A deadlock is a state where two or more processes are each waiting for a resource held by another, so none can proceed.
Four necessary conditions (Coffman conditions), all must hold simultaneously: Mutual exclusion (a resource can only be held by one process at a time), Hold and wait (a process holds at least one resource and is waiting to acquire more), No preemption (resources cannot be forcibly taken away; they must be voluntarily released), Circular wait (a chain of processes each holds a resource the next one needs).
Breaking any one of these four conditions prevents deadlock. Deadlock prevention strategies in OS design work by targeting one condition: for example, requiring all resources be requested at once (eliminating hold-and-wait).
Cognizant interviewers pick one technology from your project description and drill it one level deep, consistently. If you mention REST APIs, expect a follow-up on HTTP methods or status codes. If you mention MySQL, expect a query. If you mention React, expect a question on state management or hooks.
The structure that works: problem you solved (one sentence), tech stack (list it fast), your specific contribution (not what the team built, what you built), one challenge you hit and how you resolved it. That last part is where candidates lose points. "We faced some debugging issues" tells the interviewer nothing. "The JOIN query was returning duplicate rows because we hadn't accounted for the many-to-many relation in the schema. We added a junction table and the query resolved cleanly." That tells them something real.
Use STAR: Situation, Task, Action, Result. The action element is what matters most. "We talked it out" is not enough. What specifically did you do? Who did you approach first? What did you say?
A version that reads as real: during a college project, two team members disagreed on whether to use MySQL or MongoDB. I asked each person to write out their reasoning in a shared doc, then called a 20-minute call to go through it. We went with MySQL because our data was relational and the team had more experience with it. The doc became our reference point when the same debate came up again later.
The specific detail (the shared doc, the 20-minute call) is what separates a real-sounding answer from a generic one.
Hard questions
6A HashMap stores entries in an array of buckets. The bucket index comes from hash(key) & (capacity - 1), which works as a fast modulo because capacity is always a power of two. When two keys land in the same bucket you get a collision. Before Java 8, each bucket held a plain linked list of entries, so a bucket with many collisions degraded lookups to O(n). This was a real production issue when hostile or poorly distributed input pushed everything into one bucket, effectively turning a hash map into a linked list.
Java 8 added treeification. Once a bucket's chain grows past 8 entries (TREEIFY_THRESHOLD) and the table has at least 64 buckets, that bucket converts to a red-black tree ordered by hash and then by compareTo when the key is Comparable. That caps worst case lookup at O(log n) instead of O(n). If the bucket shrinks back down during a resize, below UNTREEIFY_THRESHOLD of 6, it converts back to a list since a tree has more overhead per node than it's worth for a handful of entries.
On resize, when size crosses capacity times load factor (default 0.75), the table doubles and every entry has to be redistributed. Java 8 optimized this so it doesn't recompute hashCode() for each key, it just checks one extra bit of the already-computed hash to decide whether an entry stays at the same index or moves to index + oldCapacity. One classic gotcha to mention: if you mutate a field that's part of a key's hashCode after inserting it, you can effectively lose that entry because it now lives in the wrong bucket for its current hash. Keys should be immutable or at least stable for the object's lifetime in the map.
The design rests on the weak generational hypothesis, most objects die young. New allocations go into Eden inside the young generation. When Eden fills up, a minor GC runs, copies the surviving objects into one of two survivor spaces, and discards everything else. Because it only has to touch live objects in a small region, minor GC is fast and usually sub-millisecond to a few milliseconds. Objects that survive a number of minor GCs, tracked by an age counter, get promoted into the old generation, which is much larger and collected far less often.
A full or major GC in the old generation is expensive because the collector has to reason about reachability across a much bigger heap, and depending on the algorithm can trigger a stop-the-world pause long enough for users to notice, sometimes seconds on a multi-gigabyte heap under the older CMS collector. G1, the default collector on modern JVMs, changes the layout slightly, it splits the whole heap into equal-sized regions and tags each one as eden, survivor, or old rather than using two fixed contiguous generations, then prioritizes collecting the regions with the most garbage first, which is where the name comes from. This lets you target a pause time goal instead of a fixed heap ratio.
If a service is hitting frequent full GCs in production, the usual suspects are objects getting promoted too early because survivor space is undersized, a real leak where references outlive their intended scope (static collections, listeners that never get removed, ThreadLocal values not cleared in pooled threads), or an old generation that's simply too small for the live data set. Before touching any JVM flags, jstat -gcutil to watch generation occupancy over time and a heap dump opened in Eclipse MAT to find the dominant retained-size objects are the standard first steps.
Flat CPU with a hung service usually means threads are blocked waiting, not spinning, so the first move is a thread dump, jstack pid, or kill -3 to dump to stdout, or jcmd pid Thread.print if jstack isn't on the box. The JVM actually detects the classic lock-ordering deadlock for you and prints a "Found one Java-level deadlock" section at the bottom of the dump, naming exactly which threads are waiting on which monitor and who currently owns it. Absent that explicit callout, you scan for threads in BLOCKED state waiting on "monitor entry", note the object they're blocked on, then find the thread that owns that monitor. If that owning thread is itself blocked on a monitor held by the first thread, you've got a cycle.
In real code this almost always comes from two code paths locking the same two resources in opposite order, one method takes lock A then B, another takes B then A, and under load the interleaving eventually hits the bad case. It's also common when a synchronized method calls out to another object's synchronized method, effectively nesting locks without anyone intending to. Distributed locks make it worse, if the lock is coordinated through Redis or Zookeeper across services, jstack only shows you the local half of the picture, the thread will just look blocked waiting on a network call or a lock acquisition with no visible owner in the same JVM.
The durable fix is enforcing a consistent lock ordering everywhere, for example always acquiring by ascending resource ID, or collapsing nested locks into one coarser lock if the contention is low enough that it won't hurt throughput. For anything crossing process boundaries, never take a lock without a timeout or TTL, use tryLock with a deadline and log and retry instead of blocking indefinitely, because a distributed lock with no expiry is a guaranteed outage waiting to happen the first time a holder crashes without releasing it.
There are four standard levels, and each one trades consistency guarantees for concurrency. READ UNCOMMITTED lets a transaction see uncommitted changes from other transactions, a dirty read, meaning you might read a value that gets rolled back a moment later and never actually existed. READ COMMITTED, the default in Postgres and Oracle, only lets you see committed data, but if you read the same row twice within one transaction it can change in between because another transaction committed an update, that's a non-repeatable read.
REPEATABLE READ, the default in MySQL's InnoDB, guarantees that if you read a row once you'll see the same value for it every time within that transaction. It still doesn't stop phantom reads in the strict standard definition, where a range query like SELECT COUNT(*) WHERE status = 'pending' returns a different row count on a second execution because another transaction inserted a new matching row, though InnoDB's specific MVCC and gap-locking implementation actually closes most phantom cases too, which is a common interview trap since it's stricter than the SQL standard requires. SERIALIZABLE is the strongest level, transactions behave as if they ran one after another with no overlap at all, which eliminates every anomaly but at the cost of the most locking or the most serialization-failure retries, since some engines implement it via full locking and others via optimistic conflict detection that aborts and retries the transaction.
Most engines implement the middle levels using MVCC, giving each transaction a consistent snapshot instead of literally locking every row it reads, which is why READ COMMITTED and REPEATABLE READ scale far better under contention than SERIALIZABLE. In practice you pick REPEATABLE READ or READ COMMITTED for almost everything and reach for SERIALIZABLE only for a narrow set of operations, like a financial transfer or an inventory decrement, where a genuine race condition would corrupt data rather than just show a stale value.
Start with EXPLAIN, or EXPLAIN ANALYZE if you can afford to actually run it, and look at the plan the optimizer chose versus what you'd expect. The two most common findings are a full table scan where an index should have been used, or a nested loop join where the outer table has grown large enough that a hash join or merge join would now be cheaper. A full scan on a table that used to be small but has grown by an order of magnitude is the single most frequent cause of a query that "used to work fine."
If an index exists but isn't being used, check whether the WHERE clause wraps the indexed column in a function, WHERE YEAR(created_at) = 2026 or LOWER(email) = '...' will not use a plain index on that column because the optimizer can't seek on a transformed value, it has to evaluate the function per row. Rewriting to a sargable form, created_at >= '2026-01-01' AND created_at < '2027-01-01', or querying against a value that's already normalized at write time, restores index usage without touching the schema. A leading wildcard in a LIKE pattern, LIKE '%something', is another common one, since a B-tree index can't be range-scanned from an unknown prefix.
Also check whether table statistics are stale, ANALYZE TABLE or the Postgres equivalent, since the optimizer picks a plan based on estimated row counts and a badly out-of-date estimate will pick a nested loop where a hash join was actually cheaper. If none of that closes the gap and you genuinely can't add an index, the remaining levers are rewriting a correlated subquery into a join, adding pagination or a tighter predicate so the query touches fewer rows, or moving the query to a read replica so it stops competing with write traffic for buffer pool and lock resources.
A rate limiter that runs in-process on each server instance doesn't work once you have more than one instance behind a load balancer, because each instance only knows about the requests it personally saw, so a client can get several times the intended limit just by hitting different instances. The count needs to live somewhere shared, and Redis is the usual answer because it's fast enough to sit on the hot path of every request and supports the atomic operations you need.
The naive fixed-window approach, increment a counter keyed by client and current minute, reset every minute, is simple but has a burst problem at window boundaries, a client can send the full limit right at the end of one window and the full limit again right at the start of the next, getting roughly double the allowed rate in a short burst. A sliding window log, storing a timestamp per request in a sorted set and counting entries within the trailing window, is accurate but memory-heavy at high volume. The common middle ground is a sliding window counter that weights the current and previous fixed window counts by how far into the current window you are, which is cheap and close enough to accurate for almost every real use case.
The part people miss is atomicity. If you do a GET to read the count, check it in application code, then INCR if it's under the limit, two concurrent requests can both read the same count before either increments, and both pass when only one should have. The fix is a Lua script executed atomically in Redis, or Redis's own INCR plus EXPIRE combined in a single round trip, so the check-and-increment happens as one atomic operation from Redis's perspective regardless of how many app servers are calling it concurrently. On rejection, return 429 with a Retry-After header rather than a bare error, so well-behaved clients back off instead of retrying immediately and making the problem worse.
Across Cognizant interview prep sessions run through LastRoundAI, the gap that costs freshers the most is not a gap in OOP knowledge. It's the live coding round. The HackerRank environment in the Cognizant Technical Assessment does not support C++, which is what many engineering students have practiced on during their competitive programming practice. Candidates who arrive expecting C++ and haven't practiced the same problems in Java or Python lose 15 to 20 minutes switching mental gears. The algorithm they know perfectly fine takes twice as long to implement in a language they haven't typed recently.
The second pattern we see is candidates who can explain OOP concepts correctly in the abstract but freeze when asked to give a real-world example. The Cognizant panel specifically prompts for examples. "Encapsulation means bundling data and methods" is the textbook answer. "A bank account object that doesn't let you directly set the balance, only deposit and withdraw" is the answer that gets a nod.

