跳至主要内容

268 篇文章 含有標籤「leetcode」

檢視所有標籤

102. Binary Tree Level Order Traversal

· 閱讀時間約 2 分鐘

Recursion

/*
* @lc app=leetcode id=102 lang=cpp
*
* [102] Binary Tree Level Order Traversal
*
* https://leetcode.com/problems/binary-tree-level-order-traversal/description/
*
* algorithms
* Medium (68.36%)
* Likes: 15464
* Dislikes: 320
* Total Accepted: 2.4M
* Total Submissions: 3.5M
* Testcase Example: '[3,9,20,null,null,15,7]'
*
* Given the root of a binary tree, return the level order traversal of its
* nodes' values. (i.e., from left to right, level by level).
*
*
* Example 1:
*
*
* Input: root = [3,9,20,null,null,15,7]
* Output: [[3],[9,20],[15,7]]
*
*
* Example 2:
*
*
* Input: root = [1]
* Output: [[1]]
*
*
* Example 3:
*
*
* Input: root = []
* Output: []
*
*
*
* Constraints:
*
*
* The number of nodes in the tree is in the range [0, 2000].
* -1000 <= Node.val <= 1000
*
*
*/

// @lc code=start
/**
* 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:
vector<vector<int>> res;
public:
vector<vector<int>> levelOrder(TreeNode* root) {
if (!root) return res;
dfs(root, 0);
return res;
}
void dfs(TreeNode* root, int level) {
if (res.size() == level) res.emplace_back(vector<int>{});
res[level].emplace_back(root->val);
if (root->left) {
dfs(root->left, level + 1);
}
if (root->right) {
dfs(root->right, level + 1);
}
}
};
// @lc code=end
  • T: $O(N)$
  • S: $O(N)$

Iteration

/**
* 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 {
public:
vector<vector<int>> levelOrder(TreeNode* root)
{
vector<vector<int>> res;
queue<TreeNode*> q{{root}};
while (!q.empty()) {
vector<int> nodesWithinLevel;
int qSize = q.size();
for (int i = 0; i < qSize; i++) {
TreeNode* node = q.front(); q.pop();
if (!node) continue;
nodesWithinLevel.push_back(node->val);
q.push(node->left);
q.push(node->right);
}
if (!nodesWithinLevel.empty()) res.push_back(nodesWithinLevel);
}
return res;
}
};
  • T: $O(N)$
  • S: $O(N)$

101. Symmetric Tree

· 閱讀時間約 2 分鐘

Recursion

/*
* @lc app=leetcode id=101 lang=cpp
*
* [101] Symmetric Tree
*
* https://leetcode.com/problems/symmetric-tree/description/
*
* algorithms
* Easy (57.89%)
* Likes: 15947
* Dislikes: 410
* Total Accepted: 2.4M
* Total Submissions: 4M
* Testcase Example: '[1,2,2,3,4,4,3]'
*
* Given the root of a binary tree, check whether it is a mirror of itself
* (i.e., symmetric around its center).
*
*
* Example 1:
*
*
* Input: root = [1,2,2,3,4,4,3]
* Output: true
*
*
* Example 2:
*
*
* Input: root = [1,2,2,null,3,null,3]
* Output: false
*
*
*
* Constraints:
*
*
* The number of nodes in the tree is in the range [1, 1000].
* -100 <= Node.val <= 100
*
*
*
* Follow up: Could you solve it both recursively and iteratively?
*/

// @lc code=start
/**
* 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 {
public:
bool isSymmetric(TreeNode* root) {
return isSame(root, root);
}
bool isSame(TreeNode* p, TreeNode* q) {
if (!p && !q) return true;
if (!p || !q) return false;
if (p->val != q->val) return false;
return isSame(p->left, q->right) && isSame(p->right, q->left);
}
};
// @lc code=end
  • T: $O(N)$
  • S: $O(N)$

iteration

class Solution {
public:
bool isSymmetric(TreeNode* root) {
queue<TreeNode*> q;
q.push(root);
q.push(root);
while (!q.empty()) {
TreeNode* t1 = q.front(); q.pop();
TreeNode* t2 = q.front(); q.pop();
if (!t1 && !t2) continue;
if (!t1 || !t2) return false;
if (t1->val != t2->val) return false;
q.push(t1->left);
q.push(t2->right);
q.push(t1->right);
q.push(t2->left);
}
return true;
}
};
  • T: $O(N)$
  • S: $O(N)$

100. Same Tree

· 閱讀時間約 2 分鐘

Recursion

/*
* @lc app=leetcode id=100 lang=cpp
*
* [100] Same Tree
*
* https://leetcode.com/problems/same-tree/description/
*
* algorithms
* Easy (63.69%)
* Likes: 12070
* Dislikes: 262
* Total Accepted: 2.7M
* Total Submissions: 4.2M
* Testcase Example: '[1,2,3]\n[1,2,3]'
*
* Given the roots of two binary trees p and q, write a function to check if
* they are the same or not.
*
* Two binary trees are considered the same if they are structurally identical,
* and the nodes have the same value.
*
*
* Example 1:
*
*
* Input: p = [1,2,3], q = [1,2,3]
* Output: true
*
*
* Example 2:
*
*
* Input: p = [1,2], q = [1,null,2]
* Output: false
*
*
* Example 3:
*
*
* Input: p = [1,2,1], q = [1,1,2]
* Output: false
*
*
*
* Constraints:
*
*
* The number of nodes in both trees is in the range [0, 100].
* -10^4 <= Node.val <= 10^4
*
*
*/

