跳至主要内容

268 篇文章 含有標籤「leetcode」

檢視所有標籤

239. Sliding Window Maximum

· 閱讀時間約 2 分鐘
  • 在一個整數陣列中,找到每個滑動視窗中的最大值。函式接收兩個參數:一個是整數陣列 nums,另一個是滑動視窗的大小 k
  • 初始化一個 deque q,用來儲存滑動視窗中有潛力成為最大值的元素的 index。

deque

class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k)
{
int n = nums.size();
vector<int> res;
deque<int> q;

for (int i = 0; i < n; ++i)
{
// 因為滑動視窗會向前移動
// 當 q.front() 的元素離開視窗的時候
// 1 [3 -1 -3]
// ^ ^
// <- k -> i
if (!q.empty() && q.front() + k == i)
{
q.pop_front();
}

// 當發現 deque 尾端的元素比目前的 nums[i] 小的時候
// pop 掉,因為不可能成為最大值
// 所以 deque 裡面會存有潛力成為最大值數字的 index
while (!q.empty() && nums[q.back()] < nums[i])
{
q.pop_back();
}

// 將 index push 到 queue
q.push_back(i);

// 當發現 i + 1 >= k 的時候
// 代表滑動視窗的大小 k 已經形成
// 則將最大值 nums[q.front()] 推到 res
if (i + 1 >= k)
{
res.push_back(nums[q.front()]);
}
}
return res;
}
};
  • T: $O(n)$
  • S: $O(k)$

priority queue

class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k)
{
vector<int> res;

// 預設由大排到小
priority_queue<pair<int, int>> q;

for (int i = 0; i < nums.size(); ++i)
{
while (!q.empty() && q.top().second <= i - k)
{
q.pop();
}

// {存數字, 存 index}
q.push({nums[i], i});

// 如果滑動視窗形成
// 將最大值 push 到 res
if (i >= k - 1)
{
res.push_back(q.top().first);
}
}
return res;
}
};
  • T: $O(n)$
  • S: $O(k)$

238. Product of Array Except Self

· 閱讀時間約 2 分鐘

Hint

class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums)
{
// Initialize a vector to store the products of elements to the left of each index
// Initialize a vector to store the products of elements to the right of each index
// Initialize a vector to store the final result

// Compute the products of all elements to the left of each index
for ()
{
// Each element in arr1[i+1] is the product of all elements before nums[i+1]
}

// Compute the products of all elements to the right of each index
for ()
{
// Each element in arr2[i-1] is the product of all elements after nums[i-1]
}

// Compute the final result by multiplying the corresponding elements of arr1 and arr2
for ()
{
// The product of all elements except nums[i] is arr1[i] * arr2[i]
}
// Return the result vector
}
};
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums)
{
int n = nums.size();
vector<int> left(n, 1);
vector<int> right(n, 1);
vector<int> res(n);

for (int i = 0; i < n - 1; ++i)
{
left[i + 1] = left[i] * nums[i];
}

for (int i = n - 1; i > 0; --i)
{
right[i - 1] = right[i] * nums[i];
}

for (int i = 0; i < n; ++i)
{
res[i] = left[i] * right[i];
}
return res;
}
};
  • T: $O(N)$
  • S: $O(N)$

Hint - Space Improved

class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums)
{
// Initialize the result array with 1s, as we will be using multiplication.

// First pass: calculate the product of all elements to the left of each index.
for ()
{
// res[i] will be the product of all elements to the left of i.
}

// Variable to store the product of all elements to the right of the current index.
// Second pass: calculate the product of all elements to the right of each index and
// multiply it with the product from the first pass.
for ()
{
// Multiply with the product of elements to the right.
// Update the right product for the next iteration (one index to the left).
}
}
};
  • Space Improved
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums)
{
int n = nums.size();
vector<int> res(n, 1);

for (int i = 1; i < n; ++i)
{
res[i] = nums[i - 1] * res[i - 1];
}

int right = 1;
for (int i = n - 1; i >= 0; --i)
{
res[i] *= right;
right *= nums[i];
}
return res;
}
};
  • T: $O(N)$
  • S: $O(1)$

236. Lowest Common Ancestor of a Binary Tree

· 閱讀時間約 1 分鐘

Hint

/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/

class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
// If the current node is null, or if it is either p or q, return the current node

// Recur for the left subtree
// Recur for the right subtree

// If both left and right are non-null, it means p and q are found in different subtrees
// Hence, the current node is their lowest common ancestor

// If one of the left or right is non-null, return the non-null value
// This means either one of p or q is found and we are returning up the recursive call stack
}
};
  • Recursion
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
{
if (!root || root == p || root == q) return root;

TreeNode* left = lowestCommonAncestor(root->left, p, q);
TreeNode* right = lowestCommonAncestor(root->right, p, q);

if (left && right) return root;
return left ? left : right;
}
};
  • T: $O(N)$
  • S: $O(N)$

