面试算法 排列硬币

本文详细介绍了三种不同的算法——暴力算法、二分算法及牛顿迭代求平方根算法,用于解决给定数量硬币时如何形成完整的阶梯形状问题。通过对比不同算法的特点,帮助读者理解并掌握每种算法的应用场景。

题目:排列硬币
内容描述:总共有n枚硬币,将它们摆成一个阶梯形状,第k行就必须正好有k枚硬币。
给定一个数字n,找出可形成完整阶梯行的总行数。n是一个非负整数,并且在32位有符号整型的范围内。


算法:

1.暴力算法

2.二分算法

3.牛顿迭代求平方根算法


算法思想:

1.暴力算法:(传入硬币数 n )

        1.来个循环从 1 开始  到  n   结束

        2.循环里面我们就 减去那个数,n=n-i ; 

        3.直到 n==0;  返回i     或者  n<0  ,返回     i -1   (结束循环)


2.二分算法  (传入硬币数 n )

        1 +2 +3 +4 +5 +6 等差数列 求和 ---》 公式 : S =n * a1 + n*(n-1 )/2   = n*( 1 + n)/2;

        所以构建第 n 个台阶所需要的硬币数量为  n * (1+ n)/2;

        1.首先命令两个变量,一个低的 low =0  ,  一个高的  high = n , 代表台阶数

        2.我们要建造一个while 循环 循环的条件为  low<=high 

        3.我们的里面定义一个变量,首先是mid  是一个中间值,中间的台阶是啥 , 

        4. mid= low +  (low+high)/2  ,mid的位置

        5.  当mid 位置所用的硬币数量 大于 n  的时候  (mid*(mid+1)/2     > n  )-->high--

        6.  当mid 位置所用的硬币数量 小于 n  的时候  (mid*(mid+1)/2     > n  )-->low ++ 

        7.当我们mid 所用的硬币数量正好等于 n   的时候,返回 mid.'

        8.while 循环没有找到,mid 所用的硬币数量正好等于 n    (mid*(mid+1)/2   ==  n) 结束循环,返回high,低的这个数,因为这时候,low>high .    


3.牛顿迭代求平方根算法 (传入硬币数 n )

        1.开始的时候我们说过这个计算公式: (阶梯数 k)

        推导:  k*(k-1)/2 =n ;

                      k*k -k =2n

                      k*k =2n-k;

                      k= sqrt(2n-k);//sqrt 开根号

        2.所以我i们开始写算法 牛顿迭代的算法:

                牛顿迭代的思想:  1.  x*x =n  

                                                2.  x=n/x; (递归,之前的求平方根 有这个算法)

                                                3.  (x+ n/x)/2==x 的时候 就证明  x 的值找到了。

                                                4. 所以我们利用这个思想 来是求 上面的值 k.

                                                5.  (k + (2n-k)/k  )/2= k  的时候,k 的值就出来了。

                                               


 代码:

/*************************************************
作者:She001
时间:2022/8/27
题目:排列硬币
内容描述:总共有n枚硬币,将它们摆成一个阶梯形状,第k行就必须正好有k枚硬币。
给定一个数字n,找出可形成完整阶梯行的总行数。n是一个非负整数,并且在32位有符号整型的范围内。
		 
***************************************************/
#include<iostream>
#include<map> 
using namespace std;
/*
算法:

1.暴力算法

2.二分算法

3.牛顿迭代求平方根算法

*/
/*
算法思想:

1.暴力算法:(传入硬币数 n )

        1.来个循环从 1 开始  到  n   结束

        2.循环里面我们就 减去那个数,n=n-i ; 

        3.直到 n==0;  返回i     或者  n<0  ,返回     i -1   (结束循环)
*/


int fangfa_1(int n)
{
	int m=n;
	for(int i=1;i<n;i++)
	{
		//cout<<"m= "<<m<<endl;	
		m=m-i;
		if(m==0)
		{
			return i;
		}	
		else if(m<0)
		{
			return i-1;
		}
	} 
} 



/*

2.二分算法  (传入硬币数 n )

        1 +2 +3 +4 +5 +6 等差数列 求和 ---》 公式 : S =n * a1 + n*(n-1 )/2   = n*( 1 + n)/2;

        所以构建第 n 个台阶所需要的硬币数量为  n * (1+ n)/2;

        1.首先命令两个变量,一个低的 low =0  ,  一个高的  high = n , 代表台阶数

        2.我们要建造一个while 循环 循环的条件为  low<=high 

        3.我们的里面定义一个变量,首先是mid  是一个中间值,中间的台阶是啥 , 

        4. mid= low +  (low+high)/2  ,mid的位置

        5.  当mid 位置所用的硬币数量 大于 n  的时候  (mid*(mid+1)/2     > n  )-->high--

        6.  当mid 位置所用的硬币数量 小于 n  的时候  (mid*(mid+1)/2     > n  )-->low ++ 

        7.当我们mid 所用的硬币数量正好等于 n   的时候,返回 mid.'

        8.while 循环没有找到,mid 所用的硬币数量正好等于 n    (mid*(mid+1)/2   ==  n) 结束循环,返回high,低的这个数,因为这时候,low>high .    

*/

int fangfa_2(int n)
{
	int mid,sum;
	int low=0;
	int high=n;
	while(low<=high)
	{
		mid=low +((high-low)/2);
		sum =((mid*(mid+1)))/2;
		//cout<<"sum= "<<sum<<endl;
		//cout<<"low= "<<low<<endl;
		//cout<<"high= "<<high<<endl;
		if(sum==n)
		{
			return mid;
		}
		else if(sum>n)
		{
			high=mid-1;
		}
		else if(sum<n)
		{
			low=mid+1;
		}
	}
	return high;//·µ»ØÐ¡µÄÄǸöÖµ 
}

/*

3.牛顿迭代求平方根算法 (传入硬币数 n )

        1.开始的时候我们说过这个计算公式: (阶梯数 k)

        推导:  k*(k-1)/2 =n ;

                      k*k -k =2n

                      k*k =2n-k;

                      k= sqrt(2n-k);//sqrt 开根号

        2.所以我i们开始写算法 牛顿迭代的算法:

                牛顿迭代的思想:  1.  x*x =n  

                               2.  x=n/x; (递归,之前的求平方根 有这个算法)

                              3.  (x+ n/x)/2==x 的时候 就证明  x 的值找到了。

                             4. 所以我们利用这个思想 来是求 上面的值 k.

                          5.  (k + (2n-k)/k  )/2= k  的时候,k 的值就出来了。

       */



double fangfa_3_1(double k,int n)
{
	double res = (k+(2*n-k)/k)/2;
	if(res==k)
	{
		return res;
	}
	if(res!=k)
	{
		fangfa_3_1(res ,n);
	}
} 



int fangfa_3(int n)
{
	double a=fangfa_3_1(n,n);
	return (int )a;
}


 
 
 
int main()
{
	int a= fangfa_1(11);
	int b= fangfa_2(11);
	int c= fangfa_3(11);
	cout<<a<<endl;
	cout<<b<<endl;
	cout<<c<<endl;
	return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值