// @lc code=start
/**
* 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 {
public:
bool isSameTree(TreeNode* p, TreeNode* q) {
if (!p && !q) return true;
if (!p || !q) return false;
if (p->val != q->val) {
return false;
}
return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}
};
// @lc code=end
  • T: $O(N)$
  • S: $O(N)$

Iteration

/**
* 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 {
public:
bool isSameTree(TreeNode* p, TreeNode* q)
{
queue<TreeNode*> q1, q2;
q1.push(p); q2.push(q);
while (!q1.empty()) {
p = q1.front(); q1.pop();
q = q2.front(); q2.pop();

if (!p && !q) continue;

if (!isSame(p, q)) return false;
if (!isSame(p->left, q->left)) return false;
if (!isSame(p->right, q->right)) return false;

if (p->left)
{
q1.push(p->left);
q2.push(q->left);
}

if (p->right)
{
q1.push(p->right);
q2.push(q->right);
}
}
return true;
}
bool isSame(TreeNode* p, TreeNode* q)
{
if (!p && !q) return true;
if (!p || !q) return false;
return p->val == q->val;
}
};
  • T: $O(N)$
  • S: $O(N)$

98. Validate Binary Search Tree

· 閱讀時間約 2 分鐘

Recursion

/*
* @lc app=leetcode id=98 lang=cpp
*
* [98] Validate Binary Search Tree
*
* https://leetcode.com/problems/validate-binary-search-tree/description/
*
* algorithms
* Medium (33.60%)
* Likes: 17453
* Dislikes: 1402
* Total Accepted: 2.8M
* Total Submissions: 8.1M
* Testcase Example: '[2,1,3]'
*
* Given the root of a binary tree, determine if it is a valid binary search
* tree (BST).
*
* A valid BST is defined as follows:
*
*
* The left subtree of a node contains only nodes with keys less than the
* node's key.
* The right subtree of a node contains only nodes with keys greater than the
* node's key.
* Both the left and right subtrees must also be binary search trees.
*
*
*
* Example 1:
*
*
* Input: root = [2,1,3]
* Output: true
*
*
* Example 2:
*
*
* Input: root = [5,1,4,null,null,3,6]
* Output: false
* Explanation: The root node's value is 5 but its right child's value is
* 4.
*
*
*
* Constraints:
*
*
* The number of nodes in the tree is in the range [1, 10^4].
* -2^31 <= Node.val <= 2^31 - 1
*
*
*/

// @lc code=start
/**
* 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 {
public:
bool isValidBST(TreeNode* root) {
return isValid(root, nullptr, nullptr);
}
bool isValid(TreeNode* root, TreeNode* left, TreeNode* right) {
if(!root) return true;

if((left && left->val >= root->val) || right && root->val >= right->val)
return false;

return isValid(root->left, left, root) && isValid(root->right, root, right);
}
};
// @lc code=end
  • T: $O(N)$
  • S: $O(N)$

94. Binary Tree Inorder Traversal

· 閱讀時間約 2 分鐘

Recursion

/*
* @lc app=leetcode id=94 lang=cpp
*
* [94] Binary Tree Inorder Traversal
*
* https://leetcode.com/problems/binary-tree-inorder-traversal/description/
*
* algorithms
* Easy (77.38%)
* Likes: 13994
* Dislikes: 833
* Total Accepted: 3M
* Total Submissions: 3.9M
* Testcase Example: '[1,null,2,3]'
*
* Given the root of a binary tree, return the inorder traversal of its nodes'
* values.
*
*
* Example 1:
*
*
* Input: root = [1,null,2,3]
*
* Output: [1,3,2]
*
* Explanation:
*
*
*
*
* Example 2:
*
*
* Input: root = [1,2,3,4,5,null,8,null,null,6,7,9]
*
* Output: [4,2,6,5,7,1,3,9,8]
*
* Explanation:
*
*
*
*
* Example 3:
*
*
* Input: root = []
*
* Output: []
*
*
* Example 4:
*
*
* Input: root = [1]
*
* Output: [1]
*
*
*
* Constraints:
*
*
* The number of nodes in the tree is in the range [0, 100].
* -100 <= Node.val <= 100
*
*
*
* Follow up: Recursive solution is trivial, could you do it iteratively?
*/