235. Lowest Common Ancestor of a Binary Search Tree

· 閱讀時間約 2 分鐘

Hint - Recursion

/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/

class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
{
// If both p and q are less than root's value, then LCA must be in the left subtree

// If both p and q are greater than root's value, then LCA must be in the right subtree

// If p and q are on different sides of root, or one of them is the root, then root is the LCA
}
};
  • Recursion
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/

class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
{
if (p->val < root->val && q->val < root->val)
{
return lowestCommonAncestor(root->left, p, q);
}

if (p->val > root->val && q->val > root->val)
{
return lowestCommonAncestor(root->right, p, q);
}
return root;
}
};
  • T: $O(N)$
  • S: $O(N)$

Hint - Iteration

/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/

class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
{
// Start with the root node

// Loop until we find the lowest common ancestor
while ()
{
// Get the value of the current node

// If both p and q are greater than parentVal, LCA must be in the right subtree
if ()
{
}
// If both p and q are less than parentVal, LCA must be in the left subtree
else if ()
{
}
// If p and q are on different sides of the current node, or one of them is the current node,
// then the current node is the lowest common ancestor
else
{
}
}
// This line is never reached because the loop always returns a node
}
};
  • Iteration
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/

class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
{
TreeNode* node = root;
while (true)
{
int parentVal = node->val;
if (parentVal < p->val && parentVal < q->val)
{
node = node->right;
}
else if (parentVal > p->val && parentVal > q->val)
{
node = node->left;
}
else
{
return node;
}
}
return node;
}
};
  • T: $O(N)$
  • S: $O(1)$

234. Palindrome Linked List

· 閱讀時間約 2 分鐘

Given the head of a singly linked list, return true_ if it is a _

palindrome

_ or false otherwise_.

Example 1:

image

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

Example 2:

image

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

Constraints:

  • The number of nodes in the list is in the range [1, 105].
  • 0 <= Node.val <= 9

判斷 linked list 是否有迴文

解法一:遞迴

/**
* 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:
bool isPalindrome(ListNode* head) {
ListNode* cur = head;
return helper(head, cur);
}
bool helper(ListNode* head, ListNode*& cur) {
if (!head) return true;
bool res = helper(head->next, cur) && (cur->val == head->val);
cur = cur->next;
return res;
}
};
  • T: $O(N)$
  • S: $O(N)$
/**
* 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:
bool isPalindrome(ListNode* head) {
if (!head || !head->next) return true;
ListNode* slow = head;
ListNode* fast = head;
stack<int> stk;
stk.push(head->val);
while (fast->next && fast->next->next) {
slow = slow->next;
fast = fast->next->next;
stk.push(slow->val);
}
if (!fast->next) stk.pop();

while (slow && slow->next) {
slow = slow->next;
int tmp = stk.top(); stk.pop();
if (tmp != slow->val) return false;
}
return true;
}
};
  • T: $O(N)$
  • S: $O(N)$

不用 stack,空間複雜度 $O(1)$ 的解法

  • T: $O(N)$
  • S: $O(1)$

232. Implement Queue using Stacks

· 閱讀時間約 2 分鐘

Implement a first in first out (FIFO) queue using only two stacks. The implemented queue should support all the functions of a normal queue (push, peek, pop, and empty).

Implement the MyQueue class:

  • void push(int x) Pushes element x to the back of the queue.
  • int pop() Removes the element from the front of the queue and returns it.
  • int peek() Returns the element at the front of the queue.
  • boolean empty() Returns true if the queue is empty, false otherwise.

Notes:

  • You must use only standard operations of a stack, which means only push to top, peek/pop from top, size, and is empty operations are valid.
  • Depending on your language, the stack may not be supported natively. You may simulate a stack using a list or deque (double-ended queue) as long as you use only a stack's standard operations.

Example 1:

Input ["MyQueue", "push", "push", "peek", "pop", "empty"] [[], [1], [2], [], [], []] Output [null, null, null, 1, 1, false]

Explanation MyQueue myQueue = new MyQueue(); myQueue.push(1); // queue is: [1] myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue) myQueue.peek(); // return 1 myQueue.pop(); // return 1, queue is [2] myQueue.empty(); // return false

Constraints:

  • 1 <= x <= 9
  • At most 100 calls will be made to push, pop, peek, and empty.
  • All the calls to pop and peek are valid.

解法:使用兩個 stacks

image

class MyQueue {
public:
MyQueue() {}

void push(int x) {
// 後進來的會維持在最上層
// 如果 s1 推了 1, 2, 3,3 會在最上面
s1.push(x);
}

int pop() {
peek();
int temp = s2.top(); s2.pop();
return temp;
}

int peek() {
// s2 用來儲存 s1 的反轉順序,如果 s2 裡面有值,直接回傳 s2.top();
if(!s2.empty()) return s2.top();
// 如果 s1 還有值,將元素丟到 s2 儲存,反轉順序
while(!s1.empty()) {
s2.push(s1.top()); s1.pop();
}
return s2.top();
}

bool empty() {
return s1.empty() && s2.empty();
}
private:
stack<int> s1; // push 進去的元素先裝在這,最後一個元素會維持在最上層
stack<int> s2; // 將 s1 的元素 pop() 到 s2,反轉順序
};

/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue* obj = new MyQueue();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->peek();
* bool param_4 = obj->empty();
*/
  • T: $O(N)$
  • S: $O(N)$

