蓝桥杯算法.Java.位运算综合训练

位运算

1、位运算符

两个数之间进行位运算是逐位运算

运算符含义规则例如
&任何二进制位和0运算,结果都是0;和1进行,结果都是原值二者都是一,才为一a & b
|任何二进制位和0运算,结果都是原值;和1进行,结果都是1;二者有一个是一,则为一a | b
~取反0 -> 1 ;1 -> 0 零变成一,一变成零~a
^异或二者相同为0,不同则为1 相异为真a ^ b
<<左移每向左移 1 位,就相当于 *** 2**a<<b
>>右移每向右移 1 位,就相当于 / 2符号位来填充高位a>>b
>>>右移0来填充高位a>>>b

相关性质:
1、交换律:可任意交换运算因子的位置,结果不变
2、结合律:即(a ^ b)^ c = a ^ (b ^ c)
3、对于任何数x,都有x ^ x=0, x ^ 0=x,同自己求异或为0,同 0求异或为自己
4、自反性: A ^ B ^ B = A ^ 0 = A

2、简单入门

第一题:判断奇偶数

& 1 = 1 (奇数) & 1 = 0 (偶数)

参考代码:

Scanner scan = new Scanner(System.in);
int n1 = scan.nextInt();
System.out.println(n1&1);

输出示例:

& 1 = 1 (奇数)

17
1

& 1 = 0 (偶数)

6
0

第二题:获取二进制位是1还是0

( 1 << (x-1) ) & num) >> (x-1) x:求第x位二进制位数上是0还是1 num:原数

意在先左移来做与运算,看这一位二进制位数是0还是1,最后右移,将结果与1进行比较,如相同则返回1,不同则为0

参考代码:

Scanner scan = new Scanner(System.in);
int n1 = scan.nextInt();
System.out.println("n1的第五位二进制位的数:" + (((((1<<4)&n1)>>4)==1)?"1":"0"));

输出示例:

66的二进制为: 01011000

左移四位相当于: 01011000 & 10000 ==> 1&1=1 (&:二者都是一,才为一

88
n1的第五位二进制位的数:1

66的二进制为: 01000010

左移四位相当于:1100100 & 10000 ==> 0&1=0 (&:二者都是一,才为一

66
n1的第五位二进制位的数:0

第三题:交换两个整数变量的值

使用三条异或语句

n1 = n1 ^ n2;
n2 = n1 ^ n2;
n1 = n1 ^ n2;

如:

int n1 = 10、int n2 = 15;

10的二进制为:1010 、20的二进制为:1111

对于异或来说,二者相同为0,不同则为1 n1 ^ n2 = 0 !

第一次n1 ^ n2后,1010 与 1111 相比,结果为:0101 ,此时二进制为0101,赋给了n1

第二次n1 ^ n2后,0101 与 1111 相比,结果为:1010,此时二进制为1010,赋给了n2

第三次n1 ^ n2后,0101 与 1010 相比,结果为:1111,此时二进制为1111,赋给了n1

此时就完成了n1和n2的交换辣!

参考代码:

int n1 = 10;
int n2 = 15;
n1 = n1 ^ n2;
n2 = n1 ^ n2;
n1 = n1 ^ n2;
System.out.println("n1="+n1);
System.out.println("n2="+n2);

输出示例:

n1=15
n2=10

第四题:不用判断语句,求整数的绝对值

x + (x >> 31)) ^ (x >> 31)

与前面的题目如出一辙,这边就省略了嗷qwq

3、综合练习

第一题:找出唯一成对的数

1-1000这1000个数放在含有1001个元素的数组中, 只有唯一的一个元素值重复,其它均只出现一次。每个数组元素只能访问一次, 设计一个算法,将它找出来;不用辅助存储空间,能否设计一个算法实现?

int n = 11;
int[] arr = new int[n];
for(int i = 0;i<arr.length-1;i++)
{
    arr[i] = i+1;
}
arr[arr.length-1]=new Random().nextInt(n-1)+1;//设置最后一个数为随机数
int index = new Random().nextInt(n);//随机下标
swap(arr,index,arr.length-1);//交换
print(arr);
int x = 0;
for(int i = 1; i <= n-1; i++)
{
    x = (x^i);//得1到n-1连续的异或
}
for(int i = 0; i < n;i++)
{
    x = x^arr[i];
}
System.out.println("重复数字:" + x );

注:本篇代码还运用了两个方法:

swap方法:将数组里的数,重复的数随机放置

public static void swap(int[] arr, int p,int q)
{
    int temp = arr[p];
    arr[p] = arr[q];
    arr[q] = temp;
}

print方法:把这个数组里的每一个数都打印出来

public static void print(int[] arr)
{
    for(int i = 0; i < arr.length; i++)
    {
        System.out.print(arr[i]+" ");
    }
    System.out.println();
}

且这道题其实用辅助存储空间解起来更方便点,所以我在下面也放进去了,就不多扩展了嗷(●’◡’●)ノ

参考代码:

import java.util.Random;
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Dog
{
    public static void main(String[] args)
    {
        int n = 11;
        int[] arr = new int[n];
        for(int i = 0;i<arr.length-1;i++)
        {
            arr[i] = i+1;
        }
        arr[arr.length-1]=new Random().nextInt(n-1)+1;//设置最后一个数为随机数
        int index = new Random().nextInt(n);//随机下标
        swap(arr,index,arr.length-1);//交换
        print(arr);
        int x = 0;
        for(int i = 1; i <= n-1; i++)
        {
            x = (x^i);//得1到n-1连续的异或
        }
        for(int i = 0; i < n;i++)
        {
            x = x^arr[i];
        }
        System.out.println("重复数字:" + x );
        
        System.out.println("尝试利用辅助存储空间来解本题");
        int[] helper = new int[n];
        for(int i = 0;i<n;i++)
        {
            helper[arr[i]]++;
        }
        for(int i = 0;i<n;i++)
        {
            if(helper[i]==2)
            {
                System.out.println("重复数字:"+i);
            }
        }

    }
    public static void print(int arr[])
    {
        for(int i = 0; i < arr.length; i++)
        {
            System.out.print(arr[i]+" ");
        }
        System.out.println();
    }
    public static void swap(int arr[], int p,int q)
    {
        int temp = arr[p];
        arr[p] = arr[q];
        arr[q] = temp;
    }
}

输出示例:

1 2 6 4 5 6 7 8 9 10 3 
重复数字:6
尝试利用辅助存储空间来解本题
重复数字:6
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

放下华子我只抽RuiKe5

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值