Wipro, one of the largest IT services companies in India, recruits thousands of candidates every year for technical roles. A crucial part of their hiring process is the coding assessment, where candidates are evaluated on their problem-solving abilities and coding skills. These assessments help determine if candidates can efficiently solve real-world problems using programming languages like C, C++, Java, and Python.
In today’s competitive job market, excelling in technical interviews, particularly coding rounds, is essential to secure a job in a reputed company like Wipro. Coding tests assess how well you understand algorithms, data structures, and various programming languages, and how efficiently you can implement solutions.
The purpose of this article is to provide you with an in-depth guide to preparing for Wipro’s coding interviews. It includes coding questions, solutions, tips, and tricks that will help you succeed.
Understanding Wipro’s Coding Assessment
Wipro’s coding interview is designed to test your understanding of algorithms and data structures, as well as your ability to think critically and solve problems. The test usually contains questions of varying difficulty levels, from basic to advanced.
Types of Coding Questions Asked in Wipro Interviews
Wipro’s coding interviews typically include a wide variety of question types, focusing on:
- String Manipulation: Questions that test your ability to manipulate and process strings.
- Array Operations: Problems where you must implement sorting, searching, or other array-based operations.
- Linked Lists: Implementing or manipulating linked lists.
- Stacks and Queues: Implementing stacks and queues or solving problems using these data structures.
- Tree and Graph Algorithms: Questions that test your knowledge of traversal algorithms (BFS, DFS) and other tree/graph-based operations.
- Dynamic Programming: Questions that test your ability to optimise algorithms using dynamic programming techniques.
- Greedy Algorithms: Problems that can be solved by making local optimum choices at each stage.
Difficulty Level of the Questions
The difficulty level varies depending on the role you are applying for. For entry-level positions, most of the questions are basic to intermediate in difficulty. However, for senior-level or more experienced candidates, Wipro tends to ask more challenging questions, which may require a deep understanding of algorithms and data structures.
Time Constraints and Expected Outcomes
The coding test is typically timed, with candidates given anywhere from 30 to 90 minutes to complete it. During this time, candidates are required to solve as many coding problems as possible. The number of questions can vary, but you will generally face between 2 to 4 problems.
Efficient time management is critical. You must aim to solve the easier problems quickly and allocate enough time for more complex questions. Moreover, it’s important to not only provide a correct solution but also to optimise your code in terms of time and space complexity.
Essential Coding Concepts for Wipro
To do well in Wipro’s coding interview, it’s essential to have a solid understanding of several core coding concepts. These concepts form the foundation of most coding questions that Wipro might ask.
Data Structures
Data structures are a crucial part of any coding interview. Below are the most important ones that you need to understand and practice:
Arrays
Arrays are one of the most common data structures and are used in a wide variety of problems. You should be able to:
Access, insert, and delete elements from an array.
Perform operations such as finding the maximum or minimum element.
Merge, rotate, or reverse arrays.
Example Question: Write a program to find the second largest element in an array.
python
def second_largest(arr):
first = second = -float(‘inf’)
for num in arr:
if num > first:
second = first
first = num
elif num > second and num != first:
second = num
return second if second != -float(‘inf’) else None
# Example usage:
array = [3, 1, 4, 1, 5, 9]
print(second_largest(array)) # Output: 5
Linked Lists
Linked lists are another common data structure you should know well. Be prepared to write code for:
Traversing a linked list.
Inserting, deleting, or searching for elements.
Reversing a linked list.
Example Question: Reverse a singly linked list.
python
class Node:
def __init__(self, value):
self.value = value
self.next = None
def reverse_linked_list(head):
prev = None
current = head
while current:
next_node = current.next
current.next = prev
prev = current
current = next_node
return prev
# Example usage:
head = Node(1)
head.next = Node(2)
head.next.next = Node(3)
reversed_head = reverse_linked_list(head)
Stacks and Queues
Stacks and queues are linear data structures that follow specific rules for insertion and deletion of elements. Common stack operations include push, pop, and peek, while common queue operations include enqueue and dequeue.
Example Question: Implement a queue using two stacks.
python
class QueueUsingStacks:
def __init__(self):
self.stack1 = []
self.stack2 = []
def enqueue(self, item):
self.stack1.append(item)
def dequeue(self):
if not self.stack2:
while self.stack1:
self.stack2.append(self.stack1.pop())
if self.stack2:
return self.stack2.pop()
else:
return “Queue is empty”
# Example usage:
queue = QueueUsingStacks()
queue.enqueue(10)
queue.enqueue(20)
print(queue.dequeue()) # Output: 10
Trees
Binary trees and binary search trees (BSTs) are common in coding problems. You should be able to:
Traverse a binary tree (in-order, pre-order, post-order).
Search for an element in a BST.
Find the height or depth of a tree.
Example Question: Find the maximum depth of a binary tree.
python
class TreeNode:
def __init__(self, value):
self.value = value
self.left = None
self.right = None
def max_depth(root):
if root is None:
return 0
return 1 + max(max_depth(root.left), max_depth(root.right))
# Example usage:
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
print(max_depth(root)) # Output: 2
Graphs
Graphs are widely used in more advanced coding problems. You need to understand graph traversal techniques like DFS (Depth-First Search) and BFS (Breadth-First Search), as well as algorithms for shortest paths and connectivity.
Example Question: Implement BFS traversal for a graph.
python
from collections import deque
class Graph:
def __init__(self):
self.graph = {}
def add_edge(self, u, v):
if u not in self.graph:
self.graph[u] = []
self.graph[u].append(v)
def bfs(self, start):
visited = set()
queue = deque([start])
visited.add(start)
while queue:
vertex = queue.popleft()
print(vertex, end=” “)
for neighbor in self.graph[vertex]:
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
# Example usage:
g = Graph()
g.add_edge(0, 1)
g.add_edge(0, 2)
g.add_edge(1, 2)
g.add_edge(2, 0)
g.add_edge(2, 3)
g.add_edge(3, 3)
g.bfs(2) # Output: 2 0 3 1
Algorithms
Algorithms are procedures or formulas for solving problems. Some of the most common types of algorithms in coding interviews include sorting, searching, dynamic programming, and greedy algorithms.
Sorting Algorithms
Sorting is one of the fundamental operations in computer science. You should be able to implement various sorting algorithms, such as:
- Bubble Sort
- Insertion Sort
- Selection Sort
- Merge Sort
- Quick Sort
Example Question: Implement quicksort.
python
def quicksort(arr):
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]
return quicksort(left) + middle + quicksort(right)
# Example usage:
array = [3, 6, 8, 10, 1, 2, 1]
print(quicksort(array)) # Output: [1, 1, 2, 3, 6, 8, 10]
Searching Algorithms
Searching algorithms are used to find elements within data structures. The most common algorithms include:
- Linear Search: Searching through each element sequentially.
- Binary Search: Efficient search for sorted arrays.
Example Question: Implement binary search.
python
def binary_search(arr, target):
low, high = 0, len(arr) – 1
while low <= high:
mid = (low + high) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
low = mid + 1
else:
high = mid – 1
return -1
# Example usage:
array = [1, 2, 3, 4, 5, 6]
target = 4
print(binary_search(array, target)) # Output: 3
Dynamic Programming
Dynamic programming is a method for solving complex problems by breaking them down into simpler subproblems. It’s used in optimization problems, where you need to make decisions at each stage that optimise the overall result.
Example Question: Solve the longest common subsequence problem.
python
def lcs(X, Y):
m, n = len(X), len(Y)
dp = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(1, m + 1):
for j in range(1, n + 1):
if X[i – 1] == Y[j – 1]:
dp[i][j] = dp[i – 1][j – 1] + 1
else:
dp[i][j] = max(dp[i – 1][j], dp[i][j – 1])
return dp[m][n]
# Example usage:
X = “AGGTAB”
Y = “GXTXAYB”
print(lcs(X, Y)) # Output: 4
Greedy Algorithms
Greedy algorithms make decisions based on the best choice available at each stage. They are used in optimization problems such as the Minimum Spanning Tree (MST) and Huffman coding.
Example Question: Implement Kruskal’s algorithm to find the minimum spanning tree.
python
class Graph:
def __init__(self, vertices):
self.V = vertices
self.graph = []
def add_edge(self, u, v, w):
self.graph.append([u, v, w])
def find(self, parent, i):
if parent[i] == i:
return i
return self.find(parent, parent[i])
def union(self, parent, rank, x, y):
root_x = self.find(parent, x)
root_y = self.find(parent, y)
if rank[root_x] < rank[root_y]:
parent[root_x] = root_y
elif rank[root_x] > rank[root_y]:
parent[root_y] = root_x
else:
parent[root_y] = root_x
rank[root_x] += 1
def kruskal_mst(self):
result = []
self.graph = sorted(self.graph, key=lambda item: item[2])
parent = []
rank = []
for node in range(self.V):
parent.append(node)
rank.append(0)
e = 0
i = 0
while e < self.V – 1:
u, v, w = self.graph[i]
i += 1
x = self.find(parent, u)
y = self.find(parent, v)
if x != y:
e += 1
result.append([u, v, w])
self.union(parent, rank, x, y)
return result
# Example usage:
g = Graph(4)
g.add_edge(0, 1, 10)
g.add_edge(0, 2, 6)
g.add_edge(0, 3, 5)
g.add_edge(1, 3, 15)
g.add_edge(2, 3, 4)
mst = g.kruskal_mst()
print(mst) # Output: [[2, 3, 4], [0, 3, 5], [0, 1, 10]]
Now that you know what to expect, let’s explore common Wipro coding questions and their solutions.
Common Wipro Coding Questions and Solutions
Practice makes perfect! Let’s look at some common Wipro coding questions and their solutions.
Basic-Level Questions
Reverse a String
Write a program to reverse a given string.
python
def reverse_string(s):
return s[::-1]
# Example usage:
string = “Wipro”
print(reverse_string(string)) # Output: “orpiW”
Find the Factorial of a Number
Write a program to calculate the factorial of a number.
python
def factorial(n):
if n == 0 or n == 1:
return 1
else:
return n * factorial(n-1)
# Example usage:
num = 5
print(factorial(num)) # Output: 120
Check for Palindrome
Write a program to check if a given string is a palindrome.
python
def is_palindrome(s):
return s == s[::-1]
# Example usage:
word = “radar”
print(is_palindrome(word)) # Output: True
Calculate the Fibonacci Series
Write a program to generate the Fibonacci series up to a given number.
python
def fibonacci(n):
fib_sequence = [0, 1]
for i in range(2, n):
fib_sequence.append(fib_sequence[-1] + fib_sequence[-2])
return fib_sequence
# Example usage:
num = 10
print(fibonacci(num)) # Output: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
Intermediate-Level Questions
Implement a Stack Using an Array
Write a program to implement a stack using an array with push and pop operations.
python
class Stack:
def __init__(self):
self.stack = []
def push(self, item):
self.stack.append(item)
def pop(self):
if not self.is_empty():
return self.stack.pop()
return “Stack is empty”
def is_empty(self):
return len(self.stack) == 0
# Example usage:
my_stack = Stack()
my_stack.push(10)
my_stack.push(20)
print(my_stack.pop()) # Output: 20
Find the Maximum Element in an Array
Write a program to find the maximum element in an array.
python
def find_max(arr):
max_element = arr[0]
for num in arr:
if num > max_element:
max_element = num
return max_element
# Example usage:
array = [3, 5, 7, 2, 8]
print(find_max(array)) # Output: 8
Merge Two Sorted Arrays
Write a program to merge two sorted arrays into a single sorted array.
python
def merge_arrays(arr1, arr2):
merged = []
i = j = 0
while i < len(arr1) and j < len(arr2):
if arr1[i] < arr2[j]:
merged.append(arr1[i])
i += 1
else:
merged.append(arr2[j])
j += 1
merged.extend(arr1[i:])
merged.extend(arr2[j:])
return merged
# Example usage:
array1 = [1, 3, 5]
array2 = [2, 4, 6]
print(merge_arrays(array1, array2)) # Output: [1, 2, 3, 4, 5, 6]
Implement a Binary Search Algorithm
Write a program to implement binary search on a sorted array.
python
def binary_search(arr, target):
low, high = 0, len(arr) – 1
while low <= high:
mid = (low + high) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
low = mid + 1
else:
high = mid – 1
return -1
# Example usage:
array = [1, 3, 5, 7, 9]
target = 5
print(binary_search(array, target)) # Output: 2
Advanced-Level Questions
Implement a Graph Data Structure and its Traversal Algorithms (BFS, DFS)
Write a program to implement a graph using an adjacency list and perform BFS and DFS.
python
from collections import deque
class Graph:
def __init__(self):
self.graph = {}
def add_edge(self, u, v):
if u not in self.graph:
self.graph[u] = []
self.graph[u].append(v)
def bfs(self, start):
visited = set()
queue = deque([start])
visited.add(start)
while queue:
node = queue.popleft()
print(node, end=” “)
for neighbor in self.graph[node]:
if neighbor not in visited:
queue.append(neighbor)
visited.add(neighbor)
def dfs(self, start, visited=None):
if visited is None:
visited = set()
visited.add(start)
print(start, end=” “)
for neighbor in self.graph[start]:
if neighbor not in visited:
self.dfs(neighbor, visited)
# Example usage:
g = Graph()
g.add_edge(0, 1)
g.add_edge(0, 2)
g.add_edge(1, 2)
g.add_edge(2, 0)
g.add_edge(2, 3)
g.add_edge(3, 3)
print(“BFS traversal:”)
g.bfs(2) # Output: 2 0 3 1
print(“\nDFS traversal:”)
g.dfs(2) # Output: 2 0 1 3
Solve a Dynamic Programming Problem (Longest Common Subsequence)
Write a program to find the longest common subsequence (LCS) between two strings. LCS is a classic dynamic programming problem where we aim to find the longest sequence that can be obtained by deleting characters from two strings without changing the order of the remaining characters.
python
def lcs(X, Y):
m = len(X)
n = len(Y)
L = [[None]*(n+1) for i in range(m+1)]
for i in range(m+1):
for j in range(n+1):
if i == 0 or j == 0:
L[i][j] = 0
elif X[i-1] == Y[j-1]:
L[i][j] = L[i-1][j-1] + 1
else:
L[i][j] = max(L[i-1][j], L[i][j-1])
return L[m][n]
# Example usage:
X = “AGGTAB”
Y = “GXTXAYB”
print(“Length of LCS is”, lcs(X, Y)) # Output: 4
In this example, the longest common subsequence of the strings “AGGTAB” and “GXTXAYB” is “GTAB”, which has a length of 4. This solution uses dynamic programming, storing the intermediate results in a table to avoid redundant computations.
Implement a Greedy Algorithm (Minimum Spanning Tree Using Kruskal’s Algorithm)
A Minimum Spanning Tree (MST) is a subset of the edges in a graph that connects all the vertices together with the minimal total edge weight. Kruskal’s algorithm is one of the most efficient algorithms to find an MST.
python
class Graph:
def __init__(self, vertices):
self.V = vertices
self.graph = []
def add_edge(self, u, v, w):
self.graph.append([u, v, w])
def find(self, parent, i):
if parent[i] == i:
return i
return self.find(parent, parent[i])
def union(self, parent, rank, x, y):
root_x = self.find(parent, x)
root_y = self.find(parent, y)
if rank[root_x] < rank[root_y]:
parent[root_x] = root_y
elif rank[root_x] > rank[root_y]:
parent[root_y] = root_x
else:
parent[root_y] = root_x
rank[root_x] += 1
def kruskal_mst(self):
result = [] # This will store the resultant MST
i, e = 0, 0 # i is an index variable, e is used for result[]
# Step 1: Sort all the edges in non-decreasing order of their weight
self.graph = sorted(self.graph, key=lambda item: item[2])
parent, rank = [], []
for node in range(self.V):
parent.append(node)
rank.append(0)
# Number of edges to be taken is equal to V-1
while e < self.V – 1:
u, v, w = self.graph[i]
i += 1
x = self.find(parent, u)
y = self.find(parent, v)
if x != y:
e += 1
result.append([u, v, w])
self.union(parent, rank, x, y)
return result
# Example usage:
g = Graph(4)
g.add_edge(0, 1, 10)
g.add_edge(0, 2, 6)
g.add_edge(0, 3, 5)
g.add_edge(1, 3, 15)
g.add_edge(2, 3, 4)
mst = g.kruskal_mst()
print(“Minimum Spanning Tree:”, mst) # Output: [[2, 3, 4], [0, 3, 5], [0, 1, 10]]
In this example, the graph has four vertices and the output shows the edges that form the Minimum Spanning Tree, resulting in the minimum possible total weight.
Solve a Coding Puzzle or Brain Teaser
Coding puzzles are designed to test your logical thinking and problem-solving skills. These questions are often challenging and are used in coding interviews to gauge how well you approach complex problems. Here’s an example of a coding puzzle:
Question: Write a program to find all unique triplets in an array that give the sum of zero.
python
def find_triplets(arr):
arr.sort()
triplets = []
for i in range(len(arr) – 2):
if i > 0 and arr[i] == arr[i – 1]:
continue
left, right = i + 1, len(arr) – 1
while left < right:
total = arr[i] + arr[left] + arr[right]
if total == 0:
triplets.append([arr[i], arr[left], arr[right]])
while left < right and arr[left] == arr[left + 1]:
left += 1
while left < right and arr[right] == arr[right – 1]:
right -= 1
left += 1
right -= 1
elif total < 0:
left += 1
else:
right -= 1
return triplets
# Example usage:
array = [-1, 0, 1, 2, -1, -4]
print(find_triplets(array)) # Output: [[-1, -1, 2], [-1, 0, 1]]
This puzzle requires sorting the array and then using two pointers to find triplets whose sum equals zero. It’s a common question in coding interviews that tests your understanding of array manipulation and sorting algorithms.
While these questions can help you prepare, there are additional tips and tricks to improve your chances of success.
Tips and Tricks for Wipro Coding Interviews
Preparing for coding interviews is not just about knowing how to solve the problems, but also about how to approach the interview process itself. Here are some practical tips that can help you perform better during Wipro’s coding interviews:
1) Effective Problem-Solving Techniques
When you are faced with a coding problem during an interview, it’s important to approach it systematically. Here’s a step-by-step process you can follow:
- Understand the problem: Carefully read the problem statement and make sure you understand it fully before attempting to code. Ask clarifying questions if something is unclear.
- Break it down: Divide the problem into smaller, manageable parts. Think about how you would solve each part of the problem.
- Plan your approach: Before jumping into coding, decide which data structures and algorithms are most appropriate for solving the problem. Consider edge cases and potential issues with your approach.
- Write clean code: Start coding once you’re confident in your approach. Make sure your code is clean, well-organised, and easy to read.
2) Time Management Strategies
In coding interviews, managing your time efficiently is crucial. Most coding tests are timed, and you need to strike a balance between solving all the problems and optimising your solutions. Here are some time management tips:
- Prioritise easier questions: Solve the easy problems first to ensure you secure those points. Once you’ve completed them, move on to the more difficult ones.
- Don’t get stuck on one problem: If you find yourself stuck on a particular question for too long, move on to the next one. You can always come back later if you have time.
- Optimise after solving: Focus on writing a working solution first, and then optimise it if you have extra time.
3) Coding Best Practices and Conventions
Employing best practices in your code can make a significant difference in how interviewers perceive your coding skills. Here are a few key tips:
- Use meaningful variable names: Instead of using single-letter variable names like “i” or “j” (except in loops), use descriptive names like “index” or “count” to make your code easier to understand.
- Comment your code: Write comments to explain what your code is doing, especially if the logic is complex.
- Follow consistent formatting: Proper indentation and code formatting not only make your code more readable but also demonstrate professionalism.
- Use built-in functions when appropriate: Programming languages like Python offer many built-in functions that are highly optimised, such as sort() or len(). Use them when possible instead of writing your own.
4) Common Mistakes to Avoid
Candidates often make certain mistakes during coding interviews that can cost them the job. Be mindful of these common errors:
- Over-complicating the solution: Many candidates try to impress the interviewer with overly complex solutions. However, simpler solutions are often preferred if they are efficient.
- Neglecting edge cases: Make sure you handle edge cases like empty arrays, null values, or very large inputs.
- Failing to test the code: Always test your code with sample inputs before submitting it. This will help you catch any errors and avoid failing the test.
5) Importance of Clarity and Communication
During a live coding interview, it’s important to communicate clearly with the interviewer. Explain your thought process, describe why you are choosing a particular approach, and make sure you articulate any assumptions you are making about the problem. This not only shows confidence but also helps the interviewer understand your approach.
- Explain your reasoning: Talk through your thought process as you solve the problem. This demonstrates that you can approach problems methodically and make informed decisions.
- Ask clarifying questions: If a problem statement is unclear, don’t hesitate to ask the interviewer for more information. This can help avoid confusion and ensure you are solving the right problem.
- Be honest about what you don’t know: If you’re unsure about something, it’s better to admit it rather than attempting a solution that you know is flawed. Interviewers appreciate honesty and a willingness to learn.
Conclusion
Preparing for Wipro’s coding interviews can be challenging, but with the right knowledge and approach, you can significantly increase your chances of success. Understanding the fundamentals of data structures, algorithms, and problem-solving techniques is essential. By practising coding questions of varying difficulty levels, and following the tips and best practices outlined in this guide, you’ll be well-prepared to excel in the coding assessments.