力扣位运算简单java

19 篇文章 0 订阅
5 篇文章 4 订阅
  1. 多数元素
    给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
    你可以假设数组是非空的,并且给定的数组总是存在多数元素。
    示例 1:
    输入:[3,2,3]
    输出:3
    示例 2:
    输入:[2,2,1,1,1,2,2]
    输出:2
位运算c++
class Solution {
public:
    int majorityElement(vector<int>& nums) {
    int res = 0;
    for(int i = 0 ; i < 32; ++i)
    {
        int ones = 0;
        for(int n : nums)
            ones += (n >> i) & 1;              //位运算法统计每个位置上1出现的次数,每次出现则ones+1
        res += (ones > nums.size()/2) << i;    //如果1出现次数大于1/2数组的长度,1即为这个位置的目标数字
    }
    return res;
    }
};
摩尔投票法
候选人(cand_num)初始化为nums[0],票数count初始化为1。
当遇到与cand_num相同的数,则票数count = count + 1,否则票数count = count - 1。
当票数count为0时,更换候选人,并将票数count重置为1。
遍历完数组后,cand_num即为最终答案。
为何这行得通呢?
投票法是遇到相同的则票数 + 1,遇到不同的则票数 - 1。
且“多数元素”的个数> ⌊ n/2 ⌋,其余元素的个数总和<= ⌊ n/2 ⌋。
因此“多数元素”的个数 - 其余元素的个数总和 的结果 肯定 >= 1。
这就相当于每个“多数元素”和其他元素 两两相互抵消,抵消到最后肯定还剩余至少1个“多数元素”
无论数组是1 2 1 2 1,亦或是1 2 2 1 1,总能得到正确的候选人。
public int majorityElement(int[] nums) {
        if(nums.length <= 0) return 0;
        int res = nums[0];
        int count =1;
        for(int i =1; i< nums.length; i++){
            if(res == nums[i]){
                count++;
            }else if(--count ==0){
              res = nums[i];
               count = 1; 
            }
        }
        return res;
    }
思路
public int majorityElement(int[] nums) {
        if(nums.length <= 0) return 0;
        int res = nums[0];
        int count =1;
        for(int i =1; i< nums.length; i++){
            if(res == nums[i]){
                count++;
            }else{
               count -=1;
               count = 1; 
            }
            
        }
        if(count >=1 ) return res;
        return 0;
    }

  1. 颠倒二进制位
    颠倒给定的 32 位无符号整数的二进制位。
    示例 1:
    输入: 00000010100101000001111010011100
    输出: 00111001011110000010100101000000
    解释: 输入的二进制串 00000010100101000001111010011100 表示无符号整数 43261596,
    因此返回 964176192,其二进制表示形式为 00111001011110000010100101000000。
public class Solution {
    public int reverseBits(int n) {
         public int reverseBits(int n) {
        int res =0;
        for(int i=0; i < 32;i++){
            res <<= 1;
            res += n&1;
            n >>= 1;  
        }
        return res;
    }
}
  1. 2的幂
    给定一个整数,编写一个函数来判断它是否是 2 的幂次方。
    示例 1:
    输入: 1
    输出: true
    解释: 20 = 1
    示例 2:
    输入: 16
    输出: true
    解释: 24 = 16
class Solution {
  public boolean isPowerOfTwo(int n) {
    if (n == 0) return false;
    long x = (long) n;
    return (x & (-x)) == x;
  }
}