// @lc code=start
/**
* 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:
vector<int> res;
public:
vector<int> inorderTraversal(TreeNode* root) {
dfs(root);
return res;
}
void dfs(TreeNode* node) {
if (!node) return;
dfs(node->left);
res.emplace_back(node->val);
dfs(node->right);
}
};
// @lc code=end
  • T: $O(N)$
  • S: $O(N)$

Iteration

class Solution {
private:
vector<int> res;
public:
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*> stk;
vector<int> res;
TreeNode* node = root;
while (node || !stk.empty()) {
while (node) {
stk.push(node);
node = node->left;
}
node = stk.top(); stk.pop();
res.emplace_back(node->val);
node = node->right;
}
return res;
}
};
  • T: $O(N)$
  • S: $O(N)$

92. Reverse Linked List II

· 閱讀時間約 2 分鐘
  • Iteration
/**
* Definition for singly-linked list.
* 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* reverseBetween(ListNode* head, int left, int right)
{
// 建立一個 dummy node
// 並使用一個指標 prev 指向 dummy
ListNode* dummy = new ListNode(-1);
ListNode* prev = dummy;

// dummy->next 接上 head
dummy->next = head;

// 移動 prev 到 left 節點的前一個節點
for (int i = 0; i < left - 1; ++i)
{
prev = prev->next;
}

// cur 指向 left 節點
ListNode* cur = prev->next;

// 開始反轉 left 到 right 節點之間的鏈結
// 以 1 -> 2 -> 3 -> 4 -> 5 為範例
// left 為 2, right 為 4
// 此時,prev 指標指向 1
// cur 指標指向 2
// node 指標指向 3

for (int i = left; i < right; ++i)
{
// 取得 cur 節點的下一個節點 node
ListNode* node = cur->next;

// 將 cur 的 next 指向 node 的下一個節點
// 也就是將 2 的下一個指向 4
cur->next = node->next;

// 將 node 插入到 prev 的後面
// 將 3 的下一個指向 2
node->next = prev->next;

// 更新 prev 的 next 為 node
// 將 1 的下一個指向 3
// 第 1 次迴圈結束會得到 1 -> 3 -> 2 -> 4 -> 5
// 第 2 次迴圈結束會得到 1 -> 4 -> 3 -> 2 -> 5
prev->next = node;
}
// 此時的 linked list 為 dummy -> 1 -> 4 -> 3 -> 2 -> 5
// 也就是回傳 dummy->next
return dummy->next;
}
};
  • T: $O(N)$
  • S: $O(1)$

91. Decode Ways

· 閱讀時間約 2 分鐘
/*
* @lc app=leetcode id=91 lang=cpp
*
* [91] Decode Ways
*
* https://leetcode.com/problems/decode-ways/description/
*
* algorithms
* Medium (35.67%)
* Likes: 12172
* Dislikes: 4551
* Total Accepted: 1.4M
* Total Submissions: 3.8M
* Testcase Example: '"12"'
*
* You have intercepted a secret message encoded as a string of numbers. The
* message is decoded via the following mapping:
*
* "1" -> 'A'
* "2" -> 'B'
* ...
* "25" -> 'Y'
* "26" -> 'Z'
*
* However, while decoding the message, you realize that there are many
* different ways you can decode the message because some codes are contained
* in other codes ("2" and "5" vs "25").
*
* For example, "11106" can be decoded into:
*
*
* "AAJF" with the grouping (1, 1, 10, 6)
* "KJF" with the grouping (11, 10, 6)
* The grouping (1, 11, 06) is invalid because "06" is not a valid code (only
* "6" is valid).
*
*
* Note: there may be strings that are impossible to decode.
*
* Given a string s containing only digits, return the number of ways to decode
* it. If the entire string cannot be decoded in any valid way, return 0.
*
* The test cases are generated so that the answer fits in a 32-bit integer.
*
*
* Example 1:
*
*
* Input: s = "12"
*
* Output: 2
*
* Explanation:
*
* "12" could be decoded as "AB" (1 2) or "L" (12).
*
*
* Example 2:
*
*
* Input: s = "226"
*
* Output: 3
*
* Explanation:
*
* "226" could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 6).
*
*
* Example 3:
*
*
* Input: s = "06"
*
* Output: 0
*
* Explanation:
*
* "06" cannot be mapped to "F" because of the leading zero ("6" is different
* from "06"). In this case, the string is not a valid encoding, so return
* 0.
*
*
*
* Constraints:
*
*
* 1 <= s.length <= 100
* s contains only digits and may contain leading zero(s).
*
*
*/

