lintcode天梯4- 数学与二进制运算

LintCode Ladder4 - Math$Bit Manipulation

1、Flip Bits

题目:给你两个数字A和B,问你需要改变A的二进制位的几个位使其变成B。

Example:
A = 31(11111)
B = 14(01110)
return 2;
只需要修改第一位和第5个二进制位即可。

分析:
从题目的意思,我们可以直接比较所有对应的二进制位,因为A和B都是32位的整数。我们可以直接比较所有的32位,记录不同的位置的个数即可。
继续想,既然是相同的位置对赢得0-1不同,那不就是异或操作了吗,于是我们可以领 C = A ^ B.计算C的1的个数就是最终的结果。

Code:

class Solution {
public:
    /**
     *@param a, b: Two integer
     *return: An integer
     */
    int bitSwapRequired(int a, int b) {
        // write your code here
        int cnt = 0, x = a ^ b;
        for(int i = 0;i < 32;i++){
            cnt += ((x & (1 << i)) != 0); 

        }
        return cnt ;
    }
};

2、O(1) Check Power of 2

题目:使用O(1)的时间,判断一个数n是不是2的幂次方。

Example:
n = 4, return true;
n = 5, return false;

分析:
1、如果是一个数n = 2 ^ i.只需要对这个n判断是否能够被2除,到达1。如果可以达到1就return true;else return false。
2、但是题目要求是O(1)的操作,上面的解法显然不是O(1)的操作,而是O(logn)。分析一个一个数n如果可以表示成
n = 2 ^ i, (i>=0)。
n = (1000..000) 首先1个1,接着i个0。
n-1 = (0111..111) 首先1个0,接着i个1.
而且有 n & (n-1) = 0。
于是得到计算公式,n满足上式的都是2的幂次方。

Code:

class Solution {
public:
    /*
     * @param n: An integer
     * @return: True or false
     */
    bool checkPowerOf2(int n) {
        // write your code here
        if(n<=0) return 0;
        return (n&(n-1))==0;
    }
};

3、Trailing Zeros

题目:给你一个数n,计算n!的末尾的0的个数。

Example:
11! = 39916800, so should return 2.

分析:
对于这个题,我们可以想到一个知识,怎么才能在末尾出现0,一个数k * 10会在末尾出现一个0,又因为10可以分解素因子10 = 2 * 5。于是我们只需要知道n! 中素因子分解后,2的个数count(2)和5的个数count(5)的最小值即可。answer = min(count(2), count(5))。
1、根据素因子分解的原理,count(2)>=count(5).
2、计算出count(5)的个数。
3、根据 Legendre’s formula
vp(n!)=1npi 链接

Code:

class Solution {
 public:
    // param n : description of n
    // return: description of return 
    long long trailingZeros(long long n) {
        long long cnt = 0;
        while(n){
            cnt += n / 5;
            n /= 5;
        }
        return cnt;
    }
};

4、Update Bits

题目描述:给出两个32位的整数N和M,以及两个二进制位的位置i和j。写一个方法来使得N中的第i到j位等于M(M会是N中从第i为开始到第j位的子串)

Example:
给出N = (10000000000)2,
M = (10101)2, i = 2, j = 6
返回 N = (10001010100)2