  1. 丢失的数字
    给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。
    进阶:你能否实现线性时间复杂度、仅使用额外常数空间的算法解决此问题?
    示例 1:
    输入:nums = [3,0,1]
    输出:2
    解释:n = 3,因为有 3 个数字,所以所有的数字都在范围 [0,3] 内。2 是丢失的数字,因为它没有出现在 nums 中。
    示例 2:
    输入:nums = [0,1]
    输出:2
    解释:n = 2,因为有 2 个数字,所以所有的数字都在范围 [0,2] 内。2 是丢失的数字,因为它没有出现在 nums 中。
由于异或运算(XOR)满足结合律,并且对一个数进行两次完全相同的异或运算会得到原来的数,
因此我们可以通过异或运算找到缺失的数字。
class Solution {
    public int missingNumber(int[] nums) {
        int missing = nums.length;
        for (int i = 0; i < nums.length; i++) {
            missing ^= i ^ nums[i];
        }
        return missing;
    }
}
  1. 4的幂
    给定一个整数,写一个函数来判断它是否是 4 的幂次方。如果是,返回 true ;否则,返回 false .整数 n 是 4 的幂次方需满足:存在整数 x 使得 n == 4x
    示例 1:
    输入:n = 16
    输出:true
    示例 2:
    输入:n = 5
    输出:false

位操作
算法:
我们首先检查 num 是否为 2 的幂:x > 0 and x & (x - 1) == 0。
现在的问题是区分 2 的偶数幂(当 xx 是 4 的幂时)和 2 的奇数幂(当 xx 不是 4 的幂时)。
在二进制表示中,这两种情况都只有一位为 1,其余为 0。
有什么区别?在第一种情况下(4 的幂),1 处于偶数位置:第 0 位、第 2 位、第 4 位等;
在第二种情况下,1 处于奇数位置。
在这里插入图片描述

因此 4 的幂与数字 (101010...10)_2(101010...10)2
​向与会得到 0。即 4^a \land (101010...10)_2 == 04 
a∧(101010...10) 2==0(101010...10)_2(101010...10)2
​ 用十六进制表示为 :(aaaaaaaa)_{16}(aaaaaaaa)16
public boolean isPowerOfFour(int n) {
        if(n ==0 ) return false;
        return (n &(-n)) == n && (n& 0xaaaaaaaa) ==0;
    }
  1. 两整数之和
    不使用运算符 + 和 - ​​​​​​​,计算两整数 ​​​​​​​a 、b ​​​​​​​之和。
    示例 1:
    输入: a = 1, b = 2
    输出: 3
    同样我们可以用三步走的方式计算二进制值相加: 5—101,7—111
    第一步:相加各位的值,不算进位,得到010,二进制每位相加就相当于各位做异或操作,101^111。
    第二步:计算进位值,得到1010,相当于各位进行与操作得到101,再向左移一位得到1010,(101&111)<<1。
    第三步重复上述两步,各位相加 010^1010=1000,进位值为100=(010 & 1010)<<1。
    继续重复上述两步:1000^100 = 1100,进位值为0,跳出循环,1100为最终结果。
    结束条件:进位为0,即a为最终的求和结果。
class Solution {
    public int getSum(int a, int b) {
        while(b != 0){
            int temp = a ^ b;
            b = (a & b) << 1;
            a = temp;
        }
        return a;
    }
}

  1. 找不同
    给定两个字符串 s 和 t,它们只包含小写字母。
    字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。
    请找出在 t 中被添加的字母。
    示例 1:
    输入:s = “abcd”, t = “abcde”
    输出:“e”
    解释:‘e’ 是那个被添加的字母。
    示例 2:
    输入:s = “”, t = “y”
    输出:“y”
思路
public char findTheDifference(String s, String t) {
        if(s.length() ==0) return t.charAt();
        Set<char> set = new HashSet<>();
        char sh = s.charAt();
        set.put(ch);
        char th = t.charAt();
        if(!set.countains(th)) return th;
    }
class Solution {
    public char findTheDifference(String s, String t) {
        int ret = 0;
        for (int i = 0; i < s.length(); ++i) {
            ret ^= s.charAt(i);
        }
        for (int i = 0; i < t.length(); ++i) {
            ret ^= t.charAt(i);
        }
        return (char) ret;
    }
}

面试题 05.01. 插入
给定两个整型数字 N 与 M,以及表示比特位置的 i 与 j(i <= j,且从 0 位开始计算)。
编写一种方法,使 M 对应的二进制数字插入 N 对应的二进制数字的第 i ~ j 位区域,不足之处用 0 补齐。具体插入过程如图所示。在这里插入图片描述

题目保证从 i 位到 j 位足以容纳 M, 例如: M = 10011,则 i~j 区域至少可容纳 5 位。
示例1:
输入:N = 1024(10000000000), M = 19(10011), i = 2, j = 6
输出:N = 1100(10001001100)
示例2:
输入: N = 0, M = 31(11111), i = 0, j = 4
输出:N = 31(11111)

先把数N的j到i之间的位置0
M左移i位
再用N或运算M

例 N = 1011 1111, M = 101, i = 2, j = 4
     (1<<(j-i+1))-1)<<i = 0001 1100 
取反后
     1110 0011
对N于运算
     1011 1111 & 1110 0011 = 1010 0011
M左移动i位
    101 << i = 0001 0100
最后M|N
    0001 0100 | 1010 0011 = 1011 0111 = 183
public int insertBits(int N, int M, int i, int j) {
       int mask=((1<<(j-i+1))-1)<<i;
       mask=~mask;
       N&=mask;
       M=M<<i;
       return M|N;
   }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值