数据结构与算法——二分查找与二叉排序树

1.预备知识

1.1 题目目录

在这里插入图片描述

1.2 二分查找

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

1.3 递归二分查找
bool binary_search(vector<int>& sort_array, int begin, int end, int target) {
    if (begin>end) {
        return false;
    }

    int mid = (begin + end) / 2;
    
    if (target == sort_array[mid]) {
        return true;
    }
    else if (target < sort_array[mid]) {
        binary_search(sort_array, begin, mid - 1, target);
    }
    else if (target > sort_array[mid]) {
        binary_search(sort_array, mid + 1, end, target);
    }
}
1.4 循环二分查找
bool binary_search(vector<int>& sort_array, int target) {
    int begin = 0;
    int end = sort_array.size() - 1;

    while (begin<=end) {
        int mid = (begin + end) / 2;
        if (target == sort_array[mid]) {
            return true;
        }
        else if(target < sort_array[mid]) {
            end = mid - 1;
        }
        else if (target > sort_array[mid]) {
            begin = mid + 1;
        }
    }

    return false;
}
1.5 二叉查找(排序)树

在这里插入图片描述
在这里插入图片描述

1.6 二叉搜索树的代码实现

1.二叉搜索树的插入

void solution::BST_insert(TreeNode* node, TreeNode* insert_node) {
	if (insert_node->val < node->val) {
		if (node->left) {
			BST_insert(node->left, insert_node);
		}
		else {
			node->left = insert_node;
		}
	}
	else {
		if (node->right) {
			BST_insert(node->right, insert_node);
		}
		else {
			node->right = insert_node;
		}
	}
}

2.二叉搜索树的搜索

bool solution::BST_search(TreeNode* node, int value) {
	if (value == node->val) {
		return true;
	}
	else if (value < node->val) {
		if (node->left) {
			BST_search(node->left, value);
		}
		else {
			return false;
		}
	}
	else if (value > node->val) {
		if (node->right) {
			BST_search(node->right, value);
		}
		else {
			return false;
		}
	}
}

2.搜索插入位置

2.1 题目描述

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

你可以假设数组中无重复元素。

2.2 C++代码实现
class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int begin=0;
        int end=nums.size()-1;
        int index=-1;

        while(index==-1){
            int mid=(begin+end)/2;

            if(target==nums[mid]){
                index=mid;
            }
            else if(target<nums[mid]){
                if(mid==0||target>nums[mid-1]){
                    index=mid;
                }
                end=mid-1;
            }
            else if(target>nums[mid]){
                if(mid==nums.size()-1||target<nums[mid+1]){
                    index= mid+1;
                }
                begin=mid+1;
            }
        }
        return index;
    }
};

3.区间查找

3.1 题目描述

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]。

3.2 算法思路

在这里插入图片描述在这里插入图片描述

3.3 C++代码实现
class Solution {
public:
    int left_bound(vector<int>& nums,int target){
        int begin=0;
        int end=nums.size()-1;

        while(begin<=end){
            int mid=(begin+end)/2;
            if(target==nums[mid]){
                if(mid==0||target>nums[mid-1]){
                    return mid;
                }
                end=mid-1;
            }
            else if(target<nums[mid]){
                end=mid-1;
            }
            else if(target>nums[mid]){
                begin=mid+1;
            }
        }
        return -1;

    }
        int right_bound(vector<int>& nums,int target){
        int begin=0;
        int end=nums.size()-1;

        while(begin<=end){
            int mid=(begin+end)/2;
            if(target==nums[mid]){
                if(mid==nums.size()-1||target<nums[mid+1]){
                    return mid;
                }
                begin=mid+1;
            }
            else if(target<nums[mid]){
                end=mid-1;
            }
            else if(target>nums[mid]){
                begin=mid+1;
            }
        }
        return -1;

    }
    vector<int> searchRange(vector<int>& nums, int target) {
        int left=left_bound(nums,target);
        int right=right_bound(nums,target);

        vector<int> result;
        result.push_back(left);
        result.push_back(right);
        return result;
    }
};

4.旋转数组查找

4.1 题目描述

整数数组 nums 按升序排列,数组中的值 互不相同 。

在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。

给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。

4.2 解题思路

在这里插入图片描述
在这里插入图片描述

