LeetCode题解-02(树、字典树、堆)
目录
- LeetCode题解
- chap-4: 树
- 1、验证二叉搜索树
- 2、恢复二叉搜索树
- 3、相同的树
- 4、对称二叉树
- 5、二叉树的层序遍历
- 6、二叉树的层序遍历 II
- 7、二叉树的锯齿形层序遍历
- 8、二叉树的最大深度
- 9、从前序与中序遍历序列构造二叉树
- 10、从中序与后序遍历序列构造二叉树
- 11、将有序数组转换为二叉搜索树
- 12、有序链表转换二叉搜索树
- 13、平衡二叉树
- 14、二叉树的最小深度
- 15、路径总和
- 16、路径总和 II
- 17、二叉树展开为链表
- 18、填充每个节点的下一个右侧节点指针【×】
- 19、填充每个节点的下一个右侧节点指针 II 【×】
- 20、二叉树中的最大路径和【×】
- 21、求根节点到叶节点数字之和
- 22、二叉树的前序遍历
- 23、二叉树的后序遍历【×】
- 24、二叉搜索树迭代器
- 25、完全二叉树的节点个数
- 26、翻转二叉树
- 27、二叉搜索树中第K小的元素
- 28、二叉树的序列化与反序列化【×】
- 29、将数据流变为多个不相交区间
- 30、左叶子之和
- 31、N 叉树的层序遍历
- 32、序列化和反序列化二叉搜索树
- 33、删除二叉搜索树中的节点
- 34、二叉搜索树中的众数【×】
- 35、找树左下角的值
- 36、在每个树行中找最大值
- 37、奇偶树
- chap-5: Trie树(字典树)
- chap-6: 堆
- chap-4: 树
LeetCode题解
chap-4: 树
1、验证二叉搜索树
/**
* 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) {
if(root == nullptr) return true;
if(root->left == nullptr && root->right == nullptr) return true;
auto left = root->left, right = root->right;
while(left){
if(left->val >= root->val) return false;
left = left->right;
}
while(right){
if(right->val <= root->val) return false;
right = right->left;
}
return isValidBST(root->left) && isValidBST(root->right);
}
};
2、恢复二叉搜索树
思路:二叉搜索树满足中序遍历的有序性,可以通过查找中序遍历逆序对,进而确定交换值的位置
class Solution {
public:
TreeNode *pre = NULL, *first = NULL, *second = NULL;
void recoverTree(TreeNode* root) {
dfs(root);
swap(first -> val, second -> val);
}
void dfs(TreeNode* root)
{
if (!root) return;
dfs(root -> left);
if (!pre) pre = root;
if (root -> val < pre -> val)
{
if (!first) first = pre;
second = root;
}
pre = root;
dfs(root -> right);
}
};
Morris遍历
class Solution {
public:
void recoverTree(TreeNode* root) {
TreeNode *first = NULL, *second, *prep = NULL;
while (root)
{
if (!root->left)
{
if (prep && prep->val > root->val)
{
if (!first) first = prep, second = root;
else second = root;
}
prep = root;
root = root->right;
}
else
{
TreeNode *p = root->left;
while (p->right && p->right != root) p = p->right;
if (!p->right)
{
p->right = root;
root = root->left;
}
else
{
p->right = NULL;
if (prep && prep->val > root->val)
{
if (!first) first = prep, second = root;
else second = root;
}
prep = root;
root = root->right;
}
}
}
swap(first->val, second->val);
}
};
3、相同的树
class Solution {
public:
bool isSameTree(TreeNode* p, TreeNode* q) {
if(!p && !q) return true;
if(!q || !p || p->val != q->val) return false;
return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
}
};
4、对称二叉树
class Solution {
public:
bool dfs(TreeNode* r,TreeNode* l){
if(!r && !l) return true;
if(!r || !l || r->val != l->val) return false;
return dfs(r->right,l->left) && dfs(r->left,l->right);
}
bool isSymmetric(TreeNode* root) {
if(root == nullptr) return true;
return dfs(root->right,root->left);
}
};
5、二叉树的层序遍历
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> ans;
if(root == nullptr) return ans;
queue<TreeNode*> q;
q.push(root);
while(q.size()){
int n = q.size();
vector<int> temp;
while(n--){
auto t = q.front(); q.pop();
temp.push_back(t->val);
if(t->left) q.push(t->left);
if(t->right) q.push(t->right);
}
ans.push_back(temp);
}
return ans;
}
};
6、二叉树的层序遍历 II
class Solution {
public:
vector<vector<int>> levelOrderBottom(TreeNode* root) {
vector<vector<int>> res;
queue<TreeNode*> q;
if (root) q.push(root);
while (q.size()) {
vector<int> level;
int len = q.size();
while (len -- ) {
auto t = q.front();
q.pop();
level.push_back(t->val);
if (t->left) q.push(t->left);
if (t->right) q.push(t->right);
}
res.push_back(level);
}
reverse(res.begin(),res.end());
return res;
}
};
7、二叉树的锯齿形层序遍历
class Solution {
public:
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
vector<vector<int>> ans; if(root == nullptr) return ans;
queue<TreeNode*> q;
q.push(root); bool zig = false;
while(q.size()){
int n = q.size(); vector<int> temp;
while(n--){
auto t = q.front(); q.pop();
temp.push_back(t->val);
if(t->left)q.push(t->left);
if(t->right)q.push(t->right);
}
if(zig) reverse(temp.begin(),temp.end());
zig = !zig;
ans.push_back(temp);
}
return ans;
}
};
8、二叉树的最大深度
class Solution {
public:
int maxDepth(TreeNode* root) {
if(root == nullptr) return 0;
return max(maxDepth(root->left),maxDepth(root->right)) + 1;
}
};
9、从前序与中序遍历序列构造二叉树
class Solution {
public:
unordered_map<int,int> pos;
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int n = preorder.size();
for (int i = 0; i < n; i ++ )
pos[inorder[i]] = i;
return dfs(preorder, inorder, 0, n - 1, 0, n - 1);
}
TreeNode* dfs(vector<int>&pre, vector<int>&in, int pl, int pr, int il, int ir)
{
if (pl > pr) return NULL;
int k = pos[pre[pl]] - il;
TreeNode* root = new TreeNode(pre[pl]);
root->left = dfs(pre, in, pl + 1, pl + k, il, il + k - 1);
root->right = dfs(pre, in, pl + k + 1, pr, il + k + 1, ir);
return root;
}
};
10、从中序与后序遍历序列构造二叉树
class Solution {
public:
TreeNode* buildTree(vector<int> in, vector<int> post) {
if(in.size() == 0) return nullptr;
auto root = new TreeNode(post.back());
int i = 0; while(i<in.size() && in[i] != post.back()) i++;
root->left = buildTree(vector<int>(in.begin(),in.begin()+i),vector<int>(post.begin(),post.begin()+i));
root->right = buildTree(vector<int>(in.begin()+i+1,in.end()),vector<int>(post.begin()+i,post.end()-1));
return root;
}
};
11、将有序数组转换为二叉搜索树
class Solution {
public:
TreeNode* sortedArrayToBST(vector<int> nums) {
if(nums.empty()) return nullptr;
int n = nums.size(), mid = n>>1;
auto root = new TreeNode(nums[mid]);
root->left = sortedArrayToBST(vector<int>(nums.begin(),nums.begin()+mid));
root->right = sortedArrayToBST(vector<int>(nums.begin()+mid+1,nums.end()));
return root;
}
};
12、有序链表转换二叉搜索树
class Solution {
public:
TreeNode* sortedListToBST(ListNode* head) {
if(head == nullptr) return nullptr;
auto dummy = new ListNode(-1);
dummy->next = head;
auto slow = dummy, fast = dummy;
while(slow && fast){
slow = slow->next;
if(fast->next) fast = fast->next->next;
else fast = fast->next;
}
fast = dummy;
while(fast->next != slow) fast = fast->next;
auto root = new TreeNode(slow->val);
fast->next = nullptr;
root->left = sortedListToBST(dummy->next);
root->right = sortedListToBST(slow->next);
return root;
}
};
13、平衡二叉树
class Solution {
public:
int maxdepth(TreeNode* root){
if(root == nullptr) return 0;
return max(maxdepth(root->left),maxdepth(root->right)) + 1;
}
bool isBalanced(TreeNode* root) {
if(root == nullptr) return true;
if(abs(maxdepth(root->left) - maxdepth(root->right)) <= 1 && isBalanced(root->left) && isBalanced(root->right))
return true;
else return false;
}
};
14、二叉树的最小深度
class Solution {
public:
int minDepth(TreeNode* root) {
if(root == nullptr) return 0;
if(root->left == nullptr && root->right == nullptr) return 1;
int l = INT_MAX, r = INT_MAX;
if(root->left) l = min(minDepth(root->left),l);
if(root->right) r = min(minDepth(root->right),r);
return min(l,r)+1;
}
};
15、路径总和
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum) {
if(root == nullptr) return false;
if(root->left == nullptr && root->right == nullptr && targetSum == root->val) return true;
return hasPathSum(root->left,targetSum - root->val) || hasPathSum(root->right, targetSum - root->val);
}
};
16、路径总和 II
class Solution {
public:
vector<int> path;
vector<vector<int>> ans;
void dfs(TreeNode* root, int targetSum){
if(root == nullptr) return;
if(root->left == nullptr && root->right == nullptr && root->val == targetSum) {
path.push_back(root->val);
ans.push_back(path);
path.pop_back();
return;
}
path.push_back(root->val);
dfs(root->left,targetSum - root->val);
dfs(root->right,targetSum - root->val);
path.pop_back();
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
dfs(root,targetSum);
return ans;
}
};
17、二叉树展开为链表
class Solution {
public:
void flatten(TreeNode* root) {
if(root == nullptr) return;
stack<TreeNode*>s;
s.push(root); auto temp = new TreeNode(-1);
while(s.size()){
auto t = s.top(); s.pop();
if(t->right) s.push(t->right);
if(t->left) s.push(t->left);
temp->left = nullptr;
temp->right = t; temp = temp->right;
}
root = temp->right;
}
};
// O(1)空间负责度
class Solution {
public:
void flatten(TreeNode* root) {
TreeNode *now = root;
while (now)
{
if (now->left)
{
TreeNode *p = now->left;
while (p->right) p = p->right;
p->right = now->right;
now->right = now->left;
now->left = 0;
}
now = now->right;
}
}
};
18、填充每个节点的下一个右侧节点指针【×】
class Solution {
public:
Node* connect(Node* root) {
if(root == NULL) return root;
auto l = connect(root->left);
auto r = connect(root->right);
while(l && r){
l->next = r;
l = l->right; r = r->left;
}
return root;
}
};
// 进阶
class Solution {
public:
Node* connect(Node* root) {
if (!root) return root;
auto source = root;
while (root->left) {
for (auto p = root; p; p = p->next) {
p->left->next = p->right;
if (p->next) p->right->next = p->next->left;
}
root = root->left;
}
return source;
}
};
19、填充每个节点的下一个右侧节点指针 II 【×】
class Solution {
public:
Node* connect(Node* root) {
if(!root) return root;
auto cur = root;
while(cur){
auto head = new Node(-1), tail = head;
for(auto p =cur;p;p=p->next){
if(p->left) tail = tail->next = p->left;
if(p->right) tail = tail->next = p->right;
}
cur = head->next;
}
return root;
}
};
20、二叉树中的最大路径和【×】
class Solution {
public:
int ans = INT_MIN;
int dfs(TreeNode* root){
if(!root) return 0;
int l = max(0,dfs(root->left));
int r = max(0,dfs(root->right));
ans = max(ans,root->val + l + r);
return root->val + max(l,r);
}
int maxPathSum(TreeNode* root) {
dfs(root);
return ans;
}
};
21、求根节点到叶节点数字之和
class Solution {
public:
int ans = 0;
int sumNumbers(TreeNode* root) {
if(root)dfs(root, 0);
return ans;
}
void dfs(TreeNode* root, int number)
{
number = number * 10 + root->val;
if(!root -> left && !root->right) ans += number;
if(root->left) dfs(root->left,number);
if(root->right) dfs(root->right, number);
}
};
22、二叉树的前序遍历
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> ans; if(root==nullptr) return ans;
stack<TreeNode*> s;
s.push(root);
while(s.size()){
auto t = s.top(); s.pop();
ans.push_back(t->val);
if(t->right) s.push(t->right);
if(t->left) s.push(t->left);
}
return ans;
}
};
23、二叉树的后序遍历【×】
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> ans; if(!root) return ans;
stack<TreeNode*> s;
s.push(root);
while(s.size()){
root = s.top();s.pop();
ans.push_back(root->val);
if(root->left) s.push(root->left);
if(root->right) s.push(root->right);
}
reverse(ans.begin(),ans.end());
return ans;
}
};
// 不取巧
class Solution {
public:
vector<int> postorderTraversal(TreeNode* cur) {
stack<TreeNode*> s;
vector<int> ans;
TreeNode* last = nullptr; // 开辟变量存储前一次访问位置
while(cur != nullptr || s.size()){
while(cur != nullptr){
s.push(cur);
cur = cur->left;
}
cur = s.top();
if(cur->right == nullptr || cur->right == last){
ans.push_back(cur->val);
last = cur;
cur = nullptr;
s.pop();
}else cur = cur->right;
}
return ans;
}
};
24、二叉搜索树迭代器
class BSTIterator {
public:
stack<TreeNode*> s;
BSTIterator(TreeNode* root) {
while(root){
s.push(root);
root = root->left;
}
}
int next() {
auto cur = s.top();
s.pop();
int v = cur->val;
cur = cur->right;
while(cur){s.push(cur); cur = cur->left;}
return v;
}
bool hasNext() {
return !s.empty();
}
};
25、完全二叉树的节点个数
1、对于每个节点,计算一直向左和一直向右的高度,如果相等则说明是满二叉树,那么该树节点个数为\(2^h−1\)
2、如果不相等则说明不是满二叉树,则需要递归地向下求解,该棵树的节点个数等于1+左子树节点数+右子树节点数
class Solution {
public:
int countNodes(TreeNode* root) {
if(!root) return 0;
auto l = root, r = root;
int a = 0, b = 0;
while(l){a++; l = l->left;}
while(r){b++; r = r->right;}
if(a == b) return (1<<a) - 1;
return countNodes(root->left) + countNodes(root->right) + 1;
}
};
26、翻转二叉树
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(root == nullptr) return root;
swap(root->left, root->right);
invertTree(root->left);
invertTree(root->right);
return root;
}
};
27、二叉搜索树中第K小的元素
class Solution {
public:
int dfs(TreeNode* root){
if(!root) return 0;
return dfs(root->left) + dfs(root->right) + 1;
}
int kthSmallest(TreeNode* root, int k) {
int m = dfs(root->left);
if(m+1 == k) return root->val;
else if(m > k) return kthSmallest(root->left,k);
else if(m == k){
root = root->left;
while(root->right) root = root->right;
return root->val;
}else return kthSmallest(root->right,k-m-1);
}
};
28、二叉树的序列化与反序列化【×】
class Codec {
public:
void dfs(TreeNode* root,string &help){
if(!root) help += "#,";
else{
help += to_string(root->val) + ',';
dfs(root->left,help);
dfs(root->right,help);
}
}
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
string help;
dfs(root,help);
return help;
}
TreeNode* vdfs(const string& data,int& i){ // 引用减少内存重复申请 +
if(i>=data.size()) return NULL;
int k = i;
while(i<data.size() && data[i] != ',')i++;
string s = data.substr(k,i++ - k);
if(s == "#") return NULL;
else{
auto t = new TreeNode(stoi(s));
t->left = vdfs(data,i);
t->right = vdfs(data,i);
return t;
}
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
int i = 0;
return vdfs(data,i);
}
};
29、将数据流变为多个不相交区间
#define x first
#define y second
typedef pair<int, int> PLL;
class SummaryRanges {
public:
/** Initialize your data structure here. */
set<PLL> S;
SummaryRanges() {
S.insert({INT_MIN, INT_MIN}), S.insert({INT_MAX, INT_MAX});
}
void addNum(int num) {
auto r = S.upper_bound({num, INT_MAX});
auto l = r; -- l;
if (l->y >= num) return;
if (l->y == num - 1 && r->x == num + 1) {
S.insert({l->x, r->y});
S.erase(l), S.erase(r);
} else if (l->y == num - 1) {
S.insert({l->x, num});
S.erase(l);
} else if (r->x == num + 1) {
S.insert({num, r->y});
S.erase(r);
} else {
S.insert({num, num});
}
}
vector<vector<int>> getIntervals() {
vector<vector<int>> res;
for (auto& p: S)
if (p.x != INT_MIN && p.x != INT_MAX)
res.push_back({(int)p.x, (int)p.y});
return res;
}
};
30、左叶子之和
class Solution {
public:
void dfs(TreeNode* root,TreeNode* pre,int& ans){
if(root == nullptr) return;
if(!root->left && !root->right && root == pre->left) ans+=root->val;
else dfs(root->left,root,ans), dfs(root->right,root,ans);
}
int sumOfLeftLeaves(TreeNode* root) {
int ans = 0;
dfs(root,root,ans);
return ans;
}
};
31、N 叉树的层序遍历
class Solution {
public:
vector<vector<int>> levelOrder(Node* root) {
vector<vector<int>> ans;
if(!root) return ans;
queue<Node*> q;
q.push(root);
while(q.size()){
int n = q.size(); vector<int> temp;
while(n--){
auto t = q.front();q.pop();
for(auto& a:t->children){
q.push(a);
}
temp.push_back(t->val);
}
ans.push_back(temp);
}
return ans;
}
};
32、序列化和反序列化二叉搜索树
class Codec {
public:
void dfs(TreeNode* root,string &ans){
if(root == NULL) return;
ans += to_string(root->val) + ' ';
dfs(root->left,ans), dfs(root->right,ans);
}
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
string ans;
dfs(root,ans);
return ans;
}
TreeNode* vdfs(vector<int>& data,int& u,int Max,int Min){
if(u == data.size() || data[u] > Max || data[u] < Min) return NULL;
auto root = new TreeNode(data[u++]);
root->left = vdfs(data,u,root->val,Min);
root->right = vdfs(data,u,Max,root->val);
return root;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
vector<int> d;
stringstream sin(data);
int n=0, u=0;
while(sin>>n) d.push_back(n);
return vdfs(d,u,INT_MAX,INT_MIN);
}
};
33、删除二叉搜索树中的节点
class Solution {
public:
void dfs(TreeNode*& root, int k){
if(!root) return;
if(root->val == k){
if(!root->left && !root->right) root=nullptr;
else if (!root->left) root = root->right; // 只有右儿子
else if (!root->right) root = root->left; // 只有左儿子
else {
auto t = root->left;
while(t->right) t = t->right;
root->val = t->val;
dfs(root->left,t->val);
}
}else if(root->val < k) dfs(root->right,k);
else dfs(root->left,k);
}
TreeNode* deleteNode(TreeNode* root, int key) {
dfs(root,key);
return root;
}
};
34、二叉搜索树中的众数【×】
class Solution {
public:
vector<int> ans;
int maxc = 0, curc = 0, last;
void dfs(TreeNode*root){
if(root == nullptr) return;
dfs(root->left);
if (!curc || root->val == last) {
curc ++;
last = root->val;
} else {
last = root->val;
curc = 1;
}
if (curc > maxc) ans = {last}, maxc = curc;
else if (curc == maxc) ans.push_back(last);
dfs(root->right);
}
vector<int> findMode(TreeNode* root) {
dfs(root);
return ans;
}
};
35、找树左下角的值
// bfs
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
int ans;
queue<TreeNode*> q;
q.push(root);
while(q.size()){
auto t = q.front(); ans = t->val;
int n = q.size();
while(n--){
t = q.front(); q.pop();
if(t->left) q.push(t->left);
if(t->right) q.push(t->right);
}
}
return ans;
}
};
// dfs
class Solution {
public:
int maxd = 0,ans = 0;
int findBottomLeftValue(TreeNode* root) {
dfs(root,1);
return ans;
}
void dfs(TreeNode*root,int d){
if(!root) return;
if(d > maxd){
maxd = d;
ans = root->val;
}dfs(root->left,d+1), dfs(root->right,d+1);
}
};
36、在每个树行中找最大值
class Solution {
public:
unordered_map<int, int> hash;
int maxd = 0;
vector<int> largestValues(TreeNode* root) {
dfs(root, 1);
vector<int> res;
for (int i = 1; i <= maxd; i ++ )
res.push_back(hash[i]);
return res;
}
void dfs(TreeNode* root, int d) {
if (!root) return;
maxd = max(maxd, d);
if (hash.count(d) == 0) hash[d] = root->val;
else hash[d] = max(hash[d], root->val);
dfs(root->left, d + 1);
dfs(root->right, d + 1);
}
};
37、奇偶树
class Solution {
public:
bool isEvenOddTree(TreeNode* root) {
queue<TreeNode*> q;
if (root) q.push(root);
int level = 0;
while (!q.empty()) {
int len = q.size();
int value = (level == 0) ? INT_MIN : INT_MAX;
while (len--) {
auto cur = q.front(); q.pop();
if ((level == 0) && (cur->val % 2 == 0 || cur->val <= value) ||
(level == 1) && (cur->val % 2 == 1 || cur->val >= value))
return false;
value = cur->val;
if (cur->left) q.push(cur->left);
if (cur->right) q.push(cur->right);
}
level ^= 1;
}
return true;
}
};
[Go Back~~](# LeetCode题解)
chap-5: Trie树(字典树)
1、实现 Trie (前缀树)
class Trie {
public:
struct Node{
Node * nxt[26];
bool end;
Node(){
for(int i=0;i<26;i++) nxt[i] = NULL;
end = false;
}
};
Node* data;
/** Initialize your data structure here. */
Trie() {
data = new Node();
}
/** Inserts a word into the trie. */
void insert(string word) {
auto t = data;
for(auto& c:word){
if(t->nxt[c-'a'] == NULL)
t->nxt[c-'a'] = new Node();
t = t->nxt[c - 'a'];
}
t->end = true;
}
/** Returns if the word is in the trie. */
bool search(string word) {
auto t = data;
for(auto& c:word){
if(t->nxt[c-'a'])
t = t->nxt[c - 'a'];
else return false;
}
return t->end == true;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(string prefix) {
auto t = data;
for(auto& c:prefix){
if(t->nxt[c-'a'])
t = t->nxt[c - 'a'];
else return false;
}
return true;
}
};
2、添加与搜索单词 - 数据结构设计
class WordDictionary {
public:
struct Node{
Node* nxt[26];
bool end;
Node(){
for(int i = 0;i<26;i++) nxt[i] = NULL;
end = false;
}
}*root;
/** Initialize your data structure here. */
WordDictionary() {
root = new Node();
}
void addWord(string word) {
auto t = root;
for(auto &c:word){
if(t->nxt[c - 'a'] == NULL)
t->nxt[c-'a'] = new Node();
t = t->nxt[c - 'a'];
}
t->end = true;
}
bool dfs(Node* t,string& word,int u){
if(!t || u == word.size()) return false;
if(word[u] != '.'){
if(t->nxt[word[u] - 'a'] == NULL) return false;
else if(u == word.size() - 1) return t->nxt[word[u] - 'a']->end == true;
else return dfs(t->nxt[word[u] - 'a'],word,u+1);
}else{
auto f = false;
for(auto i = 0;i<26;i++){
if(t->nxt[i])
if(u == word.size() -1 && t->nxt[i]->end) return true;
else f |= dfs(t->nxt[i],word,u+1);
}
return f;
}
}
bool search(string word) {
auto t = root;
return dfs(t,word,0);
}
};
3、单词搜索 II
// board建立trie树
class Solution {
public:
struct Node{
Node* nxt[26];
Node(){
for(auto i = 0;i<26;i++) nxt[i] = NULL;
}
}*root;
int col[4] = {1,0,-1,0}, row[4] = {0,1,0,-1};
vector<vector<bool>> f;
void dfs(Node* t,vector<vector<char>>& board, int i,int j,int u,int cnt){
if(u == cnt) return;
for(int k = 0;k<4;k++){
int x = i+row[k], y = j+col[k];
if(x>=0 && x<board.size() && y>=0 && y<board[0].size() && !f[x][y]){
auto temp = t;
if(t->nxt[board[x][y] -'a'] == NULL) t->nxt[board[x][y] -'a'] = new Node;
temp = t->nxt[board[x][y] -'a'];
f[x][y] = true;
dfs(temp,board,x,y,u+1,cnt);
f[x][y] = false;
}
}
}
bool search(Node* t,string& word){
for(auto &c:word){
if(t->nxt[c - 'a'] == NULL) return false;
else t = t->nxt[c - 'a'];
}
return true;
}
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
root = new Node();
f = vector<vector<bool>>(board.size(),vector<bool>(board[0].size(),false));
int cnt = 0; vector<string> ans;
for(auto &word:words) cnt = max(cnt,(int)word.size());
for(int i = 0;i<board.size();i++){
for(int j = 0;j<board[0].size();j++){
auto t = root;
if(t->nxt[board[i][j] -'a'] == NULL) t->nxt[board[i][j] -'a'] = new Node;
t = t->nxt[board[i][j] -'a'];
f[i][j] = true;
dfs(t,board,i,j,1,cnt);
f[i][j] = false;
}
}
for(auto &word:words){
auto t = root;
if(word.size() <= board.size()*board[0].size() && search(t,word)) ans.push_back(word);
}
return ans;
}
};
// words建trie树
class Solution {
public:
struct Node {
int id;
Node *son[26];
Node() {
id = -1;
for (int i = 0; i < 26; i ++ ) son[i] = NULL;
}
}*root;
unordered_set<int> ids;
vector<vector<char>> g;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
void insert(string& word, int id) {
auto p = root;
for (auto c: word) {
int u = c - 'a';
if (!p->son[u]) p->son[u] = new Node();
p = p->son[u];
}
p->id = id;
}
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
g = board;
root = new Node();
for (int i = 0; i < words.size(); i ++ ) insert(words[i], i);
for (int i = 0; i < g.size(); i ++ )
for (int j = 0; j < g[i].size(); j ++ ) {
int u = g[i][j] - 'a';
if (root->son[u])
dfs(i, j, root->son[u]);
}
vector<string> res;
for (auto id: ids) res.push_back(words[id]);
return res;
}
void dfs(int x, int y, Node* p) {
if (p->id != -1) ids.insert(p->id);
char t = g[x][y];
g[x][y] = '.';
for (int i = 0; i < 4; i ++ ) {
int a = x + dx[i], b = y + dy[i];
if (a >= 0 && a < g.size() && b >= 0 && b < g[0].size() && g[a][b] != '.') {
int u = g[a][b] - 'a';
if (p->son[u]) dfs(a, b, p->son[u]);
}
}
g[x][y] = t;
}
};
4、数组中两个数的最大异或值
class Solution {
public:
struct Node{
Node* nxt[2];
Node(){
nxt[0] = NULL;
nxt[1] = NULL;
}
};
int findMaximumXOR(vector<int>& nums) {
int ans = 0; if(nums.size() == 1) return ans;
auto root = new Node();
for(auto&num:nums) {
auto t = root;
bitset<32> n = num;
for(int i = 31;~i;i--){
if(t->nxt[n[i]] == NULL) t->nxt[n[i]] = new Node;
t = t->nxt[n[i]];
}
}
for(auto&num:nums) {
auto t = root;
bitset<32> n = num;
int b = 0;
for(int i = 31;~i;i--){
if(t->nxt[~n[i]]){
b = (b<<1) + ~n[i];
t = t->nxt[~n[i]];
}else {
b = (b<<1) + n[i];
t = t->nxt[n[i]];
}
}
ans = max(ans,num^b);
}
return ans;
}
};
[Go Back~~](# LeetCode题解)
chap-6: 堆
1、数组中的第K个最大元素
// 堆
class Solution {
public:
vector<int> tree;
void adjust(int root,int k){
auto t = tree[root], j = 2*root+1;
while(j<k){
if(j+1<k && tree[j+1] < tree[j]) j++;
if(tree[j] > t) break;
tree[(j-1)/2] = tree[j];
j = 2*j+1;
}
tree[(j-1)/2] = t;
}
int findKthLargest(vector<int>& nums, int k) {
int n = nums.size(), i = 0;
tree = vector<int>(k);
for(i = 0;i<k;i++) tree[i] = nums[i];
for(i = k/2;~i;i--) adjust(i,k);
for(i = k;i<n;i++){
if(nums[i] > tree[0]) tree[0] = nums[i], adjust(0,k);
}
return tree[0];
}
};
// api-优先队列
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
priority_queue<int,vector<int>,greater<int>> help;
for(auto &num:nums){
help.push(num);
if(help.size() > k) help.pop();
}
return help.top();
}
};
// 快排
class Solution {
public:
int quick_sort(vector<int>& nums,int x,int y,int k){
if(x == y) return nums[k];
int l = x-1, r = y+1;
auto q = nums[x];
while(l < r){
do l++; while(nums[l] > q);
do r--; while(nums[r] < q);
if(l<r) swap(nums[l],nums[r]);
}
if(k <= r) return quick_sort(nums,x,r,k);
else return quick_sort(nums,r+1,y,k);
}
int findKthLargest(vector<int>& nums, int k) {
return quick_sort(nums,0,nums.size()-1,k-1);
}
};
// 库函数
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
nth_element(nums.begin(),nums.begin()+((int)nums.size() - k),nums.end());
return nums[(int)nums.size() - k];
}
};
2、数据流的中位数【对顶堆】
// 如果数据流中所有整数都在 0 到 100 范围内,你将如何优化你的算法? [计数排序,vector<int>(100)]
// 如果数据流中 99% 的整数都在 0 到 100 范围内,你将如何优化你的算法? [计数排序,增开[-INT_max,0)与(101,INT_max]]
class MedianFinder {
public:
/** initialize your data structure here. */
priority_queue<int> big;
priority_queue<int,vector<int>,greater<int>> small;
MedianFinder() {
}
void addNum(int num) {
if(big.empty() || num <= big.top())
big.push(num);
else small.push(num);
if(big.size() == small.size() + 2){
auto t = big.top(); big.pop();
small.push(t);
}else if(small.size() == big.size()+1){
auto t = small.top(); small.pop();
big.push(t);
}
}
double findMedian() {
if(big.size() == small.size()) return (big.top()+small.top())/2.0;
else return big.top();
}
};
3、滑动窗口中位数 【对顶堆】
class Solution {
public:
multiset<int> left,right;
int k;
double find_m(){
if(k%2) return *right.begin();
else return ((double)*left.rbegin() + *right.begin())/2;
}
vector<double> medianSlidingWindow(vector<int>& nums, int k_) {
k = k_;
vector<double> ans;
for(int i = 0;i<k;i++) right.insert(nums[i]);
for(int i = 0;i<k/2;i++) {
auto t = *right.begin();
left.insert(t);
right.erase(right.find(t));
}
ans.push_back(find_m());
for(int i=k;i<nums.size();i++){
auto a = nums[i], b = nums[i-k];
if(a >= *right.begin()) right.insert(a);
else left.insert(a);
if(right.find(b) != right.end()){
right.erase(right.find(b));
}else left.erase(left.find(b));
while(right.size() > left.size() + 1){ // 此处有别于第二题
a = *right.begin();
right.erase(right.find(a));
left.insert(a);
}
while(left.size() > right.size()){ // 此处有别于第二题
a = *left.rbegin();
left.erase(left.find(a));
right.insert(a);
}
ans.push_back(find_m());
}
return ans;
}
};
4、前 K 个高频元素
class Solution {
public:
static bool mycmp(const pair<int,int> &a,const pair<int,int> & b) {
return a.second > b.second;
}
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int,int> m;
for(auto &num:nums) m[num]++;
vector<pair<int,int>> t(m.begin(),m.end());
sort(t.begin(),t.end(),mycmp);
vector<int> ans;
while(k--){
ans.push_back(t[k].first);
}
return ans;
}
};
5、查找和最小的K对数字【多路归并】
class Solution {
public:
typedef pair<int,int> pii;
vector<vector<int>> kSmallestPairs(vector<int>& a, vector<int>& b, int k) {
vector<vector<int>> ans;
priority_queue<pii,vector<pii>,greater<pii>> help;
for(int j=0;j<b.size();j++) help.push(make_pair(a[0]+b[j],0));
while(k-- && help.size()){
auto t = help.top(); help.pop();
ans.push_back({a[t.second],t.first - a[t.second]});
if(t.second+1 < a.size())
help.push(make_pair(t.first - a[t.second] + a[t.second+1],t.second+1));
}
return ans;
}
};
6、根据字符出现频率排序【topK】
class Solution {
public:
typedef pair<int,char> pic;
string frequencySort(string s) {
unordered_map<char,int> hash;
for(auto c:s) hash[c]++;
priority_queue<pic> t;
for(auto &c:hash){
t.push(make_pair(c.second,c.first));
}
string ans;
while(t.size()){
auto c = t.top();
while(c.first--)
ans += c.second;
t.pop();
}
return ans;
}
};
[Go Back~~](# LeetCode题解)
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。