linkedhashmap获取第n个元素_算法题——[leetcode1492]第k个n的约数

Medium级别的题:给定正整数n和k,满足1<=k<=n<=1000,求n的第k大的约数,如果n的约数个数少于k,返回-1。

例如:输入n = 12, k = 3返回3

因为12的约数从小到大分别为{1, 2, 3, 4, 6, 12}

又如:输入n = 4, k = 4返回-1

因为4只有1, 2, 4这3个约数。

分析:无聊题。不知道考点在哪,这么小的数据范围。

方法1 暴力

线性枚举,由小到大枚举约数。

代码:

class Solution {public:    int kthFactor(int n, int k) {        for (int i = 1; i <= n; ++i) {            if (n % i == 0 && --k == 0) return i;        }        return -1;    }};

方法2 sqrt(n)枚举n的约数,再排序

代码:

class Solution {public:    int kthFactor(int n, int k) {        vector<int> v;        for (int i = 1; i * i <= n; ++i) {            if (n % i == 0) {                v.push_back(i);                if (n / i != i) {                    v.push_back(n / i);                }            }        }        if (v.size() < k) return -1;        sort(v.begin(), v.end());        return v[k - 1];    }};

方法3 可以考虑把n,分解质因数,因为2 * 3 * 5 * 7 * 11 = 2310,所以n <= 1000时,它最多有4个不同的质因数。然后利用“丑数”的方法,从小到大枚举只由这些质因数相乘组成的数——但是要注意,不是n的约数的要跳过。

代码(略长):

class Solution {public:    int kthFactor(int n, int k) {        if (k == 1) return 1;        vector<int> v;        int m = n;        for (int i = 2; i * i <= m; ++i) {            if (n % i == 0) {                v.push_back(i);                while (m % i == 0) {                    m /= i;                }            }        }        if (m > 1) v.push_back(m);        vector<int> f = {1};        vector<int> ind(v.size());        while (f.size() < k) {            bool out = true;            int temp = n + 1;            for (int i = 0; i < v.size(); ++i) {                 while (ind[i] < f.size() && n % (f[ind[i]] * v[i])) {                     ++ind[i];                }                if (ind[i] < f.size()) {                    temp = min(temp, f[ind[i]] * v[i]);                    out = false;                }            }            if (out) return -1;            for (int i = 0; i < v.size(); ++i) {                if (ind[i] < f.size()) {                    const int may = f[ind[i]] * v[i];                    if (n % may == 0) {                        if (may == temp) ++ind[i];                    }                }            }            if (temp <= n) f.push_back(temp);        }        return f[k - 1];    }};

16adda980b561adca9953e66a765069d.png

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值