[前端]_一起刷leetcode 面试题 17.09. 第 k 个数

182 阅读3分钟

「这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战

题目

面试题 17.09. 第 k 个数

有些数的素因子只有 3,5,7,请设计一个算法找出第 k 个数。注意,不是必须有这些素因子,而是必须不包含其他的素因子。例如,前几个数按顺序应该是 1,3,5,7,9,15,21。

示例 1:

输入: k = 5

输出: 9

思路

  1. 这道题先得找规律,我看了半天才反应过来题目的意思,给大家翻译一下。一个数可以被3、5、7经过n轮整除到1的,就是素因子:

    比如: 3 / 3 = 19 / 3 / 3 = 115 / 3 / 5 = 1

  2. 找到规律后,这道题目就简单多了。我们只需要统计从let result = [1]开始,每一轮拿3、5、7来乘以我们有的数,乘积也pushresult中如此反复即可;

  3. 但是发现有个坑,比如 3 * 9 < 5 * 5, 那么该推哪一个数呢?

  4. 一开始我想用三个数组来代表每个数接下去可以乘的数,找到最小值后放进result中;

  5. 后面想了想发现没必要搞三个数组,只需要用三个变量来记录当前每个数乘到哪个位置了即可;

  6. 做完题目才发现,这就是三指针的概念。。。

  7. 整体来说,就是你每次拿数组中的元素从前往后, 分别*3、*5、*7,然后看到哪个小就先记录哪个。当然,相等的时候要把两个指针一起往后移位。比如: 3 * 5 = 5 * 3;

  8. 最后由于数组从0开始的,返回result[k-1]即可。

实现

/**
 * @param {number} k
 * @return {number}
 */
function getKthMagicNumber(k) {
    
    let reuslt = [1, 3, 5, 7];
    let index1 = index2 = index3 = 1;

    while (reuslt.length < k) {
        // 记录当前值
        let cur3 = reuslt[index1] * 3,
            cur5 = reuslt[index2] * 5,
            cur7 = reuslt[index3] * 7;
  
        if (cur3 <= cur5 && cur3 <= cur7) {
            // 最小值是*3的,乘过后把当前值push进数组中,就是我们要的数
            reuslt.push(cur3);
            
            // 有相等的指针要以前往后移
            if (cur3 === cur5) {
                index2++;
            }

             if (cur3 === cur7) {
                index3++;
            }   

            index1++;
        } else if (cur5 <= cur3 && cur5 <= cur7) {
            reuslt.push(cur5);

            if (cur5 === cur3) {
                index1++;
            }

             if (cur5 === cur7) {
                index3++;
            }

            index2++;
        } else {
            reuslt.push(cur7);

            if (cur7 === cur3) {
                index1++;
            }

             if (cur7 === cur5) {
                index2++;
            }

            index3++;
        }
    }

    return reuslt[k - 1];
};

结果

image.png

优化

写完后总觉得自己的代码不够优雅,重复的代码写了好几遍,于是痛定思痛,优化了一下代码。

/**
 * @param {number} k
 * @return {number}
 */
function getKthMagicNumber(k) {
    
    let reuslt = [1];
    let p1 = p2 = p3 = 0;

    while (reuslt.length < k) {
        // 这里三个变量是为了好理解,想优化空间复杂度可以不用变量的
        let cur3 = reuslt[p1] * 3,
            cur5 = reuslt[p2] * 5,
            cur7 = reuslt[p3] * 7;
        
        const minValue = Math.min(...[cur3, cur5, cur7]);
        reuslt.push(minValue);

        if (cur3 === minValue) p1++;
        if (cur5 === minValue) p2++;
        if (cur7 === minValue) p3++;
    }

    return reuslt[k - 1];
};

优化结果

image.png

看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。