百度面试题-乘法表

这道题简要题目如下:
乘法表第i行第j列位置的元素为i*j,并且乘法表下表编号从1开始,比如2*3乘法表为:
1 2 3
2 4 6
那么对于n*m的乘法表按照不减顺序排列之后,求第k个元素的值是多少?

看到这个题,大多数同学想到的肯定是得到这个乘法表的数值,然后进行排序,从而得到k的值,这样做的确没问题,但显然没有太多技巧性。那么到这就开始讲讲我大概的思路吧。
刚开始拿到这道题,大家肯定都是先吧这个乘法表画出来,我一开始想的是画斜线,那么斜线两边的值肯定是相同的,同时也是画斜线这一斜行(说的怎么那么别扭,意会就好)中最小的值,越到中间越大,最中间的值是最大的,我曾设想这儿会是突破口。然而,我发现从第四行(这里以及后面这段思想的所有行都是所谓的斜行)开始的最大值6要比第五行的最小值5要大,那这么说的话按递增序列找第k值岂不是还要拐弯,所以这个想法到这儿终止了。
这时候我开始第二个想法,从数1开始,我看他重复的次数,这样递增下去不就知道了k的值么,那么这些数的个数是多少呢。我们阅读题目知道,这个题是乘法表,表中的数值都是i*j求得的,那么就是说每次乘出了相同的值,这个数就会多重复一次。显然(可怕的显然,漫长的思想过程自己去体会23333),这个重复的次数就是约数的个数了。那么我们直接求约数的个数不就可以直接得到这个数重复次数,从而递增得到k的值吗?(我真是太机制了)
然而,高兴太早果然会出问题的,求约数个数只能解决掉上三角,下三个这些值出现次数该怎么算啊,而且他还不是连着的。(头疼)一定有解决办法的,而且我也不觉得我的求约数法的思路有问题,那问题出在哪了?(叮咚)对了,乘法表有自己的界线限制着,所以下三角不能得到所有的重复次数(理想的),那么我们给它一个条件限制不就行了,这样我们就能得到1~m*n(注意为什么是m*n)的所有出现次数了,那么给个递增我们就求出了第k个数的值了(是不是很简单)。
代码如下:

#include     

int result(int m, int n, int k); 

int result(int m, int n, int k)
{
    int value = 0;
    int i, j;

    for(i = 1; i <= m; i++)
        for(j = 1; j <= n; j++)
        {   
            if(k == i*j)
                value++;
        }   

    return value;
}

void main(void)
{
    int m, n, k;
    int i;
    int sum = 0;

    scanf("%d, %d, %d", &m, &n, &k);

    for(i = 1; (sum < k) && (i <= m*n); i++)
    {   
        sum += result(m, n, i); 
//      printf("sum = %d\n", sum);
    }   

    i--;

    printf("the value is %d\n", i); 
}

那么现在问题来了,这个求约数的算法实在是太二了,好吧,不知道有没有更好的算法,希望有大牛能在给出自己宝贵的意见,谢谢大家。

你可能感兴趣的:(面试题,面试题,百度)