C++ Algorithm Tricks
Universal Header File#
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
// Please enter your code here
return 0;
}
Cancel Synchronization of Streams#
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
getline#
getline(cin, string);
C-style Strings in string Class#
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
char buffer[100];
scanf("%s", buffer);
string str(buf);
printf("str = %s\n", str.c_str());
return 0;
}
str.c_str();
// Get string length
str.length();
// Concatenate strings
string res1 = str1 + "," + str2;
string res2 = str1.append(",").append(str2);
// String search
str.find();
// String replacement
// Starting position of substring, length of substring, replaced string
str.replace(7, 5, "xxxxx");
// Extract substring, do not go out of bounds
str.substr(7, 5);
// String comparison
str1.compare(str2);
Common Methods to Traverse string#
- Loop through indices
for(int i=0;i < s.length(); ++i) cout << s[i];
- Auto enumeration
Sorting with sort#
// sort(start address, end address + 1, *comparison function)
// Default comparison function is ascending
// Custom comparison function
bool cmp(const int &u, const int &v){
// Can also be written as int u, int v
return u > v;
}
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
// init v
vector<int> v = {5,1,3,9,11};
// Sort the array in descending order
sort(v.begin(), v.end(), cmp);
// Output
for(int i=0; i < v.size(); ++i){
cout << v[i] << ' ';
}
}
// Use lambda expression for custom comparison function
sort(v.begin(), v.end(), [](const int &u, const int &v)
{
return u > v;
});
// Struct custom comparison function
struct Node
{
int u, v;
bool operator < (const Node &m)const{
return u == m.u ? v < m.v : u < m.u;
}
}
// Tricks with spaces and newlines
for(int i = 1; i <=n; i++){
// Output in order
cout << a[i] << " \n"[i == n];
}
Finding Minimum and Maximum#
min(a, b);
min({1,2,3,4})=1;
max(a, b);
min_element(st, ed); // Returns the address of the smallest value
max_element(st, ed); //
// Example
vector<int> v = {5, 1, 3, 9, 11};
cout << *max_element(v.begin(), v.end()) << '\n';
ntn_element(st, k, ed); // Partial sorting
// k is in the correct position, smaller in front, larger behind
// https://www.lanqiao.cn/problems/497/learning/
Binary Search#
Can only search in monotonic arrays
// binary_search function
// Used to find a specific element in a sorted sequence (array or vector).
vector<int> numbers = {1, 3, 5, 7, 9};
int target = 5;
// Use binary_search to find the target
bool found = binary_search(numbers.begin(), numbers.end(), target);
lower_bound & upper_bound
// Premise: The array must be non-decreasing
// lower_bound(st, ed, x) returns the address of the first element greater than or equal to x in [st, ed).
// upper_bound(st, ed, x) returns the address of the first element greater than x in [st, ed).
// If it does not exist, it returns the position after the last element, which is end() in vector.
vector<int> v = {5, 1, 7, 3, 10, 18, 9};
sort(v.begin(), v.end());
for(auto &i : v) cout << i << ' ';
cout << '\n';
// Find the position of the first element greater than or equal to 8 in the array
cout << (lower_bound(v.begin(), v.end(), 8) - v.begin()) << '\n';
// https://www.lanqiao.cn/problems/1389/learning/
Case Conversion#
// islower/isupper function checks if char type is lowercase or uppercase
#include <cctype>
// tolower/toupper function
char ch1 = 'A';
char lowercaseCh1 = tolower(ch1);
Permutations#
next_permutation() function
vector<int> nums = {1, 2, 3};
cout << "Initial permutation: ";
for(int num : nums){
cout << num << " ";
}
cout << '\n';
// Generate the next permutation next_permutation returns true/false
while (next_permutation(nums.begin(), nums.end())){
cout << "Next permutation: ";
for(int num : nums){
cout << num << " ";
}
cout << endl;
}
prev_permutation() function
vector<int> nums = {3, 2, 1};
cout << "Initial permutation: ";
for(int num : nums){
cout << num << " ";
}
cout << '\n';
// Generate the previous permutation prev_permutation returns true/false
while (prev_permutation(nums.begin(), nums.end())){
cout << "Next permutation: ";
for(int num : nums){
cout << num << " ";
}
cout << endl;
}
Using search/DFS methods will utilize permutations.
Other Library Functions#
memset(void* ptr, int value, size_t num)#
Function to set memory block values #include <cstring>
void* memset(void* ptr, int value, size_t num)
ptr points to the memory block to set values
value is the value to set, usually an integer
num is the number of bytes to set
memset(arr, 0, sizeof(arr)); // Initialize an array arr
The memset() function may cause undefined behavior for non-character type arrays.
When dealing with non-character type arrays, it is better to use other methods in C++, such as looping through to initialize the array.
memset will set each byte to value.
int main(){
int a[5];
memset(a, 0, sizeof(a));
for(int i = 0; i < 5; i++){
// cout << bitset<32>(a[i]) << '\n';
cout << a[i] << '\n';
}
return 0;
}
swap(T &a, T &b)#
Swap
std::swap(a, b);
reverse(BidirIt first, BidirIt last)#
#include <algorithm>
template<class BidirIt>
void reverse(BidirIt first, BidirIt last);
Reverses [first, last)
reverse(vec.begin(), vec.end());
unique(ForwardIt first, ForwardIt last)#
#include <algorithm>
template<class ForwardIt>
ForwardIt unique(ForwardIt first, ForwardIt last)
int main(){
vector<int> vec = {1, 1, 2, 2, 3, 3, 3, 4, 4, 5};
auto it = unique(vec.begin(), vec.end()); // Remove adjacent duplicate elements
vec.erase(it, vec.end()); // Remove the duplicate elements
for(int num : vec) {
cout << num << " ";
}
cout << '\n';
return 0;
}
STL Library#
pair for Value#
pair(const T1& x, const T2& y);
// Represents a combination of a pair of values, combining two values for passing, storing, and operating
pair<int, double> p1(1, 3.14);
pair<char, string> p2('a', "Hello");
cout << p1.first << ", " << p1.second << endl;
Nesting of pairs:
Using a pair object as a member of another pair object
Pairs come with sorting rules, sorted in ascending order by the first member
vector<pair<int, int>> vec;
vec.push_back(make_pair(3, 2));
vec.push_back(make_pair(1, 4));
vec.push_back(make_pair(2, 1));
sort(vec.begin(), vec.end());
for (const auto& p : vec) {
cout << p.first << ", " << p.second << endl;
}
vector Dynamic Array#
Dynamic array container that stores a series of elements of the same type
#include <vector>
vector<T> vec;
// Element access: 0~size()-1
// Element addition and deletion: push_back() pop_back() insert() erase()
// Container size management: size() empty() resize()
// Iterators: begin() end()
vector<int> vec = {10, 20, 30};
for(auto it = vec.begin(); it != vec.end(); ++it){
cout << *it << " ";
}
sort(vec.begin(), vec.end());
// Sort and remove duplicates
vector<int> vec = {10, 20, 30};
sort(vec.begin(), vec.end());
auto last = unique(vec.begin(), vec.end());
vec.erase(last, vec.end());
for(const auto& num : vec){
cout << num << " ";
}
list#
Used very little
Doubly linked list
list<T>
stack#
Last In First Out (LIFO) data structure
#include <stack>
stack<T>
// Common functions
push(x) // Insert element x at the top of the stack
pop() // Pop the top element of the stack
top() // Return the top element of the stack
empty() // Check if the stack is empty
size() // Return the number of elements in the stack
// stack cannot be traversed
queue#
//queue
//priority_queue priority queue
//deque double-ended queue
//queue FIFO
push(x)
pop()
front()
back()
empty()
size()
https://www.lanqiao.cn/problems/1113/learning/
//priority_queue priority queue, default sorted from largest to smallest
1. push(): Inserts an element into the priority queue. It will automatically rearrange according to priority after insertion.
2. pop(): Pops the top element of the queue. This will remove the element with the highest priority from the queue.
3. top(): Returns the top element (i.e., the highest priority) of the queue, but does not remove it from the queue.
4. size(): Returns the number of elements in the queue.
5. empty(): Returns true if the queue is empty; otherwise, returns false.
struct Compare{
bool operator()(int a, int b) {
return a > b;
}
}
int main(){
priority_queue<int, vector<int>, Compare> pq;
}
// Or
// priority_queue<int, vector<int>, greater<int>> pq;
//deque double-ended queue
push_back(x)
push_front(x)
pop_back()
pop_front()
front()
back()
empty()
size()
clear()
set#
// set collection, default sorted in ascending order
// set internally uses a red-black tree to store elements
// set does not allow duplicate elements
insert()
erase()
find()
lower_bound()
upper_bound()
size()
empty()
clear()
// Change sorting method 1
set<int, greater<int>> mySet;
// 2
struct MyCompare(){
bool operator()(const int& a, const int& b) const {
// Custom comparison logic
return a > b;
}
}
int main(){
set<int, myCompare> mySet;
}
// multiset allows storing duplicate elements
// unordered_set unordered collection
map Key-Value Pair#
map()
// Sorted by key
insert(K, V)
erase(key)
find(key)
count(key)
// Multiple identical keys
multimap()
// Unordered
unordered_map()
Summary#
https://www.lanqiao.cn/problems/3226/learning/ Treasure Sorting 2
https://www.lanqiao.cn/problems/1624/learning/ Little Blue Eats Candy
https://www.lanqiao.cn/problems/2490/learning/ Little Blue's Parentheses String 1
https://www.lanqiao.cn/problems/1531/learning/ Express Sorting
Time Complexity#
Enumeration#
Exhaust all possible situations, loop through the solution space
Simulation#
Recursion#
Base Conversion#
Prefix Sum#
Difference#
The principle and characteristics of the difference
For an array a[]
, the definition of the difference array diff[]
is:
diff[i] = a[i] - a[i-1]
The prefix sum of the difference array can restore the original array:
diff[1] = a[1]
diff[2] = a[2] - a[1]
diff[3] = a[3] - a[2]
...
diff[n] = a[n] - a[n-1]
Implementation of the difference
Run an O(n) loop, it is recommended to set a[0]=0
, starting from index 1.