Leetcode 题目记录:231,342,191, 190,172,258,292

#Leetcode 题目记录:231,342,191, 190,172,258,292

这些题其实大多数都是一些数学的小技巧,以及一些数论的知识,我把他们归纳到一起,整理好,方便以后复习


190. 例43261596 (represented in binary as 00000010100101000001111010011100), return 964176192 (represented in binary as 00111001011110000010100101000000).
 * solution:231: 2的幂转换成二进制都是10,100,1000*,所以可以通过位运算100和011的并来判断是否为0
 * 191 342 见代码
 *
 * 326 求3的幂,一般方法,假设m大于n的3的幂,也即m=3^? > n=3^?; 则m % n==0
 * 所以我们求在int范围内最大的3的幂,%n 就行,也就是我们求最大的k,使得3^k 在int范围里最大,然后 %n
 *
 * 190 要求二进制翻转,那么我们可以通过&1 右移来判断每一位是否为1,然后通过左移来实现
 * 这些题着重在于考虑位运算的与非操作,同时将变量换为二进制
 *
 * 172 求n!末尾连续多少个零 n = 1*2*3*4*5.... 又因为10是2和5的乘积,零的数量是最小值2和数量5(因为2的数量大于5)
 * n=2*3*4*5*...*(5^1*2)*....*(5^1*3)..2,所以我们只计算从1到n的所有数字中有多少个5,
 * 5的倍数在1到23之间有5,10,15和20,23!有4个零。
 * 但是注意25是5×5,所以25的每个倍数有5的额外因子,例如25×4 = 100,这引起了额外的零。
 * 所以,我们需要知道25的倍数在1到100,由于100÷25 = 4,在1到100之间有25的倍数。
 * 同样当一个数比较大时还是要知道125,625等
 *
 * 258  num = 38:3 + 8 = 11,1 + 1 = 2。由于2只有一位,返回。下面是我的一般方法,时间复杂度为O(n)
 * ab = a*10+b           ab%9=(a*9+a+b)%9 =(a+b)%9
 * abc = a*100+b*10+c    abc%9=(a*99+b*9+a+b+c)%9 = (a+b+c)%9
 * 但是注意啊,%9的范围只能是[0,8],比如18%9=0; 所以我们可以(n-1)%9=(a+b+c-1)%9 然后在加一
 * (n-1)%9+1
 * 所以有更简单的方法,时间复杂度更低
 *
 * 292 Nim游戏:桌上有一堆石头,每次你们轮流去掉1到3块石头。去掉最后一块石头的人将是胜利者。你会采取第一回合去除石头。
 * 这里注意一个定理:第一个获得4的倍数(即n%4 == 0)的人输,否则将获胜。1,2,3-true 4-false, 5,6,7-true 8-false
 * 因为如果有8个,你第一次不论拿几个,只要第一轮给你留下来4个,你就必输
 * 如果有9,10,11个,你只要给它留下来8个,你就必赢
 */

import com.sun.org.apache.xpath.internal.SourceTree;

import static java.lang.Math.log;
import static java.lang.Math.pow;

public class PowerOfTwoAndOthers {

    static final int maxint = 0x7fffffff;//static 不能修饰局部变量。也就是说方法里不能定义static变量,java定义常量
    static final int minint = 0x80000000;

    //leetcode 231
    public static boolean isPowerOfTwo(int n){
        if(n <= 0) return false;
        return ((n&(n-1)) == 0); //位运算
    }

    //leetcode 342
    public static boolean isPowerOfFour(int n){
        //0x5 0101
        //0x55 0101 0101 。。。0x55555555 0101*(8)
        //刚好用来筛选2 8 32 。。10 1000 100000
        //4 16 64 。。 100 100000 10000000
        //0101 & 100(4) = 100
        //0101 & 1000(8) = 0
        if(n <= 0) return false;
        return (((n&(n-1)) == 0) && ((n&0x55555555) != 0));
    }
    //leetcode 326
    public static boolean isPowerOfThree(int n) {
        if( n <= 0) return false;
        int k = (int) (log(maxint) / log(3));
        int m = (int) pow(3,k);

        return (m % n == 0);

    }

    //leetcode 191
    public static int Numberof1Bits(long n){
        int cout=0;
        // 循环判断每一位是否为1,还有一种方法是n&(n-1),但是要求是无符号整型java里是没有这种数据类型的
        for(int i=0; i<=31; i++){
            if((n&(int)(pow(2,i))) != 0){
                cout += 1;
            }
        }
        //因为是无符号整形,也就是说还有21474834648这个数字,考虑边界范围
        if(n == 0x80000000L){
            return 1;
        }
        /* 其实这个方法是最好的,每次判定结束就右移一位。
        Java中的整数具有32位,例如00101000011110010100001000011010。
        要计算Integer表示中的1,我们输入int n与位1和1(表示为
        00000000000000000000000000000001,如果此操作结果为1,
        这意味着输入整数的最后一位为1.因此,我们将其添加到1s计数。one = ones +(n&1);
        在Java中,我们需要注意的是最大的整数是2147483647.Java中的整数类型是有符号的,没有unsigned int。
        所以输入2147483648用Java表示为-2147483648(在java int类型中有一个循环表示,这意味着Integer.MAX_VALUE + 1 == Integer.MIN_VALUE)。

        int ones = 0;
        while(n!=0) {
            ones = ones + (n & 1);
            n = n>>>1;
        }
        return ones;
         */


        return cout;
    }

    //leetcode 172
    public static int trailingZeroes(int n) {
        int sum = 0;
        while(n > 0){
            sum = sum + n /5;
            n = n / 5;

        }
        return sum;
    }


    //leetcode 190
    public static int reverseBits(int n) {
        int result = 0;
        for(int i = 0; i < 32; i++){
            result = result + (n & 1);//位运算优先级最低
            n = n >>> 1;
            if(i < 31) result = result << 1; //当i=31时,已经是32位了,所以不能在左移了

        }
        return result;
    }

    //leetcode 258
    public int addDigits(int n) {
        /*
        * if(n == 0) return 0;
        *  return (n-1)%9+1
        * */
        int m = 0;
        if(n == 0) return 0;

        while(n != 0){
            m = n % 10 + m;
            n /= 10;
        }
        if( m / 10 != 0){
            m =  addDigits(m);
        }

        return m;
    }

    //leetcode 292
    public boolean canWinNim(int n) {
        if(n % 4 == 0) return false;
        else return true;
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //二进制转换
        int a = 120;//定义一个变量并赋给他一个十进制的值
        int remainder;//定义一个变量用于存储余数
        int sum = 0;//定义一个变量用于存放和
        int k = 1;//定义一个变量控制位数

        while(a != 0){

            remainder = a % 2;//对目标数字求余
            a /= 2;//对目标数字求商
            sum = sum + remainder * k;//求和
            k *= 10;//改变位数

        }

        boolean b = PowerOfTwoAndOthers.isPowerOfTwo(1);
        boolean c = PowerOfTwoAndOthers.isPowerOfFour(64);
        boolean d = PowerOfTwoAndOthers.isPowerOfThree(81);
        long nn = 2147483648L;
        int nnn = PowerOfTwoAndOthers.reverseBits(43261596);
        System.out.println(nn);
        int n = PowerOfTwoAndOthers.Numberof1Bits(2147483648L);
        System.out.println(b);
        System.out.println(n);
        System.out.println(d);
        System.out.println("10进制的123转换为2进制结果为:" + sum );
        System.out.println("nnn==" + nnn);
        System.out.println(PowerOfTwoAndOthers.trailingZeroes(98));
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值