分析:
我们可以直接想到,让N减去[i-j]对应位的值,再加上M左移i位的值,就是替换之后的值。
1、将N转化为二进制,计算[i-j]对应的位的值t,(n-t)+(m<

class Solution {
public:
    /**
     *@param n, m: Two integer
     *@param i, j: Two bit positions
     *return: An integer
     * 将n分成三段 a[0-i) b[i-j] c(j-N]
     * 掩码的问题,需要仔细考虑
     */
    int updateBits(int n, int m, int i, int j) {
        // write your code here
        int mask;
        if(j<31){
            mask=~((1<<(j+1))-(1<<i));
        }else{
            mask=(1<<i)-1;
        }
        return (m<<i)+(n&mask);

    }
};

5、Unique Binary Search Trees

题目:给出 n,问由 1…n 为节点组成的不同的二叉查找树有多少种?

分析:这是有公式的题目,问题是能不能记住这个公式。
h(n)=(4i2)h(n1)n+1
h(1)=1

Code:

class Solution {
public:
    /**
     * @paramn n: An integer
     * @return: An integer
     * catalan Number
     * h(n)=((4*n-2)/(n+1))*h(n-1);
     */
    int numTrees(int n) {
        // write your code here
        if(n==0) return 1;

        long long h = 1; //防止数值上溢
        for(int i=2;i<=n;i++){
            h = ((4*i-2)*h/(i+1));
        }
        return h; 

    }
};

6、Fast Power

题目:计算 an%b 的值,其中a,b和n都是32位的整数。

分析:
经典的二分快速幂,
a^n%b == a^(n/2)%b * a^(n/2)%b; n%2==0;
a^n%b == a^(n/2)%b * a^(n/2)%b * a%b; n%2==1;

Code:

class Solution {
public:
    /*
     * @param a, b, n: 32bit integers
     * @return: An integer
     */

    int fastPower(int a,int b,int n){//bud
        if(n==0) return 1%b;
        long long ans=1;
        long long x=a;
        while(n){

            if(n&1) ans=ans*(x%b)%b;

            x=((x%b)*(x%b))%b;

            n=n>>1;

        }
        return ans;

    }

    int fastPower1(int a,int b,int n){//递归形式,当然也有迭代形式
        long long ans=1;
        if(n==0) return 1%b;
        if(n==1) return a%b;
        long long x=fastPower(a,b,n>>1);//注意中间精度溢出

        ans=((x%b)*(x%b))%b;
        if(n&1){//n=2*k+1
            ans=(ans*(a%b))%b;
        }
        return ans;
    }
};

7、Binary Representation

题目:给定一个数将其转换为二进制(均用字符串表示),如果这个数的小数部分不能在 32 个字符之内来精确地表示,则返回 “ERROR”。

Example:
n = “3.72”, 返回 “ERROR”.
n = “3.5”, 返回 “11.1”.

分析:这个题其实很简单,就是模拟的时候需要注意一些问题。
1、找到小数点,分成两部分处理,整数和小数。
2、小数部分是每次乘以2
3、整数部分是除以2.
4、注意小数的不能满足的情况。

Code:

class Solution {
public:
    /**
     *@param n: Given a decimal number that is passed in as a string
     *@return: A string
     */

    string Int2Binanry(string n){
        string s = "";
        int t = 0;
        for(int i=0;i<n.size();i++){
            t = t*10 + (n[i] - '0');
        }
        if(t==0) s="0";
        while(t){
            s += char(t%2 + '0');
            t /= 2;
        }
        reverse(s.begin(),s.end());

        return s;
    }

    //处理小数部分
    string DecBinary(string n){
        string s = "";
        long long t = 0; // long long 防止乘法越界上溢
        for(int i=0;i<n.size();i++){
            t = t*10 + (n[i] - '0');
        }
        int k = 0;
        long long m = (long long)pow(10,n.size());
        //cout<<t<<" "<<m<<endl;
        while(k<32){
            s += (t*2 / m) + '0';
            t = t * 2 % m;
            if(t==0) break;
            k ++;
        }
        if(k >= 32) s = "2";
        return s;
    }

    string binaryRepresentation(string n) {
        // wirte your code here
        if(find(n.begin(), n.end(), '.') == n.end()) n += '.';

        //cout<<n<<endl;
        string::iterator it = find(n.begin(), n.end(), '.');
        string f(n.begin(),it);
        string d(it+1,n.end());
        //cout<<f<<endl;
        //cout<<d<<endl;
        string fs = Int2Binanry(f);
        string ds = Dec2Binary(d);

        if(ds == "2") return "ERROR";

        if(ds=="" || ds=="0") return fs;
        return fs+'.'+ds;

    }
};

ps: 欢迎批评指正,喵~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值