1.分治策略、递归、二分查找及相关问题

一、分治策略的概念

      任何可以用计算机求解的问题所需的计算时间都与其规模有关。问题的规模越小,解题所需的计算时间往往也越少,从而也较容易处理。例如,对于n个元素的排序问题,当n =1时,不需任何计算,n=2时,只要做一次比较即可排好序;n=3时只要进行两次比较即可;.....而当n较大时,问题就不那么容易处理了。要想直接解决一个较大的问题,有时是相当困难的。
     分治法的设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。如果原问题可分割成k个子问题,1<k<=n,且这些子问题都可解,并可利用这些子问题的解求出原问题的解,那么这种分治法就是可行的。由分治法产生的子问题往往是原问题的较小规模模式,这就为使用递归技术提供了方便。在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易求出其解。由此自然导致递归算法.
   分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许多高效算法


二、递归的概念

 若一个函数直接地或间接地调用自己,则称这个函数是递归的函数(简单地描述为“自己调用自己”) 

三、分治策略的特征


分治法所能解决的问题一般具有以下四个特征:

1.该问题的规模缩小到一定的程度就可以容易地解决
2.该问题可以分解为若千个规模较小的相同问题

3.使用小规模的解,可以合并成,该问题原规模的解。
4.该问题所分解出的各个子规模是相互独立的。

分治法步骤:
分解 : 将问题划分成一些子问题,子问题的形式与原问题一样,只是规模更小。

解决:递归地求解子问题。如果子问题的规模足够小,则停止递归,直接求解

合并·将小规模的解组合成原规模问题的解

四、示例

1.输入一个整数(无符号整型) ,用递归算法将整数倒序输出分析:现在用递归过程的递推步骤中用求余运算将整数的各个位分离,并打印出来.
输入: 12345;
输出: 1 2 3 4 5 或者5 4 3 2 1

//非递归
void PrintInt1(size_t n)// size_t unsigned int
{
	while (n != 0)
	{
		printf("%d ", n % 10);
		n = n / 10;
	}
}
//递归
void PrintInt2(size_t n)
{
	if (n == 0)return;
	else
		printf("%d ", n % 10);
	return PrintInt2(n / 10);
}

2.折半查找(二分查找)

非递归实现

int BinarySearch(const int* nums,int n,int key)//n为数组长度
{
	int mid = 0;
	int right = n - 1;
	int pos = -1;
	int left = 0;
	while (left <= right)//小于相当于想、两指针正在逼近,等于说明找到了,只有left>right说明他俩岔开了就是没找到
	{
		mid = (left + right) / 2;
		if (key > nums[mid])//比中间值大
		{
			left = mid + 1;//右半边找
		}
		else if (key < nums[mid])//比中间值小
		{
			right = mid - 1;//左半边找
		}
		else
		{
			pos = mid;
			break;
		}
	}
	return pos;
}

递归实现

int BinarySearch2(const int* nums, int left, int right,int key)
{
	int pos = -1;
	int mid = (left + right) / 2; 
	if (left <= right)
	{
		if (key < nums[mid])//比中间值小
		{
			return BinarySearch2(nums, left, mid - 1, key);//左半边找
		}
		else if (key >nums[mid])//比中间值小
		{
			return BinarySearch2(nums, mid + 1, right, key);//右半边找
		}
		else
		{
			pos = mid;
		}
	}
	return pos;
}

3.折半查找找到最左key值

int LeftBinarySearch(const int* nums, int n, int key)//n为数组长度
{
	int mid = 0;
	int right = n - 1;
	int pos = -1;
	int left = 0;
	while (left <= right)//小于相当于想、两指针正在逼近,等于说明找到了,只有left>right说明他俩岔开了就是没找到
	{
		mid = (left + right) / 2;
		if (key > nums[mid])//比中间值大
		{
			left = mid + 1;//右半边找
		}
		else if (key < nums[mid])//比中间值小
		{
			right = mid - 1;//左半边找
		}
		else
		{
		    while (left <= mid && nums[mid - 1] == key)
			{
			    --mid;
			}
			pos = mid;
			break;
		}
	}
	return pos;
}

void main()
{
	//PrintInt2(12345);
	int nums[12] = { 12,23,23,23,23,56,67,78,89 };
	int i = LeftBinarySearch(nums, 8,23);
	printf("%d", i);
}

4.折半查找寻找第一个大于等于key值的元素

int FirstBinarySearch(const int* nums, int n, int key)
{
	int left = 0;
	int right = n - 1;
	int mid = n/2;
	int pos = -1;
	while (left <= right)
	{
		if ( key <= nums[mid] )
		{
			right = mid-1;
			mid = (left + right) / 2;
			while (left <= mid && nums[mid - 1] >= key)
			{
				mid--;
			}
			pos = mid;
			break;
		}
		else//(key>nums[mid])
		{
			left = mid + 1;
			mid = (left + right) / 2;
		}
	}
	return pos;
}
void main()
{
	//PrintInt2(12345);
	int nums[12] = { 1,12,23,34,45,56,78,89,90 };
	int i = FirstBinarySearch(nums,9,55);
	printf("%d", i);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
分治法是一种常用的算法设计策略,它将一个大问题分解成若干个相同或类似的子问题,然后递归地解决这些子问题,最后将子问题的解合并起来得到原问题的解。二分查找是一种高效的查找算法,它通过将有序数组分成两部分,然后判断目标值在哪一部分中,从而缩小查找范围。 在C++中,可以使用分治法实现二分查找的步骤如下: 1. 定义一个函数,接收一个有序数组和目标值作为参数。 2. 在函数内部,判断数组是否为空,如果为空则返回-1表示未找到目标值。 3. 计算数组的中间位置mid,将数组分成左右两部分。 4. 判断中间位置的元素与目标值的关系: - 如果中间位置的元素等于目标值,则返回mid。 - 如果中间位置的元素大于目标值,则在左半部分继续进行二分查找。 - 如果中间位置的元素小于目标值,则在右半部分继续进行二分查找。 5. 递归调用函数,在左半部分或右半部分进行二分查找,直到找到目标值或者数组为空。 6. 如果找到目标值,则返回对应的索引;如果未找到,则返回-1表示未找到。 下面是一个使用分治法实现二分查找的C++代码示例: ```cpp #include <iostream> #include <vector> int binarySearch(const std::vector<int>& nums, int target) { int left = 0; int right = nums.size() - 1; while (left <= right) { int mid = left + (right - left) / 2; if (nums[mid] == target) { return mid; } else if (nums[mid] > target) { right = mid - 1; } else { left = mid + 1; } } return -1; } int main() { std::vector<int> nums = {1, 3, 5, 7, 9}; int target = 5; int result = binarySearch(nums, target); if (result != -1) { std::cout << "目标值在数组中的索引为:" << result << std::endl; } else { std::cout << "未找到目标值" << std::endl; } return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Better Sally

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值