欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

素数与丑数

程序员文章站 2024-01-04 11:06:58
...

题目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];
    }
};

上一篇:

下一篇: