C++ Grammar and Syntax Guide for Coding Interviews (Algorithms & DS)#
Core Data Types and Variables#
Basic Types#
int x = 5; // Integer
long long bigNum = 1LL<<60; // Large integer (note LL suffix)
double y = 3.14; // Double precision floating point
bool flag = true; // Boolean
char c = 'A'; // Character
string s = "Hello"; // String (requires #include <string>)
Type Modifiers#
unsigned int positiveOnly = 100; // Only non-negative values
const int FIXED = 10; // Cannot be modified after initialization
Type Aliases#
typedef long long ll; // Old style type alias
using ll = long long; // Modern style type alias (preferred)
Auto Type Deduction#
auto num = 10; // Compiler deduces type (int in this case)
auto it = myVector.begin(); // Iterator type automatically deduced
Operators and Expressions#
Arithmetic Operators#
int a = 5 + 3; // Addition: 8
int b = 5 - 3; // Subtraction: 2
int c = 5 * 3; // Multiplication: 15
int d = 5 / 3; // Integer division: 1
int e = 5 % 3; // Modulo (remainder): 2
double f = 5.0/3; // Floating-point division: 1.6666...
Compound Assignment#
a += 2; // Same as a = a + 2
a -= 2; // Same as a = a - 2
a *= 2; // Same as a = a * 2
a /= 2; // Same as a = a / 2
a %= 2; // Same as a = a % 2
Increment/Decrement#
int a = 5;
int b = ++a; // Pre-increment: a becomes 6, b becomes 6
int c = a++; // Post-increment: c becomes 6, then a becomes 7
int d = --a; // Pre-decrement: a becomes 6, d becomes 6
int e = a--; // Post-decrement: e becomes 6, then a becomes 5
Comparison Operators#
bool isEqual = (a == b); // Equal to
bool isNotEqual = (a != b); // Not equal to
bool isGreater = (a > b); // Greater than
bool isLess = (a < b); // Less than
bool isGreaterEq = (a >= b); // Greater than or equal to
bool isLessEq = (a <= b); // Less than or equal to
Logical Operators#
bool andResult = (a > 0 && b > 0); // Logical AND (short-circuit)
bool orResult = (a > 0 || b > 0); // Logical OR (short-circuit)
bool notResult = !a; // Logical NOT
Bitwise Operators#
int bitwiseAnd = a & b; // Bitwise AND
int bitwiseOr = a | b; // Bitwise OR
int bitwiseXor = a ^ b; // Bitwise XOR
int bitwiseNot = ~a; // Bitwise NOT
int leftShift = a << 2; // Left shift (multiply by 2^2)
int rightShift = a >> 2; // Right shift (divide by 2^2)
Ternary Operator#
int max = (a > b) ? a : b; // If a > b, max = a; otherwise max = b
Control Flow#
Conditionals#
// If-else statement
if (x > 0) {
cout << "Positive";
} else if (x < 0) {
cout << "Negative";
} else {
cout << "Zero";
}
// Switch statement
switch (x) {
case 1:
cout << "One";
break;
case 2:
cout << "Two";
break;
default:
cout << "Other";
}
Loops#
// For loop
for (int i = 0; i < n; i++) {
// Body
}
// Range-based for loop (C++11)
for (auto element : container) {
// Process each element
}
// While loop
while (condition) {
// Body
}
// Do-while loop
do {
// Body
} while (condition);
Loop Control#
for (int i = 0; i < n; i++) {
if (condition1)
continue; // Skip current iteration
if (condition2)
break; // Exit loop completely
}
Functions#
Basic Function#
// Declaration and definition
int add(int a, int b) {
return a + b;
}
// Usage
int sum = add(5, 3); // sum = 8
Default Parameters#
int multiply(int a, int b = 1) {
return a * b;
}
int product1 = multiply(5); // b defaults to 1, result = 5
int product2 = multiply(5, 3); // b is 3, result = 15
Function Overloading#
int max(int a, int b) {
return (a > b) ? a : b;
}
double max(double a, double b) {
return (a > b) ? a : b;
}
Pass by Reference#
void swap(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
int x = 5, y = 10;
swap(x, y); // After this: x = 10, y = 5
Lambda Functions (C++11)#
// Basic syntax: [capture](parameters) -> returnType { body }
auto add = [](int a, int b) -> int { return a + b; };
// Capture by value
int multiplier = 2;
auto multiply = [multiplier](int x) { return x * multiplier; };
// Capture by reference
auto increment = [&multiplier]() { multiplier++; };
// Capture all by value
auto lambda1 = [=]() { /* can use all variables by value */ };
// Capture all by reference
auto lambda2 = [&]() { /* can use all variables by reference */ };
// Capture specific variables with different methods
auto lambda3 = [x, &y]() { /* x by value, y by reference */ };
Function Pointers and std::function#
#include <functional>
// Function pointer
int (*funcPtr)(int, int) = add;
// std::function object (more versatile)
std::function<int(int, int)> func = add;
// Can also store lambdas
std::function<int(int)> doubler = [](int x) { return x * 2; };
Arrays and Strings#
Arrays#
// Declaration and initialization
int arr1[5]; // Uninitialized array of 5 integers
int arr2[5] = {1, 2, 3, 4, 5}; // Initialized array
int arr3[] = {1, 2, 3, 4, 5}; // Size deduced from initializer
int arr4[5] = {1, 2}; // Partial initialization (rest are 0)
// Multidimensional arrays
int matrix[3][4]; // 3×4 matrix (3 rows, 4 columns)
int cube[3][3][3]; // 3D array
// Accessing elements
int first = arr2[0]; // First element (1-based indexing)
int last = arr2[4]; // Last element
// Common error: arrays don't track their size
int size = sizeof(arr2) / sizeof(arr2[0]); // Calculate array size
C-style Strings#
char str1[] = "Hello"; // Null-terminated character array
char str2[10] = "Hello"; // With explicit size
const char* str3 = "Hello"; // String literal (read-only)
// String operations (require <cstring>)
#include <cstring>
size_t len = strlen(str1); // Length: 5
char concat[20];
strcpy(concat, str1); // Copy str1 to concat
strcat(concat, " World"); // Append to concat
int comp = strcmp(str1, str2); // Compare strings
C++ Strings#
#include <string>
// Declaration and initialization
string s1; // Empty string
string s2 = "Hello"; // From string literal
string s3(5, 'a'); // String of 5 'a's: "aaaaa"
string s4 = s2; // Copy of s2
// Operations
int length = s2.length(); // or s2.size()
char first = s2[0]; // Access character (no bounds checking)
char safe = s2.at(0); // Access with bounds checking
string concat = s2 + " World"; // String concatenation
s2 += " World"; // Append to s2
string sub = s2.substr(0, 5); // Substring (starting at 0, length 5)
// Searching
size_t pos = s2.find("llo"); // Find substring (returns position or string::npos)
bool contains = s2.find("llo") != string::npos; // Check if contains substring
// Comparison
bool isEqual = (s2 == s3); // String comparison
bool isLess = (s2 < s3); // Lexicographical comparison
// Modification
s2.replace(0, 1, "J"); // Replace "H" with "J"
s2.erase(0, 1); // Remove first character
s2.insert(0, "H"); // Insert at position 0
s2.clear(); // Empty the string
bool isEmpty = s2.empty(); // Check if empty
STL Containers#
Vector#
#include <vector>
// Declaration and initialization
vector<int> v1; // Empty vector
vector<int> v2(5); // Vector of 5 zeros
vector<int> v3(5, 10); // Vector of five 10s
vector<int> v4 = {1, 2, 3, 4, 5}; // Using initializer list
vector<int> v5(v4); // Copy of v4
vector<int> v6(v4.begin(), v4.begin()+3); // First 3 elements of v4
// Size operations
int size = v4.size(); // Number of elements
bool isEmpty = v4.empty(); // Check if empty
v4.resize(10); // Resize to 10 elements
v4.resize(12, 7); // Add 2 more elements with value 7
int capacity = v4.capacity(); // Current capacity
v4.reserve(20); // Reserve space for 20 elements
v4.shrink_to_fit(); // Reduce capacity to match size
// Element access
int first = v4[0]; // First element (no bounds checking)
int safe = v4.at(0); // With bounds checking
int front = v4.front(); // First element
int back = v4.back(); // Last element
int* data = v4.data(); // Pointer to underlying array
// Modifiers
v4.push_back(6); // Add element to end
v4.pop_back(); // Remove last element
v4.insert(v4.begin() + 2, 10); // Insert 10 at position 2
v4.insert(v4.begin() + 2, 3, 10); // Insert 3 copies of 10
v4.insert(v4.begin() + 2, {7, 8, 9}); // Insert multiple elements
v4.erase(v4.begin() + 2); // Remove element at position 2
v4.erase(v4.begin(), v4.begin() + 3); // Remove range of elements
v4.clear(); // Remove all elements
vector<int>().swap(v4); // Clear and deallocate memory
// Iterating
for (auto it = v4.begin(); it != v4.end(); ++it) {
cout << *it << " ";
}
// Range-based loop (C++11)
for (int x : v4) {
cout << x << " ";
}
// Algorithm example (sort)
#include <algorithm>
sort(v4.begin(), v4.end()); // Sort in ascending order
sort(v4.begin(), v4.end(), greater<int>()); // Sort in descending order
// 2D vector
vector<vector<int>> matrix(3, vector<int>(4, 0)); // 3×4 matrix of zeros
int val = matrix[1][2]; // Access element
Pair and Tuple#
#include <utility> // For pair
#include <tuple> // For tuple
// Pair
pair<int, string> p1 = {1, "one"}; // Create pair
pair<int, string> p2 = make_pair(2, "two"); // Alternative creation
int first = p1.first; // Access first element
string second = p1.second; // Access second element
bool isLess = (p1 < p2); // Lexicographical comparison
// Tuple
tuple<int, string, double> t1 = {1, "one", 1.1}; // Create tuple
tuple<int, string, double> t2 = make_tuple(2, "two", 2.2);
int tFirst = get<0>(t1); // Access elements by index
string tSecond = get<1>(t1);
double tThird = get<2>(t1);
Set and Multiset#
#include <set>
// Set (sorted, no duplicates)
set<int> s1; // Empty set
set<int> s2 = {1, 2, 3, 4, 5}; // Using initializer list
set<int, greater<int>> s3; // Custom comparison (descending)
// Size operations
int size = s2.size(); // Number of elements
bool isEmpty = s2.empty(); // Check if empty
// Modifiers
s2.insert(6); // Insert element
auto result = s2.insert(6); // Returns pair<iterator, bool>
bool wasInserted = result.second; // Check if inserted
s2.erase(3); // Remove element by value
s2.erase(s2.begin()); // Remove element by iterator
s2.erase(s2.begin(), s2.find(4)); // Remove range
s2.clear(); // Remove all elements
// Lookup
auto it = s2.find(3); // Find element
bool contains = (it != s2.end()); // Check if found
int count = s2.count(3); // Count occurrences (0 or 1)
auto lower = s2.lower_bound(3); // First element >= 3
auto upper = s2.upper_bound(3); // First element > 3
auto range = s2.equal_range(3); // Both bounds as pair
// Multiset (sorted, allows duplicates)
multiset<int> ms = {1, 2, 2, 3, 3, 3}; // Create multiset
ms.insert(3); // Insert another 3
int count3 = ms.count(3); // Count of 3s (now 4)
Map and Multimap#
#include <map>
// Map (sorted key-value pairs, unique keys)
map<string, int> m1; // Empty map
map<string, int> m2 = {{"one", 1}, {"two", 2}}; // Using initializer list
map<string, int, greater<string>> m3; // Custom key comparison
// Element access
int value = m2["one"]; // Access by key (inserts if not found)
int valueOrDefault = m2.value_or("three", 0); // Value or default if not found
// Size operations
int size = m2.size(); // Number of elements
bool isEmpty = m2.empty(); // Check if empty
// Modifiers
m2["three"] = 3; // Insert or update
m2.insert({"four", 4}); // Insert only
m2.insert(make_pair("five", 5)); // Alternative insertion
auto result = m2.insert({"one", 10}); // Won't insert if key exists
bool wasInserted = result.second; // Check if inserted
m2.erase("one"); // Remove by key
m2.erase(m2.begin()); // Remove by iterator
m2.erase(m2.begin(), m2.find("three")); // Remove range
m2.clear(); // Remove all elements
// Lookup
auto it = m2.find("one"); // Find element
bool contains = (it != m2.end()); // Check if found
int count = m2.count("one"); // Count occurrences (0 or 1)
auto lower = m2.lower_bound("one"); // First key >= "one"
auto upper = m2.upper_bound("one"); // First key > "one"
auto range = m2.equal_range("one"); // Both bounds as pair
// Iterating
for (const auto& pair : m2) {
cout << pair.first << ": " << pair.second << endl;
}
// Multimap (sorted key-value pairs, allows duplicate keys)
multimap<string, int> mm = {{"one", 1}, {"two", 2}, {"one", 10}};
int countOne = mm.count("one"); // Count of "one" keys (2)
Unordered Containers#
#include <unordered_set>
#include <unordered_map>
// Unordered set (hash-based, no duplicates)
unordered_set<int> us = {1, 2, 3, 4, 5};
us.insert(6); // O(1) average insertion
bool contains = (us.find(3) != us.end()); // O(1) average lookup
// Unordered map (hash-based key-value pairs, unique keys)
unordered_map<string, int> um = {{"one", 1}, {"two", 2}};
um["three"] = 3; // O(1) average insertion
int value = um["one"]; // O(1) average lookup
// Hash table properties
float loadFactor = us.load_factor(); // Current load factor
float maxLoadFactor = us.max_load_factor(); // Max load factor
us.max_load_factor(0.7f); // Set max load factor
us.rehash(20); // Set minimum bucket count
us.reserve(15); // Reserve space for elements
Stack#
#include <stack>
// Declaration and initialization
stack<int> st; // Empty stack
// Operations
st.push(1); // Add element to top
st.push(2); // Add another element
int top = st.top(); // Access top element (2)
st.pop(); // Remove top element
bool isEmpty = st.empty(); // Check if empty
int size = st.size(); // Number of elements
Queue#
#include <queue>
// Declaration and initialization
queue<int> q; // Empty queue
// Operations
q.push(1); // Add element to back
q.push(2); // Add another element
int front = q.front(); // Access front element (1)
int back = q.back(); // Access back element (2)
q.pop(); // Remove front element
bool isEmpty = q.empty(); // Check if empty
int size = q.size(); // Number of elements
Priority Queue#
#include <queue>
// Declaration and initialization (max heap by default)
priority_queue<int> pq; // Empty priority queue (max-heap)
priority_queue<int, vector<int>, greater<int>> minpq; // Min-heap
// Operations
pq.push(3); // Add element
pq.push(1); // Add element
pq.push(4); // Add element
int top = pq.top(); // Access top element (largest: 4)
pq.pop(); // Remove top element
bool isEmpty = pq.empty(); // Check if empty
int size = pq.size(); // Number of elements
// Custom comparison
struct Compare {
bool operator()(const pair<int, int>& a, const pair<int, int>& b) {
return a.first > b.first; // Min-heap based on first element
}
};
priority_queue<pair<int, int>, vector<pair<int, int>>, Compare> customPQ;
Deque#
#include <deque>
// Declaration and initialization
deque<int> dq; // Empty deque
deque<int> dq2 = {1, 2, 3, 4, 5}; // Using initializer list
// Operations (all operations at both ends are efficient)
dq.push_back(6); // Add to back
dq.push_front(0); // Add to front
dq.pop_back(); // Remove from back
dq.pop_front(); // Remove from front
int front = dq.front(); // Access front element
int back = dq.back(); // Access back element
int element = dq[2]; // Random access
bool isEmpty = dq.empty(); // Check if empty
int size = dq.size(); // Number of elements
STL Algorithms#
#include <algorithm> // Most algorithms
#include <numeric> // Numeric algorithms like accumulate
#include <functional> // Function objects
Non-modifying Sequence Operations#
// Find
auto it = find(v.begin(), v.end(), value); // Find value
auto it = find_if(v.begin(), v.end(), // Find using predicate
[](int x) { return x > 10; });
int count = count(v.begin(), v.end(), value); // Count occurrences
int count = count_if(v.begin(), v.end(), // Count using predicate
[](int x) { return x % 2 == 0; });
// Comparison
bool allEven = all_of(v.begin(), v.end(), // Check if all meet condition
[](int x) { return x % 2 == 0; });
bool anyEven = any_of(v.begin(), v.end(), // Check if any meets condition
[](int x) { return x % 2 == 0; });
bool noneEven = none_of(v.begin(), v.end(), // Check if none meet condition
[](int x) { return x % 2 == 0; });
// Search
auto it = search(v1.begin(), v1.end(), // Find subsequence
v2.begin(), v2.end());
// Min/Max
auto minElement = min_element(v.begin(), v.end()); // Iterator to minimum
auto maxElement = max_element(v.begin(), v.end()); // Iterator to maximum
auto [minIt, maxIt] = minmax_element(v.begin(), v.end()); // Both at once
Modifying Sequence Operations#
// Copy
copy(src.begin(), src.end(), dest.begin()); // Copy range to destination
copy_if(src.begin(), src.end(), dest.begin(), // Copy with condition
[](int x) { return x > 0; });
copy_n(src.begin(), 5, dest.begin()); // Copy first n elements
// Transform
transform(src.begin(), src.end(), dest.begin(), // Apply function to each element
[](int x) { return x * 2; });
transform(src1.begin(), src1.end(), // Apply binary function
src2.begin(), dest.begin(),
[](int x, int y) { return x + y; });
// Generate and Fill
fill(v.begin(), v.end(), value); // Fill range with value
fill_n(v.begin(), 5, value); // Fill first n elements
generate(v.begin(), v.end(), // Generate values with function
[]() { return rand() % 100; });
iota(v.begin(), v.end(), 0); // Fill with increasing values
// Remove
auto newEnd = remove(v.begin(), v.end(), value); // Remove value (doesn't resize)
v.erase(newEnd, v.end()); // Actually erase removed elements
auto newEnd = remove_if(v.begin(), v.end(), // Remove with condition
[](int x) { return x < 0; });
// Replace
replace(v.begin(), v.end(), oldValue, newValue); // Replace value
replace_if(v.begin(), v.end(), // Replace with condition
[](int x) { return x < 0; }, 0);
// Reverse and Rotate
reverse(v.begin(), v.end()); // Reverse range
rotate(v.begin(), v.begin() + 3, v.end()); // Rotate elements
// Sorting
sort(v.begin(), v.end()); // Sort in ascending order
sort(v.begin(), v.end(), greater<int>()); // Sort in descending order
sort(v.begin(), v.end(), // Sort with custom comparator
[](int a, int b) { return abs(a) < abs(b); });
partial_sort(v.begin(), v.begin() + 5, v.end()); // Sort just first 5 elements
stable_sort(v.begin(), v.end()); // Stable sort
// Binary search (on sorted ranges)
bool found = binary_search(v.begin(), v.end(), value); // Check if exists
auto it = lower_bound(v.begin(), v.end(), value); // First element >= value
auto it = upper_bound(v.begin(), v.end(), value); // First element > value
auto [first, last] = equal_range(v.begin(), v.end(), value); // Both bounds
// Partitioning
auto it = partition(v.begin(), v.end(), // Partition by condition
[](int x) { return x % 2 == 0; });
bool isPartitioned = is_partitioned(v.begin(), v.end(), // Check if partitioned
[](int x) { return x % 2 == 0; });
// Nth element
nth_element(v.begin(), v.begin() + n, v.end()); // Nth element in sorted position
Numeric Operations#
#include <numeric>
// Basic operations
int sum = accumulate(v.begin(), v.end(), 0); // Sum of elements
int product = accumulate(v.begin(), v.end(), 1, // Product of elements
multiplies<int>());
int sum = reduce(v.begin(), v.end()); // C++17 parallel-friendly sum
// Adjacent element operations
vector<int> differences(v.size() - 1);
adjacent_difference(v.begin(), v.end(), // Differences of adjacent elements
differences.begin());
vector<int> sums(v.size() - 1);
adjacent_find(v.begin(), v.end(), // Find equal adjacent elements
sums.begin());
// Prefix sums
vector<int> prefixSums(v.size());
partial_sum(v.begin(), v.end(), prefixSums.begin()); // Cumulative sum
// Inner product
int dotProduct = inner_product(v1.begin(), v1.end(), // Dot product
v2.begin(), 0);
Heap Operations#
// Create heap
make_heap(v.begin(), v.end()); // Create max-heap
make_heap(v.begin(), v.end(), greater<int>()); // Create min-heap
// Heap operations
v.push_back(value); // Add element to end
push_heap(v.begin(), v.end()); // Fix heap after push_back
pop_heap(v.begin(), v.end()); // Move largest to end
v.pop_back(); // Remove element now at end
// Heap properties
bool isHeap = is_heap(v.begin(), v.end()); // Check if is a heap
auto it = is_heap_until(v.begin(), v.end()); // Iterator to first non-heap element
Set Operations (on sorted ranges)#
// Difference, union, intersection
set_difference(v1.begin(), v1.end(), // Elements in v1 but not in v2
v2.begin(), v2.end(),
result.begin());
set_union(v1.begin(), v1.end(), // Elements in either v1 or v2
v2.begin(), v2.end(),
result.begin());
set_intersection(v1.begin(), v1.end(), // Elements in both v1 and v2
v2.begin(), v2.end(),
result.begin());
set_symmetric_difference(v1.begin(), v1.end(), // Elements in either but not both
v2.begin(), v2.end(),
result.begin());
// Set membership
bool isSubset = includes(v1.begin(), v1.end(), // Check if v2 is subset of v1
v2.begin(), v2.end());
Common Algorithm Patterns#
Binary Search Implementation#
// Binary search on sorted array
bool binarySearch(const vector<int>& arr, int target) {
int left = 0;
int right = arr.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2; // Avoid overflow
if (arr[mid] == target)
return true;
else if (arr[mid] < target)
left = mid + 1;
else
right = mid - 1;
}
return false;
}
// Find first position greater than or equal to target
int lowerBound(const vector<int>& arr, int target) {
int left = 0;
int right = arr.size();
while (left < right) {
int mid = left + (right - left) / 2;
if (arr[mid] < target)
left = mid + 1;
else
right = mid;
}
return left;
}
// Find first position greater than target
int upperBound(const vector<int>& arr, int target) {
int left = 0;
int right = arr.size();
while (left < right) {
int mid = left + (right - left) / 2;
if (arr[mid] <= target)
left = mid + 1;
else
right = mid;
}
return left;
}
Two Pointers Technique#
// Find pair with given sum in sorted array
bool findPair(const vector<int>& arr, int target) {
int left = 0;
int right = arr.size() - 1;
while (left < right) {
int currentSum = arr[left] + arr[right];
if (currentSum == target)
return true;
else if (currentSum < target)
left++;
else
right--;
}
return false;
}
// Remove duplicates from sorted array in-place
int removeDuplicates(vector<int>& nums) {
if (nums.empty()) return 0;
int writeIndex = 1;
for (int readIndex = 1; readIndex < nums.size(); readIndex++) {
if (nums[readIndex] != nums[readIndex - 1]) {
nums[writeIndex++] = nums[readIndex];
}
}
return writeIndex;
}
// Find maximum water container (container with most water problem)
int maxArea(const vector<int>& height) {
int left = 0;
int right = height.size() - 1;
int maxWater = 0;
while (left < right) {
int h = min(height[left], height[right]);
int w = right - left;
maxWater = max(maxWater, h * w);
if (height[left] < height[right])
left++;
else
right--;
}
return maxWater;
}
// Three-sum problem
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;
if (nums.size() < 3) return result;
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size() - 2; i++) {
// Skip duplicates
if (i > 0 && nums[i] == nums[i-1]) continue;
int left = i + 1;
int right = nums.size() - 1;
int target = -nums[i];
while (left < right) {
int sum = nums[left] + nums[right];
if (sum == target) {
result.push_back({nums[i], nums[left], nums[right]});
// Skip duplicates
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;
}