LeetCode 双指针

LeetCode DFS 题目 26 删除排序数组中的重复项 用两个指针 len 和 i 分别表示没有重复的项的下标与遍历数组的下标,将没有重复的项拷贝到 nums[len] 下然后 ++len 即可。 class Solution { public: int removeDuplicates(vector<int>& nums) { int count = 0, len = 1, n = nums.size(); if (n == 0) return 0; for (int i = 1; i < n; ++i) { if (nums[i] == nums[i - 1]) continue; nums[len] = nums[i]; ++len; } return len; } }; 80 删除排序数组中的重复项 II 用两个指针 len 和 i 分别表示没有最多重复 2 次的项的下标与遍历数组的下标,将重复数小于等于 1 的项拷贝到 nums[len] 下然后 ++len 即可。 class Solution { public: int removeDuplicates(vector<int>& nums) { int count = 0, len = 1, n = nums.size(); if (n == 0) return 0; for (int i = 1; i < nums.size(); ++i) { if (nums[i] == nums[i - 1]) { if (count > 0) continue; ++count; } else count = 0; nums[len] = nums[i]; ++len; } return len; } }; 922 按奇偶排序数组 II 用两个下标 i 和 j 分别表示偶数位和奇数位的下标,如果偶数位下标对应的数不是偶数那么将其与奇数位下标对应的数不是奇数的数进行交换。 ...

July 31, 2019 · 7 min

LeetCode 深度优先搜索

LeetCode DFS 题目 78 子集 典型的回溯,找出所有可能情况。 class Solution { vector<vector<int>> res; public: vector<vector<int>> subsets(vector<int> &nums) { res = vector<vector<int>>(1, vector<int>()); vector<int> curr; DFS(nums, 0, curr); return res; } void DFS(vector<int> &nums, int idx, vector<int> &curr) { for (int i = idx; i < nums.size(); ++i) { curr.push_back(nums[i]); res.push_back(curr); DFS(nums, i + 1, curr); curr.pop_back(); } } }; 733 图像渲染 从给定的 image[sr][sc] 开始 DFS 或 BFS,将相邻的值相同的点的值全部修改为 newColor,注意要判断给定的 image[sr][sc] 是否等于 newColor,否则如果不使用额外空间的 visited 数组记录已经访问过的点的话会造成死循环栈溢出。 ...

July 27, 2019 · 13 min

LeetCode 并发

LeetCode 并发 题目 1114 按序打印 C++ mutex class Foo { mutex lock1, lock2; public: Foo() { lock1.lock(); lock2.lock(); } void first(function<void()> printFirst) { printFirst(); lock1.unlock(); } void second(function<void()> printSecond) { lock1.lock(); printSecond(); lock1.unlock(); lock2.unlock(); } void third(function<void()> printThird) { lock2.lock(); printThird(); lock2.unlock(); } }; C++ condition_variable class Foo { int i; mutex mut; condition_variable con_var1, con_var2; public: Foo() : i(1) { } void first(function<void()> printFirst) { unique_lock<mutex> lock(mut); printFirst(); ++i; con_var1.notify_one(); } void second(function<void()> printSecond) { unique_lock<mutex> lock(mut); con_var1.wait(lock, [this]() { return i == 2; }); printSecond(); ++i; con_var2.notify_one(); } void third(function<void()> printThird) { unique_lock<mutex> lock(mut); con_var2.wait(lock, [this]() { return i == 3; }); printThird(); } }; C++ atomic class Foo { atomic_int i; public: Foo() : i(1) { } void first(function<void()> printFirst) { printFirst(); ++i; } void second(function<void()> printSecond) { while (i != 2) {} printSecond(); ++i; } void third(function<void()> printThird) { while (i != 3) {} printThird(); i = 1; } }; C++ promise class Foo { promise<void> pro1, pro2; public: Foo() { } void first(function<void()> printFirst) { printFirst(); pro1.set_value(); } void second(function<void()> printSecond) { pro1.get_future().wait(); printSecond(); pro2.set_value(); } void third(function<void()> printThird) { pro2.get_future().wait(); printThird(); } }; 1115 交替打印FooBar C++ mutex class FooBar { private: int n; mutex mut1, mut2; public: FooBar(int n) { this->n = n; mut2.lock(); } void foo(function<void()> printFoo) { for (int i = 0; i < n; i++) { mut1.lock(); printFoo(); mut2.unlock(); } } void bar(function<void()> printBar) { for (int i = 0; i < n; i++) { mut2.lock(); printBar(); mut1.unlock(); } } }; C++ condition_variable class FooBar { private: int m, n; mutex mut; condition_variable con_var1, con_var2; public: FooBar(int n) : n(n), m(0) { } void foo(function<void()> printFoo) { for (int i = 0; i < n; i++) { unique_lock<mutex> lock(mut); con_var1.wait(lock, [&]() { return m == 0; }); printFoo(); ++m; con_var2.notify_one(); } } void bar(function<void()> printBar) { for (int i = 0; i < n; i++) { unique_lock<mutex> lock(mut); con_var2.wait(lock, [&]() { return m == 1; }); printBar(); m = 0; con_var1.notify_one(); } } }; C++ atomic class FooBar { private: int n; atomic_int m; public: FooBar(int n) : n(n), m(0) { } void foo(function<void()> printFoo) { for (int i = 0; i < n; i++) { while (m != 0) {} printFoo(); m = 1; } } void bar(function<void()> printBar) { for (int i = 0; i < n; i++) { while (m != 1) {} printBar(); m = 0; } } }; C++ promise class FooBar { private: int n; vector<promise<void>> pros1, pros2; public: FooBar(int n) : n(n) { for (int i = 0; i < n; ++i) { pros1.push_back(promise<void>()); pros2.push_back(promise<void>()); } } void foo(function<void()> printFoo) { for (int i = 0; i < n; i++) { if (i != 0) pros1[i - 1].get_future().wait(); printFoo(); pros2[i].set_value(); } } void bar(function<void()> printBar) { for (int i = 0; i < n; i++) { pros2[i].get_future().wait(); printBar(); pros1[i].set_value(); } } }; 1116 打印零与奇偶数 C++ mutex class ZeroEvenOdd { private: int m, n; mutex mut_zero, mut_odd, mut_even; public: ZeroEvenOdd(int n) { this->m = 1; this->n = n; mut_odd.lock(); mut_even.lock(); } void zero(function<void(int)> printNumber) { for (int i = 0; i < n; ++i) { mut_zero.lock(); printNumber(0); if (this->m % 2 == 1) mut_odd.unlock(); else mut_even.unlock(); } } void even(function<void(int)> printNumber) { for (int i = 0; i < n / 2; ++i) { mut_even.lock(); printNumber(this->m); ++this->m; mut_zero.unlock(); } } void odd(function<void(int)> printNumber) { for (int i = 0; i < (n + 1) / 2; ++i) { mut_odd.lock(); printNumber(this->m); ++this->m; mut_zero.unlock(); } } }; 1117 H2O 生成 C++ condition variable class H2O { int m = 1; mutex mut; condition_variable con_var; public: void hydrogen(function<void()> releaseHydrogen) { unique_lock<mutex> lock(mut); con_var.wait(lock, [&]() { return m % 3 != 0; }); ++m; releaseHydrogen(); con_var.notify_all(); } void oxygen(function<void()> releaseOxygen) { unique_lock<mutex> lock(mut); con_var.wait(lock, [&]() { return m % 3 == 0; }); ++m; releaseOxygen(); con_var.notify_all(); } };