230. Kth Smallest Element in a BST

· 閱讀時間約 1 分鐘

Hint

/**
* 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 {
vector<int> v;
public:
int kthSmallest(TreeNode* root, int k)
{
dfs(root);
return v[k - 1];
}
void dfs(TreeNode* root)
{
if (!root) return;
dfs(root->left);
v.push_back(root->val);
dfs(root->right);
}
};
  • T: $O()$
  • S: $O()$

228. Summary Ranges

· 閱讀時間約 2 分鐘

You are given a sorted unique integer array nums.

A range [a,b] is the set of all integers from a to b (inclusive).

Return the smallest sorted list of ranges that cover all the numbers in the array exactly. That is, each element of nums is covered by exactly one of the ranges, and there is no integer x such that x is in one of the ranges but not in nums.

Each range [a,b] in the list should be output as:

  • "a->b" if a != b
  • "a" if a == b

Example 1:

Input: nums = [0,1,2,4,5,7] Output: ["0->2","4->5","7"] Explanation: The ranges are: [0,2] --> "0->2" [4,5] --> "4->5" [7,7] --> "7"

Example 2:

Input: nums = [0,2,3,4,6,8,9] Output: ["0","2->4","6","8->9"] Explanation: The ranges are: [0,0] --> "0" [2,4] --> "2->4" [6,6] --> "6" [8,9] --> "8->9"

Constraints:

  • 0 <= nums.length <= 20
  • -231 <= nums[i] <= 231 - 1
  • All the values of nums are unique.
  • nums is sorted in ascending order.
class Solution {
public:
vector<string> summaryRanges(vector<int>& nums) {
int n = nums.size();
vector<string> ranges;

for(int i = 0; i < n; i++) {
// 將 nums[i] 當作起始點 start
int start = nums[i];
// 如果跟下一個數字比,是連續遞增序列的話,i++
while(i < n - 1 && nums[i] + 1 == nums[i + 1]) {
i++;
}

if (start != nums[i]) {
// 像是 [0, 2] 這種情況
ranges.push_back(to_string(start) + "->" + to_string(nums[i]));
} else {
// 像是 [7, 7] 這種情況
ranges.push_back(to_string(start));
}
}
return ranges;
}
};
  • T: $O(n)$
  • S: $O(1)$

226. Invert Binary Tree

· 閱讀時間約 2 分鐘

Recursion

/*
* @lc app=leetcode id=226 lang=cpp
*
* [226] Invert Binary Tree
*
* https://leetcode.com/problems/invert-binary-tree/description/
*
* algorithms
* Easy (78.10%)
* Likes: 14546
* Dislikes: 241
* Total Accepted: 2.6M
* Total Submissions: 3.2M
* Testcase Example: '[4,2,7,1,3,6,9]'
*
* Given the root of a binary tree, invert the tree, and return its root.
*
*
* Example 1:
*
*
* Input: root = [4,2,7,1,3,6,9]
* Output: [4,7,2,9,6,3,1]
*
*
* Example 2:
*
*
* Input: root = [2,1,3]
* Output: [2,3,1]
*
*
* Example 3:
*
*
* Input: root = []
* Output: []
*
*
*
* Constraints:
*
*
* The number of nodes in the tree is in the range [0, 100].
* -100 <= Node.val <= 100
*
*
*/

// @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:
TreeNode* invertTree(TreeNode* root)
{
if (!root) return NULL;

swap(root->left, root->right);

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

  • S: $O(H)$

  • 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:
TreeNode* invertTree(TreeNode* root)
{
if (!root) return NULL;
queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
TreeNode* node = q.front(); q.pop();

swap(node->left, node->right);

if(node->left) q.push(node->left);
if(node->right) q.push(node->right);
}
return root;
}
};
  • T: $O(N)$
  • S: $O(N)$