算法题--来自网易面试(JavaScript解法)

一个正整数数对(x,y),x和y均不大于n(1 <= n <= 10^5),并且x除以y的余数大于等于k(0 <= k <= n-1)。

那么一共有多少个可能的数对?

题目分析

题目要求找出满足条件0<x<=n,0<y<=n,x%y>=k三个条件的数对的数目。

这个题目可以转换为,假设有一个n*n的矩阵,x行第y列中的值为x%y,那么矩阵中有多少个元素elem满足elem>=k。

取行列式的任意一列y=y1:

    x=1时,elem=1;x=2时,elem=2;......;x = y1-1时,elem=y1-1;x=y1时,elem=0;

    x=y1+1时,elem=1;x=y1+2时,elem=2;......;x = 2y1-1时,elem=y1-1;x = 2*y1时,elem=0;

    ......

    x = (b+1)*y1+1时,elem=1;x=(b+1)*y1+2时,elem=2;......;x=(b+1)*y1+d=n,elem=d(0,y1-1);

当y1<k时显然所有元素都小于k,即elem<k,故不考虑此时的b,d的值。

当y1>=k时,b=n/y1,d=b%y1。因为一列中elem的取值为1,2,3,4,...,y1,0,1,2,3,4,...,y1,0,1,2,3,4,...,y1,0,1,2,3,4,...,d。可以发现是数列1,2,3,4,...,y1,0的重复b次,每次y1-k个elem满足条件,故所有重复中有b*(y1-k)个elem满足条件。而在剩下的数列1,2,3,4,...,d中,有a=d-k+1=b%y1-k+1(d>=k时,即a>=1时)个满足条件。

思路1

通过两层循环,然后在第二层循环中判断是否符合条件x%y>=k,若符合条件,计数器加一。

这个思路简单粗暴,实现基本没难度,但是性能会比较差,时间复杂度为o(n^2)。

思路2

使用每一列数中的规律,循环每一列,将每一列符合条件的数对的数目相加。

这个思路性能较思路1好很多,时间复杂度为o(n)。

代码实现

思路1
function fn1(n,k){
	var j,i;
	var count = 0;
	for(i=1;i<=n;i++){
		for(j = 1;j<=n;j++){
			if(i%j>=k){
				count++;
			}
		}
	}
	return count;
}
思路2
function fn2(n,k){
	var y,a,b;
	var count = 0;
	for(y=0;y<=n;y++){
		if(y<=k){
			continue;
		}
		b = parseInt(n/y);
		count += b*(y-k);
		a = n%y-k+1;
		if(a>0){
			count += a;
		}
	}
	return count;
}

以上解说若有什么错误,欢迎大家提出。

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40041299/article/details/79735480

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值