C/C++【备用题】二叉搜索树迭代器 | 验证二叉搜索树

 1. 二叉搜索树迭代器

实现一个二叉搜索树迭代器类BSTIterator ,表示一个按中序遍历二叉搜索树(BST)的迭代器:

  • BSTIterator(TreeNode root) 初始化 BSTIterator 类的一个对象。BST 的根节点 root 会作为构造函数的一部分给出。指针应初始化为一个不存在于 BST 中的数字,且该数字小于 BST 中的任何元素。
  • boolean hasNext() 如果向指针右侧遍历存在数字,则返回 true ;否则返回 false 。
  • int next()将指针向右移动,然后返回指针处的数字。

注意,指针初始化为一个不存在于 BST 中的数字,所以对 next() 的首次调用将返回 BST 中的最小元素。

你可以假设 next() 调用总是有效的,也就是说,当调用 next() 时,BST 的中序遍历中至少存在一个下一个数字。

示例:

输入
["BSTIterator", "next", "next", "hasNext", "next", "hasNext", "next", "hasNext", "next", "hasNext"]
[[[7, 3, 15, null, null, 9, 20]], [], [], [], [], [], [], [], [], []]
输出
[null, 3, 7, true, 9, true, 15, true, 20, false]
解释 
BSTIterator bSTIterator = new BSTIterator([7, 3, 15, null, null, 9, 20]); 
bSTIterator.next(); // 返回 3 
bSTIterator.next(); // 返回 7 
bSTIterator.hasNext(); // 返回 True 
bSTIterator.next(); // 返回 9 
bSTIterator.hasNext(); // 返回 True 
bSTIterator.next(); // 返回 15 
bSTIterator.hasNext(); // 返回 True 
bSTIterator.next(); // 返回 20 
bSTIterator.hasNext(); // 返回 False

提示:

  • 树中节点的数目在范围 [1, 10^5] 内
  • 0 <= Node.val <= 10^6
  • 最多调用 10^5 次 hasNext 和 next 操作

进阶:

  • 你可以设计一个满足下述条件的解决方案吗?next() 和 hasNext() 操作均摊时间复杂度为 O(1) ,并使用 O(h) 内存。其中 h 是树的高度。

出处:

https://edu.csdn.net/practice/24633337

代码:

#include null INT_MIN
#include <bits/stdc++.h>
using namespace std;

struct TreeNode
{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

class BSTIterator
{
public:
    BSTIterator(TreeNode *root)
    {
        for (; root != nullptr; root = root->left)
        {
            sti_.push(root);
        }
    }
    /** @return the next smallest number */
    int next()
    {
        TreeNode *smallest = sti_.top();
        sti_.pop();
        int val = smallest->val;
        smallest = smallest->right;
        for (; smallest != nullptr; smallest = smallest->left)
        {
            sti_.push(smallest);
        }
        return val;
    }
    /** @return whether we have a next smallest number */
    bool hasNext()
    {
        return !sti_.empty();
    }
private:
    stack<TreeNode *> sti_;
};
/**
 * Your BSTIterator object will be instantiated and called as such:
 * BSTIterator* obj = new BSTIterator(root);
 * int param_1 = obj->next();
 * bool param_2 = obj->hasNext();
 */

增加一个buildTree() 

int main()
{
	vector<int> nums = {7, 3, 15, null, null, 9, 20};
	BSTIterator bSTIterator = new BSTIterator(root); 
	cout << bSTIterator.next() << endl; // 返回 3 
	cout << bSTIterator.next() << endl; // 返回 7 
	cout << bSTIterator.hasNext() << endl; // 返回 True 
	cout << bSTIterator.next() << endl; // 返回 9 
	cout << bSTIterator.hasNext() << endl; // 返回 True 
	cout << bSTIterator.next() << endl; // 返回 15 
	cout << bSTIterator.hasNext() << endl; // 返回 True 
	cout << bSTIterator.next() << endl; // 返回 20 
	cout << bSTIterator.hasNext() << endl; // 返回 False
  
    return 0;
}

输出:

3. 验证二叉搜索树

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