July 22, 2019 · 3 min

LeetCode 树(2)

LeetCode 树(2) 题目 3. 二叉搜索树 95 不同的二叉搜索树 II 生成由 1 … n 为节点所组成的二叉搜索树。 为了构造以 i 为根节点的二叉搜索树,我们需要先构造以 1 … i - 1 为左子树的所有二叉搜索树与以 i + 1 … n 为右子树的所有二叉搜索树,再将这些子树排列组合得到以 i 为根节点的所有二叉搜索树。 class Solution { public: vector<TreeNode *> generateTrees(int n) { if (n == 0) return {}; return Generate(1, n); } vector<TreeNode *> Generate(int m, int n) { vector<TreeNode *> nodes; if (m == n) nodes.push_back(new TreeNode(n)); if (m > n) nodes.push_back(nullptr); if (m >= n) return nodes; for (int i = m; i <= n; ++i) { vector<TreeNode *> left = Generate(m, i - 1); vector<TreeNode *> right = Generate(i + 1, n); for (auto &l:left) for (auto &r:right) { TreeNode *node = new TreeNode(i); node->left = l, node->right = r; nodes.push_back(node); } } return nodes; } }; 98 验证二叉搜索树 因为二叉搜索树的中序遍历结果是一个有序数组,所以一种方法是将中序遍历的结果保存下来进行判断,也可以根据二叉搜索树的定义判断子节点和根节点的大小关系。 ...

July 18, 2019 · 5 min

LeetCode 树(1)

LeetCode 树(1) 题目 1. 树的遍历 144 二叉树的前序遍历 前序遍历一个二叉树。 前序遍历是按照根节点,左子节点,右子节点的顺序来遍历一个二叉树,有递归和迭代两种方法。对于迭代方法,先将节点加入结果数组,然后用一个栈保存右,左子节点,依次访问,重复此过程。 class Solution { vector<int> res; public: vector<int> preorderTraversal(TreeNode *root) { res = vector<int>(); Preorder(root); return res; } void Preorder(TreeNode *root) { if (!root) return; res.push_back(root->val); Preorder(root->left); Preorder(root->right); } }; class Solution { public: vector<int> preorderTraversal(TreeNode *root) { vector<int> res; if (!root) return res; stack<TreeNode *> pre; pre.push(root); while (!pre.empty()) { TreeNode *node = pre.top(); pre.pop(); res.push_back(node->val); if (node->right) pre.push(node->right); if (node->left) pre.push(node->left); } return res; } }; 589 N叉树的前序遍历 前序遍历一个 N 叉树。 ...

July 13, 2019 · 7 min