412. Fizz Buzz
写一个程序,输出从 1
到 n
数字的字符串表示。
- 如果
n
是3
的倍数,输出“Fizz”
; - 如果
n
是5
的倍数,输出“Buzz”
; - 如果
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
是质数,那么大于x
的x
的倍数2x
,3x
,…一定不是质数——埃氏筛算法 - 用数组元素
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
。
整数 n
是 3
的幂次方需满足:存在整数 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中。
I
、X
和C
存在特殊情况,当这三个字符后面跟的字符是上面六种情况的话,要减去对应的整数值。- 原理还是很好理解,只是在写判断条件的时候有一点点麻烦,每种特殊情况都要考虑到。
代码
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;
}
};