【分支算法-01】例题打卡

本文详细介绍了分治算法的基本思想,包括如何将大问题分解为子问题,递归解决子问题,并最终合并子问题的解。文中列举了二分查找、全排列问题、整数划分问题和归并排序等经典例子,通过非递归和递归的方式展示了分治算法的应用。同时,文章提供了对应的伪代码和实际代码实现,帮助读者更好地理解和掌握分治策略。
摘要由CSDN通过智能技术生成

分治算法

基本思想理解

通过阅读博客理解:

  1. 分治算法是将一个大问题分解成相应的类型相同或者相似的子问题求解,然后在将子问题最后合并为大问题。
  2. 分治方法递归技术密不可分。
分治方法适用情况
  1. 能够拆分成多个相同或者相似的子问题提高算法效率。递归思想
  2. 子问题的解能够合并成为原来问题——涉及贪心算法以及动态规划算法的择优选择
  3. 子问题的解相互独立
分治方法基本步骤
  1. :将问题分解为若干个规模较小的,相互独立的,与原问题形式相同的子问题
  2. :当问题小于一个阈值的时候,直接求解。否则不断递归子问题
  3. :将子问题的解合并成为原问题的解
//伪代码
|p|表示问题P的规模;n表示某一个阈值;ADHOC(P)表示子算法——用于求解最小规模的问题;MERGE(y1,...,yi)———合并算法;
if(|p|<n)
{
	return ADHOC(P);
}
else
{
	不断将子问题通过题目适应的递归算法分解
	for(i=1->k)
		do yi<-DivideAndConquer(Pi)//递归解决Pi
		result <- MERGE(Y1->Yi);
		return result
}

涉及题目

二分查找(例题)

题目描述:实现二分搜索:多组输入数据,每组第一个数字为数组的长度n,然后输入n个整数,最后输入带查询的数值m.
非递归方式

//运用非递归方式实现二分查找
#include <stdio.h>
#define MaxValue 1000
int main()
{
	//输入数据
	int n,m;
	int low = 0;high;
	int key;
	int result;
	int NUM[MaxValue];
	scanf("%d",&n);
	for (int i=0;i<n;i++)
	{
		scanf("%d",&NUM[i]);
	}
	scanf("%d",&key);
	high = n-1;
	while(high>=low)
	{
		int mid = (low+high)/2;
		//通过已输入数据实现非递归查找
		if(key == NUM[mid])
		{
			result = NUM[mid];
			printf("%d",result);
		}
		else if(key<NUM[mid])
		{
			low = mid + 1;
		}
		else if(key>NUM[mid])
		{
			high = mid-1;
		}
		else
			printf("无可用数值");
	}
	
	//返回数据
	return 0;
}

递归方式

int BinarySearch(int A[],int start,int end,int target)
{
	int mid;
	if(start>end)
	{
		return NULL ;
	}
	else
	{
		mid = (start + end) /2;
		if(target == A[mid])
		{
			return mid;
		}
		else if(target > A[mid])
		{
			BinarySearch(A,mid+1,end,target);
		}
		else(target < A[mid])
		{
			BinarySearch(A,start,mid,target);
		}
	}
}
全排列问题(例题)

问题描述:有1->n个数字,请问有多少种排列方式?
自我思想分析:将N个数拆分成每一个只有1个元素的数组,然后每一个数字都有多种排列情况,然后将每一个部分解合并为原来问题的解。

//通过递归求解全排列
# include<stdio.h>
#define MaxValue 1000
int main()
{
	//读取数据
	//采用递归方法求解
//伪代码
int DG(int A[],int num)
{
	if(判断目前的可变元素是否只有一个)
	{return 1;}
	else
	{
		int result;
		for(i->n,)
		{遍历第一层可能出现的所有结果};
		result = 所有结果数;
		result  +=DG(从排除固定的第一个数字开始再次将后面元素进行全排列)
	}
	return result;
}

** 全排列递归问题的思想就是将每一个数与想要交换的数字进行交换以后,其后面的组合必须再次循环一遍进行交换,这样才能满足全部都能够考虑到。然后在最后只剩一个数字的时候,没法交换了,我们才将总体组合的系数加一,然后输出这个组合**

//递归全排列问题

# include <stdio.h>
#define MaxValue 10000
//实现交换
void swap(int a,int b)
{
	int temp = a;
	a = b;
	b = a;
}
//实现输出序列的每次组合并且将cout计数++
int ArrayCount(int A[],int n-1)
{
	for (int i=0;i<=n-1;i++)
	{
		printf(A[i]);
	}
	cout++;
}
//递归实现算法(已经了解)
DG(int A[],int q,int n)//q表示从第几个元素开始全排列,n表示所有数列的总项
{
	if(q==n)//已经到达最后一个元素的位置
	{
		return ArrayCount(A[],n-1);
	}
	else
		{
			for(int i=q;i<n;i++)
			{
				swap(A[i],A[q]);
				DF(A[i],q+1,n);
				swap(A[i],A[q]);
			}
		}
}
int main()
{
	//读入数据 
	int A [MaxWalue]={0};
	int num ,result;
	for (int i=0;i<num;i++)
	{
		scanf("%d",&A[i]);
	}
	//实现全排列
	result = DF(A,0,num);
	printf(result);
	return 0;
}
整数划分问题(例题)

问题描述:
n=m1+…+mi(1<=mi<=n),则称为{m1,…,mi}的n的一个划分
如果{m1,…,mi}中最大值不超过m,及max{m1,m2,…,mi}<=m,我们称这是一个属于n的m划分。我们记n的m划分的个数f(n,m).

**已经理解:**可以通过思维导图理解
整数划分
整数划分的代码:

# include <stdio.h>
int Para(int n,int m)
{
	if((n<1)||(m<1))
	{
		return 0;
	}
	if((n=1))||(m=1))//情况1
	{
		return 1;
	}
	else if(n!=m)
	{
		if(n<m)//情况2
		{
			return Para(n,n);
		}
		else (n>m)//情况3+4
		{
			//存在包含m以及不包含m的情况
			return f(n-m,m)+f(n,m-1);
		}
	}
	else (n=m)//情况5+6
	{
		//存在包含n以及不包含n的情况
		return f(n,n-1)+1;
	}
}
int main()
{
	int n,m;
	scanf("%d %d",&n,&m);
	Para(n,m);
}
归并排序问题(例题)
//分治的思想递归拆分,通过比较每个子序列的数字的大小,然后进行合并操作,不断将子问题合并为原来的大问题,得到解决
void GB(int A[],int B[],int start,int last)
{
    //数组只剩下一个元素的时候
    if(start >= last)
    {
        return A[start];
    }
    else (start<last)
    {
       int len = last-start;
       int mid = (len>>1)+start;
       start1 = start;start2=len+1;
       end1 = mid;end2=last;
        GB(A,B,start1,end1);
        GB(A,B,start2,end2);
        int i = start;
        //排序
        while((start1<=end1)&&(start2<=end2))
        {
           B[i++]=A[start1]<A[start2]?A[start1++]:A[start2++];
        }
        //有剩余
        //左侧剩余
        while(start1<=end1)
        {
            B[k++]=A[start1++];
        }
        while(start2<end)
        {
            B[k++] = A[start2++];
        }
        for(i=start;i<last;i++)
        {
            A[i] = B[i];
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值