【数据结构与算法-二分搜索与二叉查找(排序)树相关经典例题汇总】

基础知识

  • 二分查找

在这里插入图片描述

  • 问题偏向于分治-可用循环的方法
  • 问题涉及回溯概念-可用递归的方法

典例1、插入位置(easy)

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int index = -1; // 最终返回的下标,找到,则为该元素下标,否则为需要插入的位置
        int begin = 0; // 搜索区间左端
        int end = nums.size()-1; // 搜索区间右端
        while(index == -1){  //若index 持续为-1 ,说明找不到,继续二分搜索
            int mid = ( begin + end )/2;  // 计算中心位置
            if(target == nums[mid]){  // 找到target
                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;

    }
};
  • 可本地运行测试的完整代码:


典例2、区间查找(medium)


class Solution {
public:
    std::vector<int> searchRange(std::vector<int>& nums, int target) {
        std::vector<int> result;
        result.push_back(left_bound(nums, target));
        result.push_back(right_bound(nums, target));
        return result;
    }
private:

    int left_bound(std::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 || nums[mid -1] < target){
                    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(std::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 || nums[mid + 1] > target){
                    return mid;
                }
                begin = mid + 1;
            }
            else if (target < nums[mid]){
                end = mid - 1;
            }
            else if (target > nums[mid]){
                begin = mid + 1;
            }
        }
        return -1;
    }
};
  • 可本地运行测试的完整代码:


典例3、旋转数组查找(medium)

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]){ // 如 【7,9,12,15,20,1,3,6】查找【7,8,9,10】查找【1,2,3】
                    if(target>=nums[begin]){ // 递增区间为【begin,mid-1】,旋转区间为【mid+1,end】

                        end = mid-1;
                    }
                    else {    // 如 【20,1,3,6,7,9,12,15,】查找【1,2,3】
                        begin = mid +1;  // 否则,递增区间为【mid+1,end】,旋转区间为【begin,mid-1】
                    }
                }
                else if(nums[begin]>nums[mid]){// 如 【20,1,3,6,7,9,12,15,】查找【1,2,3】
                    end = mid - 1;
                }
                else if(nums[begin]==nums[mid]){ // 说明 目标只可能在【mid+1,end】之间 ,如 target = 1,数组【6,1】
                    begin = mid +1;
                }
            }
            else if(target>nums[mid]){      // 递增区间为【begin,mid-1】,旋转区间为【mid+1,end】
                if(nums[begin]<nums[mid]){ //  如 【7,9,12,15,20,1,3,6】查找【17,18,19,110】
                    begin = mid +1;
                }
                else if(nums[begin]>nums[mid]){ // 递增区间为【mid+1,end】,旋转区间为【begin,mid-1】
                    if(target>=nums[begin]){    //如 【15,20,1,3,6,7,9,12】查找【17,18,19,110】
                        end = mid-1;
                    }
                    else{begin = mid+1;}     //如 【15,20,1,3,6,7,9,12】查找【4,5,6,7】
                }
                else if(nums[begin]==nums[mid]){  //  如 【6,7】查找【7】
                    begin = mid +1;
                }
            }
        }
        return -1;
    }
};
  • 可本地运行测试的完整代码:


典例4、二叉查找树编码与解码(medium)

  • 基础知识:

  • 1、二叉查找树查插入节点在这里插入图片描述在这里插入图片描述

  • 2、二叉查找树查找数值
    在这里插入图片描述

  • 3、二叉查找树前序遍历与复原

在这里插入图片描述

  • 题目描述:
    在这里插入图片描述
  • 思路:
    在这里插入图片描述
  • 字符串与数值类型的转换:

在这里插入图片描述


  • 可本地运行测试的完整代码:

#include <stdio.h>


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

#include <string>
#include <vector>

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, std::string &str_val){
	std::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 += '#';
}

void BST_preorder(TreeNode *node, std::string &data){
	if (!node){
		return;
	}
	std::string str_val;
	change_int_to_string(node->val, str_val);
	data += str_val;
	BST_preorder(node->left, data);
	BST_preorder(node->right, data);
}

class Codec {
public:
    std::string serialize(TreeNode* root) {
    	std::string data;
        BST_preorder(root, data);
        return data;
    }
    TreeNode *deserialize(std::string data) {
    	if (data.length() == 0){
	    	return NULL;
	    }
    	std::vector<TreeNode *> node_vec;
    	int val = 0;
    	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];
    }
};

void preorder_print(TreeNode *node,int layer){
	if (!node){
		return;
	}
	for (int i = 0; i < layer; i++){
		printf("-----");
	}
	printf("[%d]\n", node->val);
	preorder_print(node->left, layer + 1);
	preorder_print(node->right, layer + 1);
}

int main(){
	TreeNode a(8);
	TreeNode b(3);
	TreeNode c(10);
	TreeNode d(1);
	TreeNode e(6);
	TreeNode f(15);	
	a.left = &b;
	a.right = &c;
	b.left = &d;
	b.right = &e;
	c.left = &f;	
	Codec solve;	
	std::string data = solve.serialize(&a);
	printf("%s\n", data.c_str());
	TreeNode *root = solve.deserialize(data);
	preorder_print(root, 0);	
	return 0;
}

典例5、逆序数(hard)


  • 可本地运行测试的完整代码:
#include <stdio.h>

#include <vector>
struct BSTNode {
	int val;
	int count;
	BSTNode *left;
	BSTNode *right;
	BSTNode(int x) : val(x), left(NULL), right(NULL), count(0) {}
};

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

class Solution {
public:
    std::vector<int> countSmaller(std::vector<int>& nums) {
    	std::vector<int> result;
    	std::vector<BSTNode *> node_vec;
    	std::vector<int> count;
    	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;
    		BST_insert(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;
    }
};

int main(){
	int test[] = {5, -7, 9, 1, 3, 5, -2, 1};
	std::vector<int> nums;
	for (int i = 0; i < 8; i++){
		nums.push_back(test[i]);
	}
	Solution solve;
	std::vector<int> result = solve.countSmaller(nums);
	for (int i = 0; i < result.size(); i++){
		printf("[%d]", result[i]);
	}
	printf("\n");
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值