LeetCode——数学

这篇博客介绍了四个编程题目,包括FizzBuzz问题,高效计算质数数量的埃氏筛法,判断数字是否为3的幂次方,以及罗马数字转整数的实现。通过这些题目,探讨了类型转换、优化算法和处理特殊规则的技巧,适合提升编程思维和算法能力。
摘要由CSDN通过智能技术生成

412. Fizz Buzz

写一个程序,输出从 1n数字的字符串表示。

  1. 如果 n3的倍数,输出“Fizz”
  2. 如果 n5的倍数,输出“Buzz”
  3. 如果 n 同时是3和5的倍数,输出 “FizzBuzz”

思路:

  • 本题重点是将数字转化为字符串
  • 利用头文件<sstream> 中的stringstream类进行数据类型转换
  • 因为传入参数和目标对象的类型会被自动推导出来,所以不存在错误的格式化符的问题

整数转字符串代码

string num2str(int num)
    {
        stringstream ss;
        string s;
        ss<<num;
        ss>>s;
        return s;
    }

题解代码

class Solution {
public:
    vector<string> fizzBuzz(int n) {
        vector<string>result;
        string s;
        for(int i=1;i<=n;i++)
        {
        	//调用整数转字符串代码
            s=num2str(i);
            if((i%3==0)&&(i%5==0))
                s="FizzBuzz";
            else if(i%3==0)
                s="Fizz";
            else if(i%5==0)
                s="Buzz";
            
            result.push_back(s);
        }
        return result;
    }
};

204. 计数质数

统计所有小于非负整数 n的质数的数量。
在这里插入图片描述
思路:(来自官方题解)

  • 本题可以采用暴力枚举,挨个判断是否为质数,但是时间复杂度较高。
  • 枚举法没有考虑到数与数之间的关联性:如果x是质数,那么大于xx的倍数2x3x,…一定不是质数——埃氏筛算法
  • 用数组元素isPrime[i]表示数i是否为质数,是质数则为1,否则为0。
  • 从小到大遍历每个数,如果为质数(isPrime[i]==1),则将其所有的倍数都标记为合数(isPrime[i]=0)(除了该质数本身),即0。
  • 这种方法的正确性是比较显然的:这种方法显然不会将质数标记成合数;另一方面,当从小到大遍历到数x时,倘若它是合数,则它一定是某个小于 x的质数 y的整数倍,故根据此方法的步骤,我们在遍历到 y时,就一定会在此时将 x 标记为 isPrime[x]=0。因此,这种方法也不会将合数标记为质数。
  • 当然这里还可以继续优化,对于一个质数 x,如果按上文说的我们从 2x 开始标记其实是冗余的,应该直接从 x⋅x 开始标记,因为 2x,3x,… 这些数一定在x之前就被其他数的倍数标记过了,例如 2 的所有倍数,3的所有倍数等。

代码

class Solution {
public:
    int countPrimes(int n) {
        vector<int> isPrime(n, 1);
        int ans = 0;
        for (int i = 2; i < n; ++i) {
            if (isPrime[i]) {
                //计数
                ans += 1;
                //遍历前半段
                if ((long long)i * i < n) {
                    //对于质数i,它的a倍数(a=1,2,3...)是合数,先将这些数标记为合数
                    //下次遍历到时跳过它
                    for (int j = i * i; j < n; j += i) {
                        isPrime[j] = 0;
                    }
                }
            }
        }
        return ans;
    }
};
    bool isPrime(int x) {
        for (int i = 2; i * i <= x; ++i) {
            if (x % i == 0) {
                return false;
            }
        }
        return true;
    }

326. 3的幂

给定一个整数,写一个函数来判断它是否是 3 的幂次方。如果是,返回 true ;否则,返回 false

整数 n3 的幂次方需满足:存在整数 x 使得 n == 3^x
在这里插入图片描述
思路:

  • 利用迭代,一直除3,看能不能整除,如果某次对3取余的结果不是0,说明不能整除3,返回false
  • 除到最后商为1时说明全部除尽了
class Solution {
public:
    bool isPowerOfThree(int n) {
       //利用迭代
       if(n==0)
       return false;
       if(n==1)
       return true;
       while(n!=1)
       {
       		//能整除
           if(n%3==0)
           n/=3;
           //不能整除
           else
           return false;
       }
       return true;
    }
};

13. 罗马数字转整数

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M
在这里插入图片描述
例如, 罗马数字 2 写做II,即为两个并列的 1。12 写做 XII,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

  • I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
  • X 可以放在 L (50) 和 C(100) 的左边,来表示 40 和 90。
  • C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
    给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。

思路:

  • 遍历字符串中的每个字符,并对每个字符做判断,将字符对应的整数值加到result中。
  • IXC存在特殊情况,当这三个字符后面跟的字符是上面六种情况的话,要减去对应的整数值。
  • 原理还是很好理解,只是在写判断条件的时候有一点点麻烦,每种特殊情况都要考虑到。

代码

class Solution {
public:
    int romanToInt(string s) {
    	//保存结果
        int result=0;
        for(int i=0;i<s.length();i++)
        {
        	//后面没有特殊字符,做加法
            if((s[i]=='I')&&(s[i+1]!='V')&&(s[i+1]!='X'))
                result++;
            //后面是特殊字符,做减法
            else if((s[i]=='I')&&((s[i+1]=='V')||(s[i+1]=='X')))
                result--;
            
            if(s[i]=='V')
                result+=5;
            if((s[i]=='X')&&(s[i+1]!='L')&&(s[i+1]!='C'))
                result+=10;
            else if((s[i]=='X')&&((s[i+1]=='L')||(s[i+1]=='C')))
                result-=10;

            if(s[i]=='L')
                result+=50;
            if((s[i]=='C')&&(s[i+1]!='D')&&(s[i+1]!='M'))
                result+=100;
            else if((s[i]=='C')&&((s[i+1]=='D')||(s[i+1]=='M')))
                result-=100;
            
            if(s[i]=='D')
                result+=500;
            if(s[i]=='M')
                result+=1000;
        }
        return result;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值