素数与丑数

题目1:给出n中所有素数的个数。

暴力解法

每个数i都判断其是否被前面2~i的数整除,如果是不是素数,全部都不能整除,为素数。

bool isPrime(int n)
{
    if(n<2) return false;
    for(int i=2;i<n;i++)
    {
        if(n%i==0) return false;
    }
    return true;
} 
解法2:建立一个bool数组,从2的倍数开始,如果为其倍数的数都不是素数,依次遍历到n.然后再遍历一遍bool数组,输出素数。
    int n;
    cin>>n;
    if(n<2) return 0;
    bool *nums=(bool *)malloc(sizeof(bool)*n);
    for(int i=2;i<n;i++)
    {
        if(!nums[i])
        {
            for(int j=2;j*i<n;j++)
                nums[j*i]=true;
        }
    }
    int count=0;
    for(int i=2;i<n;i++)
    {
        if(nums[i]==false)
            count++;
    }
    cout<<count<<endl;
    free(nums);

题目2:

把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

解法1:暴力解法
bool isUgly(int number)
{
    while(number%2==0)
        number/=2;
    while(number%3==0)
        number/=3;
    while(number%5==0)
        number/=5;
    return (number==1)?true:false;
}
解法 2

根据丑数的定义我们可以将丑数分成下列3个组:
(1)1*2,2*2,3*2,4*2....
(2)
1*3,2*3,3*3,4*3….
(3)`1*5,2*5,3*5,4*5….

一个新的丑数可以看成一个旧的丑数乘以2,3,5(1除外)。那么如何维护丑数数列成为从小到大排序的顺序就成了本题的难点。

思路如下:

  • 维护三个列表,分别是当前遍历的丑数num的2,3,5倍,三个列表内的数都是有序的。
  • 每次三个列表分别获得第一个节点(列表最小节点),取得最小的数则为当前所需遍历的丑数。
  • 删除当前丑数在指定列表的节点,计数值+1。
class Solution {
public:
    int nthUglyNumber(int n) {
        int count = 1;
        int num = 1;
        list<int> l2;
        list<int> l3;
        list<int> l5;

        while(count != n)
        {
            l2.push_back(2*num);
            l3.push_back(3*num);
            l5.push_back(5*num);

            int l2min = l2.front();
            int l3min = l3.front();
            int l5min = l5.front();

            int minNum = min(l2min, min(l3min, l5min));
            if(l2min == minNum) l2.pop_front();
            if(l3min == minNum) l3.pop_front();
            if(l5min == minNum) l5.pop_front();
            num = minNum;
            ++count;
        }
        return num;
    }
};
解法 3

我们考虑用一个数组,数组存储的是当前的丑数,以后的每个丑数,都是用之前的数组的元素相乘的来的。接下来就是如何得到后面的丑数并保证它是有序的。可以想到,数组的第一个元素是1,1与2 3 5分别相乘,可以得到三个值,这三个值里面最小的,肯定就是下一个丑数的最大值,接着这个t2下标后移,继续比较,t3,t5同理。

class Solution {
public:
    int GetUglyNumber_Solution(int index) {
        if(index<7) return index;
        vector<int> res(index);//辅助数组保存排序的丑数
        res[0]=1;//第一个丑数为1
        int t2=0,t3=0,t5=0,i;//t2为丑数为2的倍数中,目前已遍历的丑数的最大值的下标。。以此类推
        for(i=1;i<index;i++)
        {
            res[i]=min(res[t2]*2,min(res[t3]*3,res[t5]*5));//得出第i个丑数的值
            if(res[i]==res[t2]*2) ++t2;//更新t2,t3,t5值
            if(res[i]==res[t3]*3) ++t3;
            if(res[i]==res[t5]*5) ++t5;
        }
        return res[index-1];
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值