您的位置:首页 > 其它

分治算法——假硬币寻找,硬币找零,众数问题

2017-12-23 19:17 323 查看
分治算法(dac),是对递归或者递推技术的一种具体运用。处理问题的过程中,我们有时的确分而且治了(线性时间选择,归并排序),但更多情况下,恐怕是一种分而不治的思想(假硬币寻找,众数问题)通过递归技术,在逻辑上不断使原问题规模缩减,类似树从根节点不断寻值,直到返回目标值。

1,假硬币寻找:

问题很简单:n个数形成了一个数组,只有一个数与其他数值不同,找到其下标。

思想:对于奇数个硬币,找到中间值(注意:对数组的分治经常会寻找中间值),对左右比较(这点思路很简单,不赘述)

对偶数个硬币,找到中间两个硬币,进行左右比较即可。

#include <stdio.h>
int sum(int a[],int min,int max)
{
int sum=0; //注意此处赋值
for(int i=min;i<=max;i++)
{
sum+=a[i];
}
return sum;
}
int Judge(int a[],int min,int max)
{
int mid;
int mid1;
if((max-min+1)%2==0)
{
mid=(max+min)/2;
mid1=mid+1;
if(sum(a,min,mid-1)>sum(a,mid1+1,max))
{
Judge(a,mid1+1,max);
}
else if(sum(a,min,mid-1)==sum(a,mid1+1,max))
{
if(a[mid]<a[mid1])
{
return mid;
}
else
{
return mid1;
}
}
else{
Judge(a,min,mid-1);
}
}
else{
mid=(max+min)/2;
if(sum(a,min,mid-1)>sum(a,mid+1,max))
{
Judge(a,mid+1,max);
}
else if(sum(a,min,mid-1)==sum(a,mid+1,max))
{
return mid;

}
else{
Judge(a,min,mid-1);
}
}
}
int main()
{
int a[10]={1,1,1,1,1,1,1,0,1,1};
printf("%d",Judge(a,0,9));
}这个思路非常简单,不赘述。代码如下:
2,硬币找零的分治法算法

硬币找零的问题描述非常简单,不予赘述。

思想:双递归(类似计算斐波那契数列)

f(value,i)=min{f(value,i-1),value/a[i]+f((value%a[i]),i(此处的i是value被当前v值减去后剩余的金额对应最大的i,比如100块被15的硬币分的只剩下10块,而剩下硬币的面额还有8,5,3,1,那么我们选择8的下标为i))#include <stdio.h>
int a[3]={1,3,5};
int min(int a,int b)
{
return a<b?a:b;
}
int f(int c)
{
int i;
for(i=0;i<=5;i++)
{
if(a[i]>c)
{
break;
}
}
return i-1;
}
int coin(int value,int i)
{
if(value==0)
{
return 0;
}
if(value==1)
{
return 1;
}
if(i==0) //!
{
return value;
}
else{
return min(coin(value,i-1),value/a[i]+coin((value%a[i]),f(value%a[i])));
}
}
int main()
{

printf("%d",coin(9,2));
} 在上述代码中,!处为我第一次写出现的错误,需要注意的是在双参数函数递归的时候,一般而言对两个参数需要定义两个出口,并且要明白自己数组的最小下标在哪里,否则很容易出现错误。
3,众数问题。

思想:本质上还是利用分治思想处理数组。可以先对数组进行排序,然后找中间的数,从左和右得到它的个数,再对数组的左右子树进行减治处理即可。代码明日粘。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  分治算法 递归 class