二分查找与二叉排序树 3/31号

1.二分查找

bool binary_search(std::vector<int> &nums, int key) {
	int begin = 0;
	int end = nums.size()-1;
	int mid = 0;
	while( begin <= end) {
		int mid = (end+begin)/2;
		if(key == nums[mid]) {
			return true;
		}else if(key < nums[mid]) {
			end = mid - 1;
		} else {
			begin = mid +1;
		}
	}
	return false;
}

2 搜索插入位置

/**
 * 搜索插入位置,输出该元素在有序数组中的位置,如果没有,输出该插入的位置,不存在时,主要考虑两个问题,
 * nums[mid] < key < nums[mid+1] || nums[mid] < key && mid == nums.size() -1(到边界了),此时位置? mid +1
 * nums[mid] > key > nums[mid-1] || nums[mid] > key && mid == 0(到边界了),此时位置?mid
 * 
 */

int getPos( std::vector<int> &nums, int key) {
	bool index = -1;
	int begin = 0;
	int end = nums.size() -1;
	int mid = 0;
	while(begin <= end) {
		mid = (end+begin)/2;
		if(nums[mid] == key) {
			return mid;
		} else if(nums[mid] > key) {
			if(mid == 0||key > nums[mid -1]) {
				index = mid;
			}
			end = mid -1;
		} else {
			if (mid == nums.size() -1 || key < nums[mid + 1]) {
				index = mid + 1;
			}
			begin = mid + 1;
		}
	}
	return index;
}

1 查找旋转数组中最小的数字

/**
 *  查找旋转数组中最小的数,主要是看 end与begin差值唯一的时候,END 就是 index,
 *  否则看实在左边还是右边,把 MID 复制给 begin或者 END
 *  
 */
int findMin(vector<int>& nums) {
	int begin = 0;
	int end = nums.size() -1 ;
	int mid = 0;
	int index = -1;
	//循环条件头比尾大
	while(nums[begin] >= nums[end]) {
		if((end - head) == 1) {
			index = end;
			break;
		}
		int mid = (end + begin) >>1;
		if(nums[mid] <= nums[end]) {
			end = mid;
		} else if (nums[mid] >= nums[begin]) {
			begin = mid;
		}
	}
	
	return nums[mid];
}

2 在旋转数组中查找某个数字
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。

/**
 * 旋转数组中查找一个数,看是在左边还是在右边哪边有序,然后再看是不是顺序的子序列
 */
 int search(vector<int>& nums, int target) {
 	int begin =0;
 	int end = nums.size() -1;
 	int mid = 0;
 	int index = -1;
 	
 	while(begin <= end) {
 		mid  = (begin +end) >>1;
 		if(nums[mid] == target) {
 			index = mid;
 			break;
 		}
 		//右边有序
 		if (nums[mid] < nums[end]) {
 			//假设右边是有顺序的同时target落在了有序的部分,begin前提,否则end落下来
 			 if(target > nums[mid] && target <= nums[end]) {
 			 	begin = mid +1;
 			 } else{
 			 	end = mid -1;
 			 }
 		} else {
 			//否则,左边有序,同时 target 落在了有序部分,end落下来,否则 begin 上提
 			if(target >= nums[begin] && target < nums[mid]) {
 				end = mid -1;
 			} else {
 				begin = mid +1;
 			}
 		}
 	}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值