小白 刷题 入门 leetcode (五) 数学题目 简单 C++

69. x 的平方根

实现 int sqrt(int x) 函数。 计算并返回 x 的平方根,其中 x 是非负整数。
由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。

解法一
暴力解法,从0开始遍历,判断这个数的平方是否比x大。
需要考虑的点是开方以后可能是小数,不过这不影响我们暴力破解。只要找到一个开方以后稍大于X的数,这个数-1即为答案/
还有一个问题是,如果用integer类型很有可能整数溢出,所以用long。
另一个防止溢出的方法:把i*i换成i/x

class Solution {
public:
    int mySqrt(int x) {
        long i;
        for(i=0;i*i<=x;i++)if(i*i==x)return i;
        return (int)(i-1);
    }
};

解法二:
二分法
如果开方是1的话,是不在我们的区间里面0,因为1/2=0,被舍掉了。

class Solution {
 public:
     int mySqrt(int x) {
         if (x == 0) return 0;
         if (x < 4)return 1;
         int  left = 2, right = x / 2, mid = right / 2;
         while (left <= right) {
             if (mid > x / mid)right = mid - 1;
             else if (mid == x / mid)return mid;
             else left = mid + 1;
             mid = left + (right - left) / 2;
         }
         return right;
     }
 };

解法3:

牛顿求根法的原理和公式推导:

class Solution {
public:
    int mySqrt(int x) {
        double a=x, b=0;
        while(abs(b-a)>=1){
            b=a;
            a=(a+x/a)/2;
        }
        return (int)a;
    }
};

168. Excel表列名称

给定一个正整数,返回它在 Excel 表中相对应的列名称。

解法一:
这个题目还是有一些思路上的困扰,在于取余之前要减一。
顺着十进制取出每位数的思路做这种题,结果不对因为不是从0开始的。十进制是0-9,所以除10取余得到个位数。
本题中,为了得到最后一位数,如果除27取余,就会错乱。除26合理,但是得到0-25,最大的26A取余后是0在最前面,而且26/26是1.,有了一个进位。
所以我想到的办法是n-1,吧1-26变为0-26,这样可以从容地除26取余,也可以顺利的得到后面各位的数。
用十进制类比,本题相当于十进制,但是是1-10十个数而非0-9.

class Solution {
 public:
     string convertToTitle(int n) {
         string s;
         while (n != 0) {
             int i = --n % 26;
             n /= 26 ;
             char c = 'A' + i ;            
             s = c+s;             
         }
         return s;
     }
 };

171. Excel表列序号

给定一个Excel表格中的列名称,返回其相应的列序号。

解法一:

class Solution {
public:
    int titleToNumber(string s) {
        int sum=0, i=0;
        while(i<s.size())
            sum= sum*26+(s[i++] - 'A' + 1);
        return sum;
    }
};
解法二:
直接用pow函数算26的幂再相乘。
class Solution {
public:
    int titleToNumber(string s) {
        int sum=0, i=0;
        while(i<s.size())
            sum+= (s[i] - 'A' + 1)*pow(26,s.size()-1-(i++));
        return sum;
    }
};

172. 阶乘后的零

给定一个整数 n,返回 n! 结果尾数中零的数量。

如果算一个数的阶乘,稍微大点的数用int或者long来存就会溢出。
这也敢叫简单题?
解法一:
通过数学分析找规律,发现只要阶乘的数里有一个5,最后的结果就会有一个0.因为5前面一定有个2,而10可以分解为5*2;
所以问题转化为,n, n-1, n-2……3, 2, 1这些数里5的个数。
从n开始遍历,如果n里有5这个因数,那么n%5==0是真的,在内层循环找到n里所有的5.本思路代码如下:

class Solution {
public:
    int trailingZeroes(int n) {
        int num=0;
        for(;n>0;n--)
            for(int a= n;a%5==0;a/=5)num++;
        return num;
    }
};