// @lc code=start
class Solution {
public:
int numDecodings(string s) {
int n = s.size();
vector<int> dp(n + 1);

dp[0] = 1;
dp[1] = (s[0] == '0' ? 0 : 1);

for (int i = 2; i <= n; i++) {
if (s[i - 1] != '0') {
dp[i] = dp[i - 1];
}

int twoDigits = stoi(s.substr(i - 2, 2));

if (10 <= twoDigits && twoDigits <= 26) {
dp[i] += dp[i - 2];
}
}
return dp[n];
}
};
// @lc code=end
  • T: $O(N)$
  • S: $O(N)$

88. Merge Sorted Array

· 閱讀時間約 3 分鐘

Sort

/*
* @lc app=leetcode id=88 lang=cpp
*
* [88] Merge Sorted Array
*
* https://leetcode.com/problems/merge-sorted-array/description/
*
* algorithms
* Easy (51.43%)
* Likes: 17089
* Dislikes: 2375
* Total Accepted: 4.6M
* Total Submissions: 8.8M
* Testcase Example: '[1,2,3,0,0,0]\n3\n[2,5,6]\n3'
*
* You are given two integer arrays nums1 and nums2, sorted in non-decreasing
* order, and two integers m and n, representing the number of elements in
* nums1 and nums2 respectively.
*
* Merge nums1 and nums2 into a single array sorted in non-decreasing order.
*
* The final sorted array should not be returned by the function, but instead
* be stored inside the array nums1. To accommodate this, nums1 has a length of
* m + n, where the first m elements denote the elements that should be merged,
* and the last n elements are set to 0 and should be ignored. nums2 has a
* length of n.
*
*
* Example 1:
*
*
* Input: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
* Output: [1,2,2,3,5,6]
* Explanation: The arrays we are merging are [1,2,3] and [2,5,6].
* The result of the merge is [1,2,2,3,5,6] with the underlined elements coming
* from nums1.
*
*
* Example 2:
*
*
* Input: nums1 = [1], m = 1, nums2 = [], n = 0
* Output: [1]
* Explanation: The arrays we are merging are [1] and [].
* The result of the merge is [1].
*
*
* Example 3:
*
*
* Input: nums1 = [0], m = 0, nums2 = [1], n = 1
* Output: [1]
* Explanation: The arrays we are merging are [] and [1].
* The result of the merge is [1].
* Note that because m = 0, there are no elements in nums1. The 0 is only there
* to ensure the merge result can fit in nums1.
*
*
*
* Constraints:
*
*
* nums1.length == m + n
* nums2.length == n
* 0 <= m, n <= 200
* 1 <= m + n <= 200
* -10^9 <= nums1[i], nums2[j] <= 10^9
*
*
*
* Follow up: Can you come up with an algorithm that runs in O(m + n) time?
*
*/

// @lc code=start
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
for (int i = 0; i < n; ++i) {
nums1[m + i] = nums2[i];
}
sort(nums1.begin(), nums1.end());
}
};
// @lc code=end
  • T: $O(N \cdot \log N)$
  • S: $O(N)$

Two Pointers

class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i = m - 1;w
int j = n - 1;
int k = m + n - 1;
while (j >= 0) {
if (i >= 0 && nums1[i] > nums2[j]) {
nums1[k] = nums1[i];
i--;
} else {
nums1[k] = nums2[j];
j--;
}
k--;
}
}
};
  • T: $O(N + M)$
  • S: $O(M)$

86. Partition List

· 閱讀時間約 2 分鐘

Given the head of a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.

You should preserve the original relative order of the nodes in each of the two partitions.

Example 1:

image

Input: head = [1,4,3,2,5,2], x = 3 Output: [1,2,2,4,3,5]

Example 2:

Input: head = [2,1], x = 2 Output: [1,2]

Constraints:

  • The number of nodes in the list is in the range [0, 200].
  • -100 <= Node.val <= 100
  • -200 <= x <= 200
/**
* Definition for singly-linked list.
* 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* partition(ListNode* head, int x) {
// 建立兩條 linked list: node1, node2;
ListNode* node1 = new ListNode(-1);
ListNode* node2 = new ListNode(-1);
ListNode* ptr1 = node1;
ListNode* ptr2 = node2;
while (head) {
// 如果 head 的 val 比 x 小
if (head->val < x) {
// 將 head 接到 ptr1->next
ptr1->next = head;
// 移動 ptr1
ptr1 = ptr1->next;
} else {
// 反之,接到 ptr2
ptr2->next = head;
// 移動 ptr2
ptr2 = ptr2->next;
}
// 移動 head
head = head->next;
}
// ptr2->next 為尾端 NULL
ptr2->next = nullptr;
// ptr1 後面接 node2->next
ptr1->next = node2->next;
// 最後返回 node1->next
return node1->next;
}
};
  • T: $O()$
  • S: $O()$