[Notes] Leetcode Codebooks

This is the notebook for Leetcode problems. The problems are categorized into different types, and tricks are summarized for each type so that they can be looked up quickly like in a toolbox. The primary language is C++ or rust, as I am practicing system programming.

Basic Data Structure

// traversal template
void traverse(TreeNode* root) {
	if (root == nullptr) return;
	// pre-order ...
	traverse(root->left);
	// in-order ...
	traverse(root->right);
	// post-order ...
}


// sub-problem template (divide and conquer)
int tree_max_depth(TreeNode* root) {
	if (root == nullptr) return 0;
	int left = tree_max_depth(root->left);
	int right = tree_max_depth(root->right);
	return max(left, right) + 1;
}
#include <queue>

// Max priority queue (popping the max in O(logN))
std::priority_queue<int> q1; 
for (int i = 0; i < 10; i++) q1.push(i);
while (!pq.empty()) {
    std::cout << pq.top() << ' ';
    pq.pop();
}

// Min priority queue
std::priority_queue<int, std::vector<int>, std::greater<int>> q2; 
std::priority_queue q3(data.begin(), data.end(), std::greater<int>());  

// Max PQ with custom object container
auto custom_comparator = [](const custom_obj& a, const custom_obj& b) {
	return a.val < b.val;
};
std::proirity_queue<obj, std::vector<obj>, decltype(custom_comparator)> q4;

Double Pointers

Linked List Double Pointers

struct ListNode {
	int val;
	ListNode* next;
	ListNode(int x) : val(x), next(nullptr) {}
};

ListNode* listMerger(ListNode* p1, ListNode* p2) {
	ListNode dummy(0);
	ListNode* tail = &dummy;
	while (p1 != nullptr && p2 != nullptr) {
		if (p1->val < p2->val) {
			tail->next = p1;
			p1 = p1->next; // move p1 forward
		} else {
			tail->next = p2;
			p2 = p2->next; // move p2 forward
		}
		tail = tail->next;
	}
	tail->next = p1 != nullptr ? p1 : p2;
	return dummy.next;
}

void FindCycleStartPoint(LinkedList* head) {
	LinkedList* slow = head;
	LinkedList* fast = head;
	while (fast != nullptr && fast->next != nullptr) {
		slow = slow->next;
		fast = fast->next->next;
		if (slow == fast) break;
	}
	if (fast == nullptr || fast->next == nullptr) return nullptr; // no cycle

	// find the start point of the cycle. assume distance between start and meeting point is m
	// it only takes another (k-m) steps for the slow pointer to reach the start point
	slow = head;
	while (slow != fast) {
		slow = slow->next;
		fast = fast->next;
	}
	return slow;
}

Array Double Pointers


void removeDuplicates(vector<int>& nums) {
	if (nums.empty()) return 0;
	int slow = 0;
	while (fast < nums.size()) {
		fast++;
		if (nums[fast] != nums[slow]) {
			slow++;
			nums[slow] = nums[fast];
		}
	}
	return slow + 1;
}
// pointers from middle to both ends
string PalindromeAt(string s, int left, int right) {
	while (left >= 0 && right < s.size() && s[left] == s[right]) {
		left--;
		right++;
	}
	return s.substr(left + 1, right - left - 1);
}

// Scan palindromes from start to end
string longestPalindrome(string s) {
	if (s.empty()) return "";
	string res = s.substr(0, 1);
	for (int i = 0; i < s.size() - 1; i++) {
		string p1 = PalindromeAt(s, i, i);
		string p2 = PalindromeAt(s, i, i + 1);
		if (p1.size() > res.size()) res = p1;
		if (p2.size() > res.size()) res = p2;
	}
	return res;
}

C++ Basics

// NB: typedef a template not allowed: https://stackoverflow.com/a/2448307
template <typename T> // only class can be used as typename
struct array { 
  size_t x; 
  T *ary; 
};