897已经做过一遍,成功AC,可是在我用C++编写算法的时候遇到了一些问题。真是用C的毛病改不了啊。
- 我的题解
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) {}
};
//vector<TreeNode*> mynode = vector<TreeNode*>(101);
//vector<TreeNode> mynode (101,TreeNode());
vector<TreeNode> mynode;
int count = 0;
void zhongxubianli(TreeNode* root){
if (root != NULL){
zhongxubianli(root->left);
mynode.push_back(TreeNode(root->val));
count++;
zhongxubianli(root->right);
}
}
void adjust(vector<TreeNode> mynode){
for (int i = 0; i < count-1; ++i) {
mynode[i].right = &mynode[i+1];
}
}
TreeNode* increasingBST(TreeNode* root) {
zhongxubianli(root);
adjust(mynode);
return &mynode[0];
}
首先,我第一次见到了结构体的构造函数,这个我没学过,用stl和string做题的我第一次遇到了没见过的C++基础语法。其次,我使用了和C一样的编程思维,却报错Address Sanitizer
。我检查了N次都没发现容器越界。
这里简述一下编程思想:
1、创建容器,创建计数器,因为在进行push_back的时候无法自动计数(靠貌似有size方法,无所谓了,都差不多)
2、中序遍历方法,在两个左右操作中间加上push_back,稳稳的。其实是先创建一个结点val赋值为当前root的val,再将当前结点装入容器。
3、容器中的结点是val有序,因为是按照中序遍历装入的,只需要按照顺序利用for循环进行指向就可以了
4、结束
我觉得任何一个环节都没毛病,可就是越界了,这个先放在这里,我先看看大佬的递归思想
- 大佬的题解
/**
* 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:
TreeNode* prev;
void dfs(TreeNode* curr)
{
if (curr != nullptr)
{
dfs(curr->left);
// prev的left无需设置,因为每次插入前已设置
prev->right = curr;
// 一定要把当前left置为空,避免野指针造成后续遍历会异常
curr->left = nullptr;
prev = curr;
dfs(curr->right);
}
}
public:
TreeNode* increasingBST(TreeNode* root) {
// 预留一个空结点,它的right就是我们的需要返回的结果
TreeNode* dummyRoot = new TreeNode(-1);
prev = dummyRoot;
dfs(root);
return dummyRoot->right;
}
};
//作者:ffreturn
作者只创建了一个额外空间给初始点用,即prev
1、prev为全局指针指向一个初始结点
2、在中序遍历过程中先让prev->right
指向最小的数对应的结点,在这个由小到大的遍历过程中一定要让所有的prev->left
为null,不然在之后的返回答案过程中可能会出现环。
3、prev虽说是全局变量,初始化是在main函数中,且答案的开始是从prev->right
开始,这从初始化时候的TreeNode* dummyRoot = new TreeNdoe(-1)
就能看出来,因为所给搜索二叉树val中不存在负数,这个prev也只是一个开始标识的作用。