Arrays and Strings: Concepts, Techniques, and Interview Questions
By: Developer Akash
Introduction
Arrays and strings are fundamental data structures in programming, providing the foundation for solving many complex problems efficiently. This article explores key concepts, advanced techniques, and problem-solving strategies associated with arrays and strings, making it a comprehensive guide for students, professionals, and interview preparation.
Basic Operations on Arrays
1. Traversal
Traversal refers to accessing each element of an array once. For example:
// Example in C++
int arr[] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; i++) {
cout << arr[i] << " ";
}
2. Insertion
Inserting an element into an array involves shifting elements and placing the new element in the desired position.
// Insert 10 at index 2 in C++
int arr[6] = {1, 2, 3, 4, 5};
int pos = 2, n = 5, element = 10;
for (int i = n; i > pos; i--) {
arr[i] = arr[i - 1];
}
arr[pos] = element;
3. Deletion
Deleting an element involves shifting elements to fill the gap left by the removed element.
// Delete element at index 2
int arr[] = {1, 2, 3, 4, 5};
int pos = 2, n = 5;
for (int i = pos; i < n - 1; i++) {
arr[i] = arr[i + 1];
}
Multi-Dimensional Arrays
Multi-dimensional arrays store data in rows and columns (2D arrays) or more dimensions. They are widely used for grid-like problems.
// Declaring a 2D array
int matrix[3][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
Advanced Techniques for Arrays and Strings
1. Sliding Window Technique
The sliding window is a powerful technique to solve problems like finding subarrays or substrings that meet specific conditions.
// Maximum sum of subarray of size k
int maxSum(int arr[], int n, int k) {
int max_sum = 0, window_sum = 0;
for (int i = 0; i < k; i++) {
window_sum += arr[i];
}
max_sum = window_sum;
for (int i = k; i < n; i++) {
window_sum += arr[i] - arr[i - k];
max_sum = max(max_sum, window_sum);
}
return max_sum;
}
2. Two-Pointer Technique
This technique is used to solve problems involving sorted arrays, like finding pairs that sum to a target.
// Find if a pair sums to target
bool hasPair(int arr[], int n, int target) {
int left = 0, right = n - 1;
while (left < right) {
int sum = arr[left] + arr[right];
if (sum == target) return true;
else if (sum < target) left++;
else right--;
}
return false;
}
String Manipulation
1. Palindromes
A palindrome reads the same backward and forward. To check if a string is a palindrome:
bool isPalindrome(string s) {
int left = 0, right = s.length() - 1;
while (left < right) {
if (s[left] != s[right]) return false;
left++; right--;
}
return true;
}
2. Anagrams
Two strings are anagrams if they contain the same characters in a different order. Use frequency counts to check for anagrams.
bool isAnagram(string s1, string s2) {
if (s1.length() != s2.length()) return false;
int count[26] = {0};
for (char c : s1) count[c - 'a']++;
for (char c : s2) {
if (--count[c - 'a'] < 0) return false;
}
return true;
}
3. Pattern Matching (KMP Algorithm)
The Knuth-Morris-Pratt (KMP) algorithm efficiently finds substrings by preprocessing the pattern.
void computeLPS(string pattern, int lps[]) {
int length = 0, i = 1;
lps[0] = 0;
while (i < pattern.length()) {
if (pattern[i] == pattern[length]) {
lps[i++] = ++length;
} else {
if (length != 0) length = lps[length - 1];
else lps[i++] = 0;
}
}
}
Subarray Problems
Kadane’s Algorithm
This algorithm finds the maximum sum of a contiguous subarray in O(n) time.
int kadane(int arr[], int n) {
int max_sum = INT_MIN, current_sum = 0;
for (int i = 0; i < n; i++) {
current_sum = max(arr[i], current_sum + arr[i]);
max_sum = max(max_sum, current_sum);
}
return max_sum;
}
Interview Questions and Answers
- Explain the differences between arrays and linked lists.
Answer: Arrays are a collection of elements stored in contiguous memory locations, allowing random access with an index. Linked lists consist of nodes, where each node contains a data field and a pointer to the next node. Arrays offer constant-time access for elements but have a fixed size, while linked lists provide dynamic size and efficient insertion/deletion but require sequential access.
- How does the sliding window technique work? Provide examples.
Answer: The sliding window technique involves maintaining a subset of elements within a "window" and moving it across the array. For example, to find the maximum sum of a subarray of size
k, calculate the sum of the firstkelements and adjust the sum by adding the next element and removing the first element of the previous window.// Example in C++ int maxSum(int arr[], int n, int k) { int max_sum = 0, window_sum = 0; for (int i = 0; i < k; i++) { window_sum += arr[i]; } max_sum = window_sum; for (int i = k; i < n; i++) { window_sum += arr[i] - arr[i - k]; max_sum = max(max_sum, window_sum); } return max_sum; } - Write a function to check if two strings are rotations of each other.
Answer: Concatenate the first string with itself and check if the second string is a substring of this concatenated string.
bool isRotation(string s1, string s2) { if (s1.length() != s2.length()) return false; string temp = s1 + s1; return temp.find(s2) != string::npos; } - What are the advantages of Kadane's Algorithm over brute-force methods?
Answer: Kadane's Algorithm finds the maximum sum of a contiguous subarray in
O(n)time, while brute-force methods takeO(n^2)orO(n^3)time. It avoids unnecessary calculations by keeping track of the current sum and maximum sum. - Implement the KMP algorithm and explain its time complexity.
Answer: The KMP algorithm preprocesses the pattern into an LPS (Longest Prefix Suffix) array to skip unnecessary comparisons. Its time complexity is
O(n + m), wherenis the text length andmis the pattern length.void computeLPS(string pattern, int lps[]) { int length = 0, i = 1; lps[0] = 0; while (i < pattern.length()) { if (pattern[i] == pattern[length]) { lps[i++] = ++length; } else { if (length != 0) length = lps[length - 1]; else lps[i++] = 0; } } } - How do you reverse a string in place?
Answer: Use two pointers, one starting at the beginning and the other at the end, and swap their values while moving the pointers towards the center.
void reverseString(char str[]) { int left = 0, right = strlen(str) - 1; while (left < right) { swap(str[left], str[right]); left++; right--; } } - Find the longest palindromic substring in a given string.
Answer: Use dynamic programming or expand around each character as the center. Expanding around the center is efficient with
O(n^2)complexity.string longestPalindrome(string s) { int start = 0, maxLength = 0; for (int i = 0; i < s.length(); i++) { int len1 = expandAroundCenter(s, i, i); // Odd length int len2 = expandAroundCenter(s, i, i+1); // Even length int len = max(len1, len2); if (len > maxLength) { maxLength = len; start = i - (len - 1) / 2; } } return s.substr(start, maxLength); } int expandAroundCenter(string s, int left, int right) { while (left >= 0 && right < s.length() && s[left] == s[right]) { left--; right++; } return right - left - 1; } - Given an array of integers, find all unique triplets that sum to zero.
Answer: Use sorting and a two-pointer approach to efficiently find unique triplets.
vector> threeSum(vector& nums) { sort(nums.begin(), nums.end()); vector> result; for (int i = 0; i < nums.size() - 2; i++) { if (i > 0 && nums[i] == nums[i-1]) continue; int left = i + 1, right = nums.size() - 1, target = -nums[i]; while (left < right) { int sum = nums[left] + nums[right]; if (sum == target) { result.push_back({nums[i], nums[left], nums[right]}); while (left < right && nums[left] == nums[left + 1]) left++; while (left < right && nums[right] == nums[right - 1]) right--; left++; right--; } else if (sum < target) left++; else right--; } } return result; } - Explain how you can use hashing to solve anagram problems efficiently.
Answer: Use a frequency count of characters as the key in a hash map. If two strings have the same character frequency, they are anagrams.
bool isAnagram(string s1, string s2) { if (s1.length() != s2.length()) return false; unordered_map freq; for (char c : s1) freq[c]++; for (char c : s2) { if (--freq[c] < 0) return false; } return true; }