4.3 C++代码实现
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int begin=0;
        int end=nums.size()-1;

        while(begin<=end){
            int mid=(begin+end)/2;
            if(target==nums[mid]){
                return mid;
            }
            else if(target<nums[mid]){
                if(nums[begin]<nums[mid]){
                    if(target>=nums[begin]){
                        end=mid-1;
                    }
                    else{
                        begin=mid+1;
                    }
                }
                else if(nums[begin]>nums[mid]){
                    end=mid-1;
                }
                else if(nums[begin]==nums[mid]){
                    begin=mid+1;
                }
            }
            else if(target>nums[mid]){
                if(nums[begin]<nums[mid]){
                    begin=mid+1;
                }
                else if(nums[begin]>nums[mid]){
                    if(target>=nums[begin]){
                        end=mid-1;
                    }
                    else{
                        begin=mid+1;
                    }
                }
                else if(nums[begin]==nums[mid]){
                    begin=mid+1;
                }
            }
        }
        return -1;
    }
};

5.序列化和反序列化二叉搜索树

5.1 题目描述

序列化是将数据结构或对象转换为一系列位的过程,以便它可以存储在文件或内存缓冲区中,或通过网络连接链路传输,以便稍后在同一个或另一个计算机环境中重建。

设计一个算法来序列化和反序列化 二叉搜索树 。 对序列化/反序列化算法的工作方式没有限制。 您只需确保二叉搜索树可以序列化为字符串,并且可以将该字符串反序列化为最初的二叉搜索树。

编码的字符串应尽可能紧凑。

5.2 算法思路

在这里插入图片描述
在这里插入图片描述

5.3 C++代码实现
class Codec {
public:
    void BST_insert(TreeNode* node, TreeNode* insert_node) {
        if (insert_node->val < node->val) {
            if (node->left) {
                BST_insert(node->left, insert_node);
            }
            else {
                node->left = insert_node;
            }
        }
        else {
            if (node->right) {
                BST_insert(node->right, insert_node);
            }
            else {
                node->right = insert_node;
            }
        }
    }
    void change_int_to_string(int val, string& str_val) {
        string tmp;
        while (val) {
            tmp += val % 10 + '0';
            val = val / 10;
        }
        for (int i = tmp.length()- 1; i >= 0; i--) {
            str_val += tmp[i];
        }
        str_val += '#';
    }
	/*9.2 将二叉查找树按照前序遍历的方式,转化为字符串,数字之间使用#隔开*/
    void BST_preorder(TreeNode* node, string& data) {
        if (!node) {
            return;
        }
        string str_val;
        change_int_to_string(node->val, str_val);
        data += str_val;
        BST_preorder(node->left, data);
        BST_preorder(node->right, data);
    }
    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
         string data;
         BST_preorder(root,data);
         return data;   
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
          int val=0;
          vector<TreeNode*> node_vec;

          if(data.length()==0){
              return NULL;
          } 

          for(int i=0;i<data.length();i++){
              if(data[i]=='#'){
                  node_vec.push_back(new TreeNode(val));
                  val=0;
              }
              else{
                  val=val*10+(data[i]-'0');
              }
          }

         for(int i=1;i<node_vec.size();i++){
             BST_insert(node_vec[0],node_vec[i]);
         }
         return node_vec[0];
    }
};

6.计算右侧小于当前元素的个数

6.1 题目描述

给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量。

示例:
输入:nums = [5,2,6,1]
输出:[2,1,1,0]
解释:
5 的右侧有 2 个更小的元素 (2 和 1)
2 的右侧仅有 1 个更小的元素 (1)
6 的右侧有 1 个更小的元素 (1)
1 的右侧有 0 个更小的元素

6.2 算法思路

在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述

6.3 C++代码实现
struct BSTNode{
    int val;
    int count;
    BSTNode* left;
    BSTNode* right;
    BSTNode(int x):val(x),count(0),left(NULL),right(NULL){}
};

class Solution {
public:
    void BSTInsert(BSTNode* node,BSTNode* insert_node,int& count_small){
        if(insert_node->val<=node->val){
            node->count++;
            if(node->left){
                BSTInsert(node->left,insert_node,count_small);
            }
            else{
                node->left=insert_node;
            }
        }
        else{
            count_small+=node->count+1;
            if(node->right){
                BSTInsert(node->right,insert_node,count_small);
            }
            else{
                node->right=insert_node;
            }
        }
    }

    vector<int> countSmaller(vector<int>& nums) {
        vector<int> result;
        vector<int> count;
        vector<BSTNode*> node_vec;

        for(int i=nums.size()-1;i>=0;i--){
            node_vec.push_back(new BSTNode(nums[i]));
        }

        count.push_back(0);
        for(int i=1;i<node_vec.size();i++){
            int count_small=0;
            BSTInsert(node_vec[0],node_vec[i],count_small);
            count.push_back(count_small);
        }

        for(int i=node_vec.size()-1;i>=0;i--){
            delete node_vec[i];
            result.push_back(count[i]);
        }
        return result;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值