LeetCode 476. Number Complement (数字的补数)C++ JAVA实现

Given a positive integer, output its complement number. The complement strategy is to flip the bits of its binary representation.

Note:

  1. The given integer is guaranteed to fit within the range of a 32-bit signed integer.
  2. You could assume no leading zero bit in the integer’s binary representation.

Example 1:

Input: 5
Output: 2
Explanation: The binary representation of 5 is 101 (no leading zero bits), and its complement is 010. So you need to output 2.

 

Example 2:

Input: 1
Output: 0
Explanation: The binary representation of 1 is 1 (no leading zero bits), and its complement is 0. So you need to output 0.

给定一个正整数,输出它的补数。补数是对该数的二进制表示取反。

注意:

  1. 给定的整数保证在32位带符号整数的范围内。
  2. 你可以假定二进制数不包含前导零位。

示例 1:

输入: 5
输出: 2
解释: 5的二进制表示为101(没有前导零位),其补数为010。所以你需要输出2。

示例 2:

输入: 1
输出: 0
解释: 1的二进制表示为1(没有前导零位),其补数为0。所以你需要输出0。

思路一:计算出num的原码,再取反求补数。

C++实现:

class Solution {
public:
    int findComplement(int num) {
        vector <int> temp;
        while(num)
        {
            temp.push_back(num%2);
            num /= 2;
        }
        int sum = 0 , j = 0;
        for(int i = 0; i < temp.size(); i++)
        {
            temp[i] = temp[i] > 0? 0 : 1;
            sum += temp[i]*pow(2,j);
            j++;
        }
        return sum;
    }
};

C++代码实现二:

class Solution {
public:
    int findComplement(int num) 
    {
        int tmp = num, count = 0;
        if(num == 0)
            return 1;
        while(tmp)
        {
            tmp = tmp &(tmp -1);
            count++;
        }
        
        for(int i = 0; i < 32 && count; i++)
        {
            if(num & (1 << i))
            {
                count--;
            }
            else
            {
                tmp |= (1 << i);
            }
        }
        return tmp;
    }
};

 

思路二:

如果我们能知道该数最高位的1所在的位置,就可以构造一个长度和该数据所占位置一样长的一个掩码mask,然后概述和mask进行异或即可。

例如:5的二进制是101,我们的构造的掩码为mask=111,两者异或则为010,即是所要的结果。这里和计算机网络中IP地址的子网掩码比较相似,如10的二进制为0000 1010,其掩码为0000 1111,1表示二进制的有效位,两者进行异或时恰好等同于对原码取反(因为掩码有效位始终为1,则当原码中为1时 异或为0 ,原码中为0时 异或为1)。那么如何求得该数的掩码呢,由0001 0000 - 0000 0001 = 0000 1111可看出,只要求得num二进制的最高位,将该位再左移一位,减1即可得到该数的掩码。

java代码实现一:

public class Solution {
    public int findComplement(int num) {
        int mask = 1, temp = num;
        while(temp > 0) {
            mask = mask << 1;
            temp = temp >> 1;
        }
        return num^(mask-1);
    }
}

java代码实现二:

public class Solution {
    public int findComplement(int num) {
        int mask = (Integer.highestOneBit(num) << 1) - 1;
        return num^mask;
    }
}

Integer.highestOneBit(i)是一个什么样的函数呢?通过查看文档得知,这个函数的作用是取 i 这个数的二进制形式最左边的最高一位且高位后面全部补零,最后返回int型的结果。

来看下  Integer.highestOneBit (i) 这个函数的实现代码:

publicstaticinthighestOneBit(int i) {  
     // HD, Figure 3-1  
     i |= (i >>  1);  
     i |= (i >>  2);  
     i |= (i >>  4);  
     i |= (i >>  8);  
     i |= (i >> 16);  
     return i - (i >>> 1);  
 }

1、第一步的作用是把最高位1右移移位,并与原数据按位取或。那么这就使得最高位和它的下一位是连续两个1。

2、第二步的作用是把刚刚移位得到连续两个1继续右移两位并与原数据按位取或。那么这就使得最高两位和它的下两个连续位组成四个连续的1。

3、 以此类推,最终得到的i是从开始的最高位到结束全是1。并减去i不带符号的右移一位,即可得到一个int数据的最高位的值。

4、上述情况是针对于i不为零和负数的情况,如果i为零,那么得到的结果始终为零。如果i位负数,那么得到的结果始终是-2147483648。即等于Integer.MIN_VALUE。(原因在于负数的最高位始终为1,即是负数的符号位)

 

此函数的最重要理解点在与要始终把握二进制的最高位进行运算处理,那么对于函数中的右移一位、两位、四位、八和十六位就好理解了。同理,对于long类型的取最高位运算应该需要加一条语句 i|=(i>>32); 原因在于long类型在Java中是64位的。
Long类型的hightestOneBit(i)代码如下:

