zoukankan      html  css  js  c++  java
  • LeetCode算法题-Number Complement(Java实现-五种解法)

    这是悦乐书的第240次更新,第253篇原创

    01 看题和准备

    今天介绍的是LeetCode算法题中Easy级别的第107题(顺位题号是476)。给定正整数,输出其补码数。补充策略是翻转其二进制表示的位。例如:

    输入:5
    输出:2
    说明:5的二进制表示为101(无前导零位),其补码为010,因此需要输出2。

    输入:1
    输出:0
    说明:1的二进制表示形式为1(无前导零位),其补码为0,因此需要输出0。

    注意:

    • 保证给定的整数适合32位有符号整数的范围。

    • 您可以假设整数的二进制表示中没有前导零位。

    本次解题使用的开发工具是eclipse,jdk使用的版本是1.8,环境是win7 64位系统,使用Java语言编写和测试。

    02 第一种解法

    先将正整数转为二进制字符串,然后变成字符数组,将其中的0变成1,1变成0,再将字符数组变为字符串,最后将字符串转为二进制数。

    public int findComplement(int num) {
        String str = Integer.toBinaryString(num);
        char[] arr = str.toCharArray();
        for (int i=0; i<arr.length; i++) {
            if (arr[i] == '0') {
                arr[i] = '1';
            } else {
                arr[i] = '0';
            }
        }
        return Integer.parseInt(String.valueOf(arr), 2);
    }
    

    03 第二种解法

    我们可以仔细观察题目所给的示例:

    5表示的二进制数为101,最后的结果是2,所表示的二进制数为10,如果我们将其前导0补齐,就会发现101通过计算后要得到010,那么需要借助怎样的计算呢?

    借助位运算,101^111 = 010,我们使用二进制数111和101做异或运算就可以得到最后的结果。

    因此,我们需要获取num表示的二进制数长度,来组成一个由1组成新二进制数(长度和num表示的二进制数一致),再将两数做异或运算即可。

    异或运算的规则是两边的对应位不同时,取1,否则取0。

    public int findComplement2(int num) {
        String str = Integer.toBinaryString(num);
        String str2 = "";
        for (int i=0; i<str.length(); i++) {
            str2 += "1";
        }
        int res = Integer.parseInt(str2, 2);
        return num^res;
    }
    

    04 第三种解法

    还是第二种解法的思路,只不过将字符串操作换为了位运算操作,我们先将num右移,计算其二进制数有多少位,记为i,然后再对1进行左移i位,移完后得到的二进制数是1个1加上i个0,而不是i个1,所以我们需要减去1使其变成i个1,最后和num做异或运算并返回其结果。

    public int findComplement3(int num) {
        if (num == 0) {
            return 1;
        }
        int i = 0;
        while ((num>>i) != 0) {
            i++;
        }
        int res = (1<<i)-1;
        return num^res;
    }
    

    05 第四种解法

    还是第二种解法的思路,与第三种解法的位运算不同,借助包装类和位运算来一起完成计算,Integer类的highestOneBit方法,取的是其二进制数左侧的最高位1,因为本题的输入参数为正数,可以不用考虑负数、反码、补码的问题。获得最高位所表示的整数后,再左移一位,然后再减1,最后还是和num进行异或运算,并返回结果。

    public int findComplement4(int num) {
        if (num == 0) {
            return 1;
        }
        int res = (Integer.highestOneBit(num)<<1) - 1;
        return num^res;
    }
    

    06 第五种解法

    还有一种做法,也借助位运算,使用与(&)运算,在进行与运算之前,我们先要把与运算两边的数准备好。左边的数是对num进行非运算,右边的数还是需要借助Integer类的highestOneBit方法,获取最高位1所表示的整数再减去1,然后两个新的数进行与运算,并返回结果。以题目中的5为例:

    左边:对5进行非运算,得到-6

    右边:5的二进制数最高位1表示为整数4,减去1为3

    3

    00000000000000000000000000000011

    -6

    10000000000000000000000000001010

    当相同的位上均为1时结果为1,否则结果为0

    00000000000000000000000000000010

    也就是整数2。

    public int findComplement5(int num) {
        return ~num & (Integer.highestOneBit(num) - 1);
    }
    

    07小结

    算法专题目前已日更超过三个月,算法题文章107+篇,公众号对话框回复【数据结构与算法】、【算法】、【数据结构】中的任一关键词,获取系列文章合集。

    以上就是全部内容,如果大家有什么好的解法思路、建议或者其他问题,可以下方留言交流,点赞、留言、转发就是对我最大的回报和支持!

  • 相关阅读:
    JDBC获取数据库表字段信息
    No bean named 'springSecurityFilterChain' is defined
    VS 2010中对WPF4有哪些多点触摸支持?
    文件管理File类
    VS 2010 Beta2中WPF有哪些改进?
    WPF的实质
    C#中AppDomain.CurrentDomain.BaseDirectory与Application.StartupPath的区别
    VS 2010 Beta2中WPF与Silverlight的关键区别?
    C# 图片与byte[]之间以及byte[]与string之间的转换
    日期格式化{0:yyyyMMdd HH:mm:ss.fff}和{0:yyyyMMdd hh:mm:ss.fff}的区别
  • 原文地址:https://www.cnblogs.com/xiaochuan94/p/10312532.html
Copyright © 2011-2022 走看看