leetcode--二分查找和二分排序

基础知识

二分法有三种情况:
1、找到那个数的位置(只需要找到其中一个)
2、找左边界
3、找右边界
通用模板:

int binary_search(int[] nums, int target) {
    int left = 0, right = nums.length - 1; 
    while(left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid - 1; 
        } else if(nums[mid] == target) {
            // 直接返回
            return mid;
        }
    }
    // 直接返回
    return -1;
}

int left_bound(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid - 1;
        } else if (nums[mid] == target) {
            // 别返回,锁定左侧边界
            right = mid - 1;
        }
    }
    // 最后要检查 left 越界的情况
    if (left >= nums.length || nums[left] != target)
        return -1;
    return left;
}

int right_bound(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid - 1;
        } else if (nums[mid] == target) {
            // 别返回,锁定右侧边界
            left = mid + 1;
        }
    }
    // 最后要检查 right 越界的情况
    if (right < 0 || nums[right] != target)
        return -1;
    return right;
}

二分查找(递归)代码

#include <vector>
using namesape std;
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]){
		return binary_search(sort_array,begin,mid-1,target);
	}
	else if(target>sort_array[mid]){
		return binary_search(sort_array,mid+1,end,target);
	}
}

二分查找(循环)代码

bool binary_search(std::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;
}

leetcode题目

##3 5. Search Insert Position

题意:

给出一个递增序列,和一个target数字,找到这个数字在递增序列中的插入位置,使插入之后还是有序。

解题思路:

普通的二分查找,要注意边界条件。

代码:

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(nums[mid]==target){
                index=mid;
            }
            else if(nums[mid]>target){
                if(mid==0||target>nums[mid-1]){   //注意边界的情况 
                    index=mid;
                }
                end=mid-1;
            }
            else if(nums[mid]<target){
                if(mid==nums.size()-1||target<nums[mid-1]){  //注意边界的情况
                    index=mid+1;
                }
                begin=mid+1;   
            }
        }
        return index;
    }
};

34. Search for a Range

题意:

递增序列中的元素可能重复,找到target在递增序列中的range,如果不存在输出[-1,-1]

解题思路:

用两个二分查找,分别找出左界限和右界限。

代码:

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

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


class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        vector<int> result;
        result.push_back(searchLeft(nums,target));
        result.push_back(searchRight(nums,target));
        return result;
        }
    };

33. Search in Rotated Sorted Array

题意:

在一个旋转数组中找目标元素。

解题思路:

分情况讨论的二分查找,变成一部分是顺序数组,一部分是旋转数组,每次判断是在顺序数组中还是旋转数组中,注意一些等于的边界情况。

代码:

class Solution {
public:
int search(vector& 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 if(target < nums[begin]){
begin = mid + 1;
}
}
else if(nums[begin] < nums[mid]){
begin = mid + 1;
}
else if(nums[begin] == nums[mid]){
begin = mid + 1;
}

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

};

基础知识

二叉排序树数据结构:

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

二叉排序树数据查找:

用递归的方法搜索:

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

##二叉排序树数据插入:
也是用递归的方法,当子树空就插入,不空就递归的向子树搜索

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;
		}
	}
}

Leetcode 题目

449. Serialize and Deserialize BST

题意:

给定一个二叉树,写出编码和解码的方法。
编码:将二叉树转为字符串
解码:将字符串转为二叉树

解题思路:

1、前序遍历保留二叉树,然后用特殊符号#隔开
2、遍历字符串,用二叉树的插入方法重建二叉树
建立时候的基础知识:
1、数字变字符串,用mod 10取余再反转的方法。
2、字符串变数字,用*10+x来还原,

代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
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 += '#';
}

//根节点,插入节点
void BST_insert(TreeNode *node, TreeNode *insert_node){
    if (node->val > insert_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 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);
}

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

// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));

315. Count of Smaller Numbers After Self

题意:

输入一个数组a,返回一个相同size的数组b,b中每个元素是a中该位置的元素后面比该元素小的元素个数。

解题思路:

先将数组逆置,逐个插入数组到一个二叉搜索树中,相当于维护一个带左子树个数的二叉搜索树。

代码

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;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值