public static long highestOneBit(long i) {  
    // HD, Figure 3-1  
    i |= (i >>  1);  
    i |= (i >>  2);  
    i |= (i >>  4);  
    i |= (i >>  8);  
    i |= (i >> 16);  
    i |= (i >> 32);  
    return i - (i >>> 1);  
}

 

java代码实现三:

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

java代码实现四:

public class Solution {
    public int findComplement(int num) {
        char[] ch = Integer.toBinaryString(num).toCharArray();
        int ret = 0;
        for(int i = 0; i < ch.length; i++) {
            if(ch[i] == '0') {
                ret += Math.pow(2, ch.length - i - 1);
            }
        }
        return ret;
    }
}

java代码实现五:

class Solution {
    public int findComplement(int num) {
        String str=Integer.toBinaryString(num);
        char[] a=str.toCharArray();
        char[] b=new char[a.length];
        for(int i=0;i<a.length;i++){
            if(a[i]=='0'){
                b[i]='1';
            }else if(a[i]=='1'){
                b[i]='0';
            }
        }
        String c=new String(b);
        int nums=Integer.parseInt(c,2);
        return nums;
    }
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用Java中的排序功能来实现。可以使用Arrays.sort()函数,将列表中的元素按照字母顺序排序,或者使用Collections.sort()函数,将列表中的元素按用户指定的排序规则排序。 ### 回答2: 为了实现LeetCode 2561题(Rearranging Fruits)的要求,需要使用Java编程语言。主要思路是遍历给定的水果数组,同时用一个哈希表来记录每个水果出现的次数。然后根据题目要求,重新排列水果使得相同类型的水果尽可能接近,并且按照出现次数的非递增顺序排序。 具体实现步骤如下: 1. 创建一个HashMap来存储每个水果的出现次数。遍历给定的水果数组,如果该水果已经存在于HashMap中,则将其出现次数加1;否则,将该水果添加到HashMap,并将其出现次数初始化为1。 2. 创建一个ArrayList来存储已经排列好的水果。通过HashMap的entrySet方法获取到每种水果和它的出现次数,然后将这些entry按照出现次数的非递增顺序进行排序。 3. 遍历排序好的entry集合,根据每个水果的出现次数,在ArrayList中连续添加相应数量的水果。 4. 返回排列好的水果数组。 以下是Java代码的示例实现: ```java import java.util.*; class Solution { public String[] rearrange(String[] fruits) { HashMap<String, Integer> fruitCountMap = new HashMap<>(); // 统计每个水果的出现次数 for (String fruit : fruits) { if (fruitCountMap.containsKey(fruit)) { fruitCountMap.put(fruit, fruitCountMap.get(fruit) + 1); } else { fruitCountMap.put(fruit, 1); } } ArrayList<Map.Entry<String, Integer>> sortedEntries = new ArrayList<>(fruitCountMap.entrySet()); // 根据出现次数进行非递增排序 Collections.sort(sortedEntries, new Comparator<Map.Entry<String, Integer>>() { public int compare(Map.Entry<String, Integer> entry1, Map.Entry<String, Integer> entry2) { return entry2.getValue().compareTo(entry1.getValue()); } }); ArrayList<String> rearrangedFruits = new ArrayList<>(); // 根据出现次数连续添加水果 for (Map.Entry<String, Integer> entry : sortedEntries) { String fruit = entry.getKey(); int count = entry.getValue(); for (int i = 0; i < count; i++) { rearrangedFruits.add(fruit); } } return rearrangedFruits.toArray(new String[0]); } } ``` 使用以上代码,可以对给定的水果数组进行重新排列,使得相同类型的水果尽可能接近,并且按照出现次数的非递增顺序进行排序。返回的结果就是排列好的水果数组。 ### 回答3: 题目要求将一个字符串中的水果按照特定规则重新排列。我们可以使用Java实现这个问题。 首先,我们需要定义一个函数来解决这个问题。 ```java public static String rearrangeFruits(String fruits) { // 将字符串转换为字符数组方便处理 char[] fruitArray = fruits.toCharArray(); // 统计每种水果的数量 int[] fruitCount = new int[26]; for (char fruit : fruitArray) { fruitCount[fruit - 'a']++; } // 创建一个新的字符数组来存储重新排列后的结果 char[] rearrangedFruitArray = new char[fruitArray.length]; // 逐个将水果按照规则放入新数组中 int index = 0; for (int i = 0; i < 26; i++) { while (fruitCount[i] > 0) { rearrangedFruitArray[index++] = (char) ('a' + i); fruitCount[i]--; } } // 将字符数组转换为字符串并返回 return new String(rearrangedFruitArray); } ``` 上述代码中,我们首先将字符串转换为字符数组,并使用一个长度为26的数组来统计每一种水果的数量。然后,我们创建一个新的字符数组来存储重新排列后的结果。 接下来,我们利用双重循环将每一种水果按照规则放入新数组中。最后,我们将字符数组转换为字符串并返回。 例如,如果输入字符串为`"acbba"`,则经过重新排列后,输出结果为`"aabbc"`。 这样,我们就用Java实现了题目要求的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值