  • 节点的左子树只包含 小于 当前节点的数。
  • 节点的右子树只包含 大于 当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

示例 1:

输入:root = [2,1,3]
输出:true

示例 2:

输入:root = [5,1,4,null,null,3,6]
输出:false
解释:根节点的值是 5 ,但是右子节点的值是 4 。

提示:

  • 树中节点数目范围在[1, 10^4] 内
  • -2^31 <= Node.val <= 2^31 - 1

以下程序实现了这一功能,请你填补空白处内容:

```c++
#include <bits/stdc++.h>
using namespace std;
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)
    {
        stack<TreeNode *> stk;
        int prev = INT_MIN;
        bool first = true;
        while (!stk.empty() || root != nullptr)
        {
            if (root != nullptr)
            {
                stk.push(root);
                root = root->left;
            }
            else
            {
                root = stk.top();
                stk.pop();
                _______________________;
            }
        }
        return true;
    }
};
```

出处:

https://edu.csdn.net/practice/25116236

代码:

#define null INT_MIN
#include <bits/stdc++.h>
using namespace std;

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)
    {
        stack<TreeNode *> stk;
        int prev = INT_MIN;
        bool first = true;
        while (!stk.empty() || root != nullptr)
        {
            if (root != nullptr)
            {
                stk.push(root);
                root = root->left;
            }
            else
            {
                root = stk.top();
                stk.pop();
				if (!first && prev >= root->val)
				{
				    return false;
				}
				first = false;
				prev = root->val;
				root = root->right;
            }
        }
        return true;
    }
};

TreeNode* buildTree(vector<int>& nums)
{
    if (nums.empty()) return nullptr;
	TreeNode *root = new TreeNode(nums.front());
    queue<TreeNode*> q;
    q.push(root);
    int i = 1;
    while(!q.empty() && i < nums.size())
    {
        TreeNode *cur = q.front();
        q.pop();
        if(i < nums.size() && nums[i] != null)
        {
            cur->left = new TreeNode(nums[i]);
            q.push(cur->left);
        }
        i++;
        if(i < nums.size() && nums[i] != null)
        {
            cur->right = new TreeNode(nums[i]);
            q.push(cur->right);
        }
        i++;
    }
    return root;
}

int main()
{
	Solution s;
	vector<int> nums = {2,1,3};
	TreeNode* root = buildTree(nums);
	cout << (s.isValidBST(root) ? "true" : "false") << endl;

	nums = {5,1,4,null,null,3,6};
	root = buildTree(nums);
	cout << (s.isValidBST(root) ? "true" : "false") << endl;
		
	return 0;
} 

输出:

true
false


寻找旋转排序数组中的最小值 II

已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,4,4,5,6,7] 在变化后可能得到:

  • 若旋转 4 次,则可以得到 [4,5,6,7,0,1,4]
  • 若旋转 7 次,则可以得到 [0,1,4,4,5,6,7]

注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]] 。

给你一个可能存在 重复 元素值的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。

示例 1:

输入:nums = [1,3,5]
输出:1

示例 2:

输入:nums = [2,2,2,0,1]
输出:0

提示:

  • n == nums.length
  • 1 <= n <= 5000
  • -5000 <= nums[i] <= 5000
  • nums 原来是一个升序排序的数组,并进行了 1 至 n 次旋转

进阶:

  • 这道题是 寻找旋转排序数组中的最小值的延伸题目。
  • 允许重复会影响算法的时间复杂度吗?会如何影响,为什么?
#include <bits/stdc++.h>
using namespace std;

class Solution
{
public:
    int findMin(vector<int> &nums)
    {
        int left = 0, right = nums.size() - 1;
        while (left < right)
        {
            int mid = left + (right - left) / 2;
            if (nums[mid] < nums[right])
                right = mid;
            else if (nums[mid] > nums[right])
                left = mid + 1;
            else if (nums[mid] == nums[right])
                right--;
        }
        return nums[right];
    }
};

int main()
{
	Solution s;
	vector<int> nums = {1,3};
	cout << s.findMin(nums) << endl;

	nums = {2,2,2,0,1};
	cout << s.findMin(nums) << endl;
	
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/boysoft2002/article/details/129332515