这两个都不是什么算法,而是一种思想。
分治
是一个把原问题拆分成多个小问题,再把这几个小问题算出,在转换成大问题。
这个问题要满足以下几种性质
1,好拆
2,好合
3,(最小的)子问题好求
4,时间复杂度因为合并而增加
我们来算一道题:
斐波那契数列
这道题是可以不用分治的,我们来看一下
我们可以用递归,但是时间复杂度很高,为什么
Fn=Fn-1+Fn-2;Fn-1=fn-2+fn-3;
Fn-2算了两遍,所以用分治会比较好
快速幂(数字的分治)
来一道题:c=a^p%b(p<=long long)
这题怎么办?一道一道乘起来?不可能!(看一下后面的数据)
所以用到快速幂
A^(a+b)=A^a*A^b;
这题想必大家都知道,我们可不可以就吧p拆成两份,拆后平方一下不就好了?
就这样一直递归下去,直到是一就返回a,这样减少了很多时间复杂度
代码实现
int power(int a,int b,int p)//算递归
{
if(b==0){
return 1%p;//防止p=1;
}
else if(b==1)
{
return a%p;
}
else {
long long res=power(a,b/2,p);
res-=res;
res%=p;
if(b%2==0)
{
res-=a;
res%=p;
}
return res;
}
}
int power(int a,int b,int p)//notDG
{
int res=1;
for(long long i=1,x=a;i<=b;i<<=1)
{
if(i&b)
{
res*=x;
res=res%p;
}
x*=x;
x%=p;
}
return res;
}
归并排序:
是一种很经典的,时间复杂度很低的一种求逆序对的方法
原理:
就是用分治法,分成两个部分(平均分配),三种可能(及全部在左边,或右边,或两边都有)
代码实现:
long long ans=0;
void Sort(int begin,int end)
{
if(begin==end)return ;
else
{
int mid=(begin+end)>>1;
Sort(begin,mid);
Sort(mid+1,end);
int h1=begin,h2=mid+1,t1=mid,t=begin;
while(t<=end)
if(h1<=t1)
if(t2>=h2)
if(c[hi]<=c[h2])
top[++t]=c[hi++];
else{
ans+=t1-h1+1;
top[t++]=c[hi++];
}
else top[t++]=c[hi++];
else top[++p]=c[h2++];
}
for(int i=begin;i<=end;i++)
c[i]=temp[i];
return ;
}
贪心
贪心的是一种从前一个结论推出下一个结论的方法(我也说不清)
贪心是一种思想,只能用题目来理解。
合并果子(题目我就不说了,只讲思路,题目网上也可搜)
想必这题一定都做过,是一到典型的贪心
方法:
现将其排序
把两个最小的放在一起合并
剩下在排序
两个最小的放在一起……
删数问题
对于给定的n位正整数a,
编程计算删去k个数字后得到的最小数。
这道题显然很简单,把最大的数找到,删掉便可
来到语文题,考考你们的理解力
现有一张N!个节点的图,每个节点的编号都是A1A2A3…AN序列的一个置换。对于任意两个节点S和T,如果T的编号是由S编号的首位与除首位外的编号中任一位交换所得 ,则S和T之间有一条边,求从给定节点S走到节点(A1A2A3…AN)所需经过的最少边数。其中,n≤100。
理解的了吗?我们来转换一下
身高为1~n的n个人随意地站成一列,你每次可以交换队首与队中的某一人的位置, 你需要进行多少次交换才可以让这n个人的身高升序排列?
这样理解了吗?
是不是理解了?所以,信息也考语文。(很多题目都是这样)
思路:留给大家思考一下下
提示:不在应有位置上的数便是交换的次数