但是问题是本思路用时很长,如果有一个很大的数要循环很多次。
解法二:
5是每5个数出现一次,123…10这十个数中5的个数就是10/2.
但是考虑到,每5个5就多一个因数无,也就是n=25时,1234……24 25并不是25/5=5个5,25中有两个5,125中有3个……

class Solution {
public:
    int trailingZeroes(int n) {
        int num=0;
        for(;n>0;n/=5) num+=n/5;
        return num;
    }
};

202. 快乐数

一个“快乐数”定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为> 1,也可能是无限循环但始终变不到 1。如果可以变为 1,那么这个数就是快乐数。

解法一:
这也是一个找规律题目,但是如果找不到规律,就暴力破解一下。
在一定的迭代次数,能不能得到1.
为了计算快乐数,每次对十取余、/10得到最后一位,直到除的只剩了0.

class Solution {
public:
    bool isHappy(int n) {
        int m=0;
        for(int i=10;i>0&&m!=1;i--,n=m)
            for(m=0;n>0;n/=10)   m+=(n%10)*(n%10);
        return m==1;
    }
};

解法二:

如果是无限循环的,那么每次迭代得到的结果一定会有重复。每次计算得到的值,如果在之前的计算中出现过,那么就一定不是快乐数。

使用set来完成这个统计,count() 用来查找set中某个某个键值出现的次数,set中的值都是不重复的,一个键值在set只可能出现0或1次。

class Solution {
public:
    bool isHappy(int n) {
        set<int>s;
        int m=n;
        while(s.count(m)!=1&&m!=1){
            s.insert(m);
            for(m=0;n>0;n/=10) m+=(n%10)*(n%10);
            n=m;
        }
        return m==1;
    }
};

解法三:
判断有没有环可以用快慢指针的方法。在每次循环中,快指针计算一次数的平方和,然后再计算一次,而慢指针只计算一次。
如果快指针能够追上慢指针,那么说明有环的存在,也就是这个数会一直无限循环下去。

class Solution {
public:
    bool isHappy(int n) {
        int fast=n, slow=n;
        do{
            fast=f(fast);
            fast=f(fast);
            slow=f(slow);
        }while(slow!=fast);
        return fast==1;
    }
    int f(int n){
        int m=0;
        for(m=0;n>0;n/=10)   m+=(n%10)*(n%10);
        return m;
    }
};

204. 计数质数

统计所有小于非负整数 n 的质数的数量。

解法一,暴力破解
,但是数太大了就会超时。

~~class Solution {
public:
    int countPrimes(int n) {
        set<int>s;
        s.insert(0);
        s.insert(1);
        for(int i=2; i<n; i++)
            for(int j=i; j<n; j++){
                s.insert(i*j);
                if(i*j>n){
                    break;
                    i=n;
                }
            }
        int num=0;
        for(n=n-1;n>1;n--)if(s.count(n)==0)num++;
        return num;
    }
};~~ 

解法二:
埃拉托色尼筛选法

class Solution {
public:
int countPrimes(int n) {
    int count = 0;
    vector<bool> s(n, true);
    for (int i = 2; i < n; i++) {
        if (s[i]) {
            count++;
            for (int j = i *2; j < n; j += i) s[j] = false;
        }
    }
    return count;
}
};

231. 2的幂

给定一个整数,编写一个函数来判断它是否是 2 的幂次方。

解法一:
思路是,如果一个数是2的幂,那么这个数一直除2,一定会变成2(除非是2^0=1)
2/2一定为1.

class Solution {
public:
    bool isPowerOfTwo(int n) {
        while(n%2==0&&n!=0) n/=2;
        return n==1;
    }
};

解法二:
位运算,如果一个数n2的幂, 那么他的二进制一定是最高位为1,后面全是0.所以n-1是最高位为0,后面全是1,这样做位运算的与就是0.








要处理的特殊情况是为0或者小于0.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值