Solve many problems in C++
This commit is contained in:
parent
eaa8414c67
commit
b438dd5395
46
cpp/101.cpp
Normal file
46
cpp/101.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
// https://leetcode.com/problems/symmetric-tree/submissions/1292981419/
|
||||
|
||||
/**
|
||||
* Definition for a binary tree node.
|
||||
*/
|
||||
struct TreeNode {
|
||||
int val;
|
||||
TreeNode *left;
|
||||
TreeNode *right;
|
||||
TreeNode() : val(0), left(nullptr), right(nullptr) {}
|
||||
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
|
||||
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method:
|
||||
* - Reverse the right-hand side
|
||||
* - Check whether the left and right are now equal via a pre-order traversal.
|
||||
* - Time: O(n)
|
||||
* - Space: O(n).
|
||||
*
|
||||
* On my first time, I didn't see that the problem could be solved directly by comparing the trees recursively;
|
||||
* doing this would still be O(n) time and space, but avoid having to invert the right tree for no other reason.
|
||||
*/
|
||||
class Solution {
|
||||
public:
|
||||
bool isSymmetric(TreeNode* root) {
|
||||
reverseBinaryTree(root->right);
|
||||
return treesAreEqual(root->left, root->right);
|
||||
}
|
||||
|
||||
void reverseBinaryTree(TreeNode* root) {
|
||||
if (root == nullptr) return;
|
||||
TreeNode* temp = root->left;
|
||||
root->left = root->right;
|
||||
root->right = temp;
|
||||
reverseBinaryTree(root->left);
|
||||
reverseBinaryTree(root->right);
|
||||
}
|
||||
|
||||
bool treesAreEqual(TreeNode* left, TreeNode* right) {
|
||||
if (left == nullptr) return right == nullptr;
|
||||
if (right == nullptr) return left == nullptr;
|
||||
return (left->val != right->val) && treesAreEqual(left->left, right->left) && treesAreEqual(left->right, right->right);
|
||||
}
|
||||
};
|
26
cpp/110.cpp
Normal file
26
cpp/110.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
// https://leetcode.com/problems/balanced-binary-tree/submissions/1292988627/
|
||||
/**
|
||||
* Definition for a binary tree node.
|
||||
*/
|
||||
#include <algorithm>
|
||||
struct TreeNode {
|
||||
int val;
|
||||
TreeNode *left;
|
||||
TreeNode *right;
|
||||
TreeNode() : val(0), left(nullptr), right(nullptr) {}
|
||||
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
|
||||
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
|
||||
};
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
bool isBalanced(TreeNode* root) {
|
||||
if (root == nullptr) return true;
|
||||
return std::abs(height(root->left) - height(root->right)) < 2 && isBalanced(root->left) && isBalanced(root->right);
|
||||
}
|
||||
|
||||
int height(TreeNode* root) {
|
||||
if (root == nullptr) return 0;
|
||||
return (root->val = 1 + std::max(height(root->left), height(root->right)));
|
||||
}
|
||||
};
|
35
cpp/111.cpp
Normal file
35
cpp/111.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
// https://leetcode.com/problems/minimum-depth-of-binary-tree/
|
||||
|
||||
/**
|
||||
* Definition for a binary tree node.
|
||||
*/
|
||||
struct TreeNode {
|
||||
int val;
|
||||
TreeNode *left;
|
||||
TreeNode *right;
|
||||
TreeNode() : val(0), left(nullptr), right(nullptr) {}
|
||||
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
|
||||
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
|
||||
};
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
int min = 100001;
|
||||
public:
|
||||
int minDepth(TreeNode* root) {
|
||||
if (root == nullptr) return 0;
|
||||
return minDepth(root, 1);
|
||||
}
|
||||
int minDepth(TreeNode* root, int current) {
|
||||
if (root == nullptr) {
|
||||
return min;
|
||||
} else {
|
||||
if (root->left == nullptr && root->right == nullptr && current < min) {
|
||||
min = current;
|
||||
}
|
||||
minDepth(root->left, current + 1);
|
||||
minDepth(root->right, current + 1);
|
||||
}
|
||||
return min;
|
||||
}
|
||||
};
|
32
cpp/141a.cpp
Normal file
32
cpp/141a.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
// https://leetcode.com/problems/linked-list-cycle/
|
||||
// This is my intial, unthoughtful solution.
|
||||
// Looking at the answers, it would turn out there's a much better method, involving two pointers, which didn't occur to me when I was originally trying to solve it.
|
||||
// It seemed impossible to me to "remember" whether we've "seen" a specific node before so as to tell whether a cycle has occurred - the type of reasoning being used in this solution -
|
||||
// but such reasoning is unnecessary under the other method. Please see 141b for that implementation.
|
||||
|
||||
/**
|
||||
* Definition for singly-linked list.
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <unordered_set>
|
||||
struct ListNode {
|
||||
int val;
|
||||
ListNode *next;
|
||||
ListNode(int x) : val(x), next(NULL) {}
|
||||
};
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
bool hasCycle(ListNode *head) {
|
||||
std::unordered_set<ListNode*> seen;
|
||||
ListNode* current = head;
|
||||
while (current) {
|
||||
if (seen.count(current)) {
|
||||
return true;
|
||||
}
|
||||
seen.insert(current);
|
||||
current = current->next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
33
cpp/141b.cpp
Normal file
33
cpp/141b.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
// https://leetcode.com/problems/linked-list-cycle/
|
||||
/**
|
||||
* Definition for singly-linked list.
|
||||
*/
|
||||
#include <cstddef>
|
||||
struct ListNode {
|
||||
int val;
|
||||
ListNode *next;
|
||||
ListNode(int x) : val(x), next(NULL) {}
|
||||
};
|
||||
|
||||
// Reasoning:
|
||||
// If we use two pointers, one that moves twice as fast as the other, then the faster one will
|
||||
// eventually lap the slower one if there's a cycle, as it will go all the way back and catch up to it again.
|
||||
// In this case, the pointers will eventually become equal, and we can return true, that there is a cycle;
|
||||
// otherwise, the faster pointer will simply reach the end of the list, so either it or its successor will be null;
|
||||
// in this case, there must not be a cycle, as it has simply reached the end.
|
||||
// This begs the question whether this can be done in "O(1)" time by just iterating 10^4 times (as specified as the upper limit of the list's length in the problem).
|
||||
class Solution {
|
||||
public:
|
||||
bool hasCycle(ListNode *head) {
|
||||
ListNode* slow = head;
|
||||
ListNode* fast = head;
|
||||
while (fast && fast->next) {
|
||||
fast = fast->next->next;
|
||||
slow = slow->next;
|
||||
if (fast == slow) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
29
cpp/141c.cpp
Normal file
29
cpp/141c.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
// https://leetcode.com/problems/linked-list-cycle/
|
||||
/**
|
||||
* Definition for singly-linked list.
|
||||
*/
|
||||
#include <cstddef>
|
||||
struct ListNode {
|
||||
int val;
|
||||
ListNode *next;
|
||||
ListNode(int x) : val(x), next(NULL) {}
|
||||
};
|
||||
|
||||
// Pursuing the cheeky logic from last time, indeed, we can run the loop 10001 times,
|
||||
// and if the pointer still isn't at the end, we know it must be stuck in a loop
|
||||
// (since the longest possible list is only 10000).
|
||||
// This actually performs surprisingly well on the leaderboard, despite being totally, totally
|
||||
// overkill for almost all the cases :)
|
||||
class Solution {
|
||||
public:
|
||||
bool hasCycle(ListNode *head) {
|
||||
ListNode* ptr = head;
|
||||
for (int i = 0; i < 10001; i++) {
|
||||
if (ptr == nullptr) {
|
||||
return false;
|
||||
}
|
||||
ptr = ptr->next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
26
cpp/145a.cpp
Normal file
26
cpp/145a.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Definition for a binary tree node.
|
||||
*/
|
||||
#include <vector>
|
||||
struct TreeNode {
|
||||
int val;
|
||||
TreeNode *left;
|
||||
TreeNode *right;
|
||||
TreeNode() : val(0), left(nullptr), right(nullptr) {}
|
||||
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
|
||||
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
|
||||
};
|
||||
|
||||
class Solution {
|
||||
private:
|
||||
std::vector<int> traversal;
|
||||
public:
|
||||
std::vector<int> postorderTraversal(TreeNode* root) {
|
||||
if (root != nullptr) {
|
||||
postorderTraversal(root->left);
|
||||
postorderTraversal(root->right);
|
||||
traversal.push_back(root->val);
|
||||
}
|
||||
return traversal;
|
||||
}
|
||||
};
|
20
cpp/145b (WIP).cpp
Normal file
20
cpp/145b (WIP).cpp
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Definition for a binary tree node.
|
||||
*/
|
||||
#include <vector>
|
||||
struct TreeNode {
|
||||
int val;
|
||||
TreeNode *left;
|
||||
TreeNode *right;
|
||||
TreeNode() : val(0), left(nullptr), right(nullptr) {}
|
||||
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
|
||||
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
|
||||
};
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
// TODO: Make this iterative instead of recursive.
|
||||
std::vector<int> postorderTraversal(TreeNode* root) {
|
||||
//TODO
|
||||
}
|
||||
};
|
28
cpp/160a.cpp
Normal file
28
cpp/160a.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Definition for singly-linked list.
|
||||
*/
|
||||
#include <cstddef>
|
||||
struct ListNode {
|
||||
int val;
|
||||
ListNode *next;
|
||||
ListNode(int x) : val(x), next(NULL) {}
|
||||
};
|
||||
|
||||
// This solution is not great, being O(n^2)-ish time, although it is O(1) space, which is good.
|
||||
// There is likely at least an O(n) in both solution...
|
||||
class Solution {
|
||||
public:
|
||||
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
|
||||
while (headA) {
|
||||
ListNode* check = headB;
|
||||
while (check) {
|
||||
if (check == headA) {
|
||||
return headA;
|
||||
}
|
||||
check = check->next;
|
||||
}
|
||||
headA = headA->next;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
};
|
44
cpp/160b.cpp
Normal file
44
cpp/160b.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Definition for singly-linked list.
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
struct ListNode {
|
||||
int val;
|
||||
ListNode *next;
|
||||
ListNode(int x) : val(x), next(NULL) {}
|
||||
};
|
||||
|
||||
// This solution is now O(n) time and O(n) space.
|
||||
// The method is to copy the linked list nodes into two vectors;
|
||||
// then, starting from the back, if the elements are not equal from the very end,
|
||||
// the lists don't intersect ever.
|
||||
// Otherwise, iterating from the back, find the first node that isn't shared between the lists,
|
||||
// and then return the node just after that (which is shared by both).
|
||||
// If we get all the way to the beginning, then the first node of the lists must be the shared one.
|
||||
class Solution {
|
||||
public:
|
||||
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
|
||||
std::vector<ListNode*> listA;
|
||||
std::vector<ListNode*> listB;
|
||||
for (ListNode* start = headA; start != nullptr; start = start->next) {
|
||||
listA.push_back(start);
|
||||
}
|
||||
for (ListNode* start = headB; start != nullptr; start = start->next) {
|
||||
listB.push_back(start);
|
||||
}
|
||||
int endA = listA.size() - 1;
|
||||
int endB = listB.size() - 1;
|
||||
if (listA.at(endA) != listB.at(endB)) {
|
||||
return nullptr;
|
||||
}
|
||||
while (endA >= 0 && endB >= 0) {
|
||||
if (listA.at(endA) != listB.at(endB)) {
|
||||
return listA.at(endA + 1);
|
||||
}
|
||||
endA--;
|
||||
endB--;
|
||||
}
|
||||
return listA.at(endA + 1);
|
||||
}
|
||||
};
|
35
cpp/160c.cpp
Normal file
35
cpp/160c.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Definition for singly-linked list.
|
||||
*/
|
||||
#include <cstddef>
|
||||
struct ListNode {
|
||||
int val;
|
||||
ListNode *next;
|
||||
ListNode(int x) : val(x), next(NULL) {}
|
||||
};
|
||||
|
||||
// I couldn't figure this solution out on my own, so I looked it up on YouTube.
|
||||
// This is my implementation after seeing the method.
|
||||
// The idea is to use two pointers, and advance both forwards; if the end is reached by either,
|
||||
// swap that pointer to the beginning of the opposite list.
|
||||
// Once both pointers have moved all the way to the end, they will be in line with each other;
|
||||
// by this token, some time before they even reach the end, they will reach their common intersection point,
|
||||
// and be equal to each other.
|
||||
//
|
||||
// Even if they don't intersect, they will still end up equal to each other, both as null pointers.
|
||||
//
|
||||
// P.S. for reasons unknown, solution B that I wrote seems to consistently work faster,
|
||||
// despite being asymptotically slower; and it doesn't even have simpler operations, either.
|
||||
// I don't know what the cause could be, but...
|
||||
class Solution {
|
||||
public:
|
||||
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
|
||||
ListNode* a = headA;
|
||||
ListNode* b = headB;
|
||||
while (a != b) {
|
||||
a = a == nullptr ? headB : a->next;
|
||||
b = b == nullptr ? headA : b->next;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
};
|
38
cpp/168.cpp
Normal file
38
cpp/168.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
class Solution {
|
||||
private:
|
||||
std::array<char, 26> alphabet = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
|
||||
public:
|
||||
std::string convertToTitle(int columnNumber) {
|
||||
long power = 1;
|
||||
short length = 0;
|
||||
while (columnNumber >= power) {
|
||||
columnNumber -= power;
|
||||
power *= 26;
|
||||
length++;
|
||||
}
|
||||
|
||||
std::string out;
|
||||
for (; length > 0; length--) {
|
||||
int remainder = columnNumber % 26;
|
||||
columnNumber = columnNumber / 26;
|
||||
char corresponding_char = alphabet.at(remainder);
|
||||
out.push_back(corresponding_char);
|
||||
}
|
||||
|
||||
std::reverse(out.begin(), out.end());
|
||||
return out;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
int main() {
|
||||
Solution sol;
|
||||
for (int i = 1; i < 26*10; i++) {
|
||||
std::cout << i << " -> " << sol.convertToTitle(i) << '\n';
|
||||
}
|
||||
}
|
18
cpp/171.cpp
Normal file
18
cpp/171.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
#include <string>
|
||||
class Solution {
|
||||
private:
|
||||
constexpr int numericValue(char c) {
|
||||
return (int) (c-'A');
|
||||
}
|
||||
public:
|
||||
int titleToNumber(std::string columnTitle) {
|
||||
int value = 0;
|
||||
int length = columnTitle.length();
|
||||
for (long power = 1, i = length-1; i >= 0; power *= 26, i--) {
|
||||
// value += power;
|
||||
// value += power * numericValue(columnTitle.at(i));
|
||||
value += power * (1 + numericValue(columnTitle.at(i)));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
};
|
25
cpp/190.cpp
Normal file
25
cpp/190.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include <cstdint>
|
||||
// #include <iostream>
|
||||
class Solution {
|
||||
private:
|
||||
uint32_t setBit(uint32_t in, char value, char pos) {
|
||||
uint32_t ones = -1;
|
||||
uint32_t zero_mask = (ones ^ (value << pos));
|
||||
in = in & zero_mask;
|
||||
in = in ^ (value << pos);
|
||||
return in;
|
||||
}
|
||||
public:
|
||||
uint32_t reverseBits(uint32_t n) {
|
||||
uint32_t out = 0;
|
||||
for (char i = 0; i < 32; i++) {
|
||||
out = setBit(out, n & 1, 31-i);
|
||||
n >>= 1;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
// int main() {
|
||||
// std::cout << setBit(8, 1, 3) << std::endl;
|
||||
// }
|
84
cpp/65.cpp
Normal file
84
cpp/65.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
class Solution {
|
||||
private:
|
||||
int i = 0;
|
||||
std::string s;
|
||||
std::vector<char> digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
|
||||
|
||||
bool atEnd() {
|
||||
return this->i == s.length();
|
||||
}
|
||||
|
||||
bool test(char c) {
|
||||
if (atEnd()) {
|
||||
return false;
|
||||
}
|
||||
return s.at(i) == c;
|
||||
}
|
||||
bool test(std::vector<char> chars) {
|
||||
for (char c : chars) {
|
||||
if (test(c)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool match(char c) {
|
||||
if (test(c)) {
|
||||
i++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool match(std::vector<char> chars) {
|
||||
if (test(chars)) {
|
||||
i++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool many(std::vector<char> chars) {
|
||||
bool matched = false;
|
||||
while (match(chars)) {
|
||||
matched = true;
|
||||
}
|
||||
return matched;
|
||||
}
|
||||
bool digitString() {
|
||||
return many(digits);
|
||||
}
|
||||
|
||||
bool integer() {
|
||||
match({'+', '-'});
|
||||
return digitString();
|
||||
}
|
||||
|
||||
bool decimal() {
|
||||
if (!integer()) {
|
||||
return match('.') && digitString();
|
||||
} else {
|
||||
match('.');
|
||||
digitString();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool exponent() {
|
||||
if (match({'e', 'E'})) {
|
||||
return integer();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool number() {
|
||||
bool success = decimal();
|
||||
return success && exponent();
|
||||
}
|
||||
|
||||
public:
|
||||
bool isNumber(std::string s) {
|
||||
this->s = s;
|
||||
return number() && this->atEnd();
|
||||
}
|
||||
};
|
34
cpp/83.cpp
Normal file
34
cpp/83.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
// https://leetcode.com/problems/remove-duplicates-from-sorted-list/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
struct ListNode {
|
||||
int val;
|
||||
ListNode *next;
|
||||
ListNode() : val(0), next(nullptr) {}
|
||||
ListNode(int x) : val(x), next(nullptr) {}
|
||||
ListNode(int x, ListNode *next) : val(x), next(next) {}
|
||||
};
|
||||
|
||||
class Solution {
|
||||
public:
|
||||
ListNode* deleteDuplicates(ListNode* head) {
|
||||
if (head == nullptr)
|
||||
return head;
|
||||
bool newSequence = false;
|
||||
int currentVal = head->val;
|
||||
ListNode* front = head->next;
|
||||
ListNode* rear = head;
|
||||
while (front != nullptr) {
|
||||
if (front->val != currentVal) {
|
||||
std::cout << "Previous value: " << currentVal << "; current value: " << front->val << '\n';
|
||||
rear->next = front;
|
||||
currentVal = front->val;
|
||||
rear = front;
|
||||
}
|
||||
front = front->next;
|
||||
}
|
||||
rear->next = nullptr;
|
||||
return head;
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user