力扣刷题之深度优先搜索
98.验证二叉搜索树
法一:递归
class Solution {
public:
bool helper(TreeNode* root, long long lower, long long upper) {
if (root == nullptr) {
return true;
}
if (root -> val <= lower || root -> val >= upper) {
return false;
}
return helper(root -> left, lower, root -> val) && helper(root -> right, root -> val, upper);
}
bool isValidBST(TreeNode* root) {
return helper(root, LONG_MIN, LONG_MAX);
}
};
法二:中序遍历
class Solution {
TreeNode* pre = NULL;
public:
bool isValidBST(TreeNode* root) {
if(root == NULL) return true;
if(!isValidBST(root->left)) return false;
if(pre != NULL && root->val <= pre->val) return false;
pre = root; //记录中序遍历的上一个节点
if(!isValidBST(root->right)) return false;
return true;
}
};
99.恢复二叉搜索树
中序遍历过程中,记录错误两个错误排序节点,最后进行交换
class Solution {
TreeNode t1, t2, pre;
public void recoverTree(TreeNode root) {
inorder(root);
int temp = t1.val;
t1.val = t2.val;
t2.val = temp;
}
public void inorder(TreeNode root){
if (root == null) return ;
inorder(root.left);
if (pre != null && pre.val > root.val) {
if (t1 == null) t1 = pre;
t2 = root;
}
pre = root;
inorder(root.right);
}
}
113.路径总和II
法一:回溯
/**
* 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>> ans;
vector<int> t;
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
if(!root)return ans;
t.push_back(root->val);
dfs(root,root->val,targetSum);
return ans;
}
void dfs(TreeNode* root,int add,int targetSum){
if(!root->left && !root->right && add==targetSum){
ans.push_back(t);
return;
}
if(root->left){
t.push_back(root->left->val);
dfs(root->left,add+root->left->val,targetSum);
t.pop_back();
}
if(root->right){
t.push_back(root->right->val);
dfs(root->right,add+root->right->val,targetSum);
t.pop_back();
}
}
};
法二:递归
class Solution {
public:
vector<vector<int>> ret;
vector<int> path;
void dfs(TreeNode* root, int targetSum) {
if (root == nullptr) {
return;
}
path.emplace_back(root->val);
targetSum -= root->val;
if (root->left == nullptr && root->right == nullptr && targetSum == 0) {
ret.emplace_back(path);
}
dfs(root->left, targetSum);
dfs(root->right, targetSum);
path.pop_back();
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
dfs(root, targetSum);
return ret;
}
};
114.二叉树展开为链表
法一:前序遍历
class Solution {
public:
void flatten(TreeNode* root) {
vector<TreeNode*> l;
preorderTraversal(root, l);
int n = l.size();
for (int i = 1; i < n; i++) {
TreeNode *prev = l.at(i - 1), *curr = l.at(i);
prev->left = nullptr;
prev->right = curr;
}
}
void preorderTraversal(TreeNode* root, vector<TreeNode*> &l) {
if (root != NULL) {
l.push_back(root);
preorderTraversal(root->left, l);
preorderTraversal(root->right, l);
}
}
};
116.填充每个节点的下一个右侧节点指针
class Solution {
public:
Node* connect(Node* root) {
if (root == nullptr) {
return root;
}
// 从根节点开始
Node* leftmost = root;
while (leftmost->left != nullptr) {
// 遍历这一层节点组织成的链表,为下一层的节点更新 next 指针
Node* head = leftmost;
while (head != nullptr) {
// CONNECTION 1
head->left->next = head->right;
// CONNECTION 2
if (head->next != nullptr) {
head->right->next = head->next->left;
}
// 指针向后移动
head = head->next;
}
// 去下一层的最左的节点
leftmost = leftmost->left;
}
return root;
}
};
117.填充每个节点的下一个右侧节点指针II
class Solution {
public:
Node* connect(Node* root) {
if(!root){
return nullptr;
}
queue<Node*>q;//按层存储树的结点
Node* cur=root;
q.push(root);
int n=1;//指示当层结点尚未遍历的结点个数
while(!q.empty()){
q.pop();
n--;
if(cur->left){
q.push(cur->left);
}
if(cur->right){
q.push(cur->right);
}
if(n==0){//n=0时,表示该层遍历完毕
cur->next=nullptr;
n=q.size();
}
else{
cur->next=q.front();
}
cur=q.front();
}
return root;
}
};
129.求根节点到叶节点数字之和
class Solution {
public:
int dfs(TreeNode* root, int prevSum) {
if (root == nullptr) {
return 0;
}
int sum = prevSum * 10 + root->val;
if (root->left == nullptr && root->right == nullptr) {
return sum;
} else {
return dfs(root->left, sum) + dfs(root->right, sum);
}
}
int sumNumbers(TreeNode* root) {
return dfs(root, 0);
}
};
199.二叉树的右视图
层序遍历 队列 取最右值
vector<int> rightSideView(TreeNode* root) {
vector<int> res;
if (!root) return res;
queue<TreeNode*> q;
q.push(root);
while (!q.empty())
{
int size = q.size();
res.push_back(q.front()->val);
while (size--)
{
TreeNode* temp = q.front();
q.pop();
if (temp->right) q.push(temp->right);
if (temp->left) q.push(temp->left);
}
}
return res;
}
207.课程表
拓扑排序 判断是否存在有向环
class Solution {
private:
vector<vector<int>> edges;
vector<int> indeg;
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
edges.resize(numCourses);
indeg.resize(numCourses);
for (const auto& info: prerequisites) {
edges[info[1]].push_back(info[0]);
++indeg[info[0]];
}
queue<int> q;
for (int i = 0; i < numCourses; ++i) {
if (indeg[i] == 0) {
q.push(i);
}
}
int visited = 0;
while (!q.empty()) {
++visited;
int u = q.front();
q.pop();
for (int v: edges[u]) {
--indeg[v];
if (indeg[v] == 0) {
q.push(v);
}
}
}
return visited == numCourses;
}
};
210.课程表II
class Solution {
private:
// 存储有向图
vector<vector<int>> edges;
// 存储每个节点的入度
vector<int> indeg;
// 存储答案
vector<int> result;
public:
vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
edges.resize(numCourses);
indeg.resize(numCourses);
for (const auto& info: prerequisites) {
edges[info[1]].push_back(info[0]);
++indeg[info[0]];
}
queue<int> q;
// 将所有入度为 0 的节点放入队列中
for (int i = 0; i < numCourses; ++i) {
if (indeg[i] == 0) {
q.push(i);
}
}
while (!q.empty()) {
// 从队首取出一个节点
int u = q.front();
q.pop();
// 放入答案中
result.push_back(u);
for (int v: edges[u]) {
--indeg[v];
// 如果相邻节点 v 的入度为 0,就可以选 v 对应的课程了
if (indeg[v] == 0) {
q.push(v);
}
}
}
if (result.size() != numCourses) {
return {};
}
return result;
}
};
211.添加与搜索单词-数据结构设计
class TrieNode{
public:
vector<TrieNode*> child;
bool isWord;
TrieNode() : child(26, nullptr), isWord(false) {};
~TrieNode() {
for (auto c : child) delete c;
}
};
class WordDictionary {
public:
/** Initialize your data structure here. */
WordDictionary() {
root = new TrieNode();
}
~WordDictionary() {
delete root;
}
/** Adds a word into the data structure. */
void addWord(string word) {
TrieNode* p = root;
for (char c : word) {
int i = c - 'a';
if (!p->child[i])
p->child[i] = new TrieNode();
p = p->child[i];
}
p->isWord = true;
}
/** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
bool search(string word) {
return match(word, root, 0);
}
bool match(string& word, TrieNode* p, int start) {
if (!p) return false;
if (start == word.size()) return p->isWord;
char c = word[start];
if (c != '.') {
return match(word, p->child[c - 'a'], start + 1);
} else {
for (const auto& child : p->child) {
if (match(word, child, start + 1))
return true;
}
}
return false;
}
private:
TrieNode* root;
};
/**
* Your WordDictionary object will be instantiated and called as such:
* WordDictionary obj = new WordDictionary();
* obj.addWord(word);
* bool param_2 = obj.search(word);
*/
222.完全二叉树的节点个数
二分+位运算
class Solution {
public:
int countNodes(TreeNode* root) {
if (root == nullptr) {
return 0;
}
int level = 0;
TreeNode* node = root;
while (node->left != nullptr) {
level++;
node = node->left;
}
int low = 1 << level, high = (1 << (level + 1)) - 1;
while (low < high) {
int mid = (high - low + 1) / 2 + low;
if (exists(root, level, mid)) {
low = mid;
} else {
high = mid - 1;
}
}
return low;
}
bool exists(TreeNode* root, int level, int k) {
int bits = 1 << (level - 1);
TreeNode* node = root;
while (node != nullptr && bits > 0) {
if (!(bits & k)) {
node = node->left;
} else {
node = node->right;
}
bits >>= 1;
}
return node != nullptr;
}
};
230.二叉搜索树中第K小的元素
中序遍历
class Solution {
public:
int kthSmallest(TreeNode* root, int k) {
stack<TreeNode *> stack;
while (root != nullptr || stack.size() > 0) {
while (root != nullptr) {
stack.push(root);
root = root->left;
}
root = stack.top();
stack.pop();
--k;
if (k == 0) {
break;
}
root = root->right;
}
return root->val;
}
};
236.二叉树的最近公共祖先
深度优先搜索+哈希表
class Solution {
public:
unordered_map<int, TreeNode*> fa;
unordered_map<int, bool> vis;
void dfs(TreeNode* root){
if (root->left != nullptr) {
fa[root->left->val] = root;
dfs(root->left);
}
if (root->right != nullptr) {
fa[root->right->val] = root;
dfs(root->right);
}
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
fa[root->val] = nullptr;
dfs(root);
while (p != nullptr) {
vis[p->val] = true;
p = fa[p->val];
}
while (q != nullptr) {
if (vis[q->val]) return q;
q = fa[q->val];
}
return nullptr;
}
};
297.二叉树的序列化与反序列化
class Codec {
public:
void rserialize(TreeNode* root, string& str) {
if (root == nullptr) {
str += "None,";
} else {
str += to_string(root->val) + ",";
rserialize(root->left, str);
rserialize(root->right, str);
}
}
string serialize(TreeNode* root) {
string ret;
rserialize(root, ret);
return ret;
}
TreeNode* rdeserialize(list<string>& dataArray) {
if (dataArray.front() == "None") {
dataArray.erase(dataArray.begin());
return nullptr;
}
TreeNode* root = new TreeNode(stoi(dataArray.front()));
dataArray.erase(dataArray.begin());
root->left = rdeserialize(dataArray);
root->right = rdeserialize(dataArray);
return root;
}
TreeNode* deserialize(string data) {
list<string> dataArray;
string str;
for (auto& ch : data) {
if (ch == ',') {
dataArray.push_back(str);
str.clear();
} else {
str.push_back(ch);
}
}
if (!str.empty()) {
dataArray.push_back(str);
str.clear();
}
return rdeserialize(dataArray);
}
};