第一章 位运算
第一章 位运算
一.运算符号:
&(与)、|(或)、^(异或)、~(非/取反);>>(二进制右移,用符号位填充高位)、<<(左移);>>>(用0填充高位);(无<<<);
二.题目:
思路:
法一 .^(异或):两个相同的数异或得0,根据这一特点:
(1)遍历1-1000,得到一个含有1-1000元素的数组x1。
(2)将创建的数组x1与原数组arr进行异或运算,得到的即为所求。
法二.暴力算法:
(1)创建一个数组helper。
(2)将原数组arr中的元素作为helper的下标进行遍历,每遍历一次:helper[arr[i]]++。
(3)遍历helper,如果为2,则输出helper的下标,即为所求。
import java.util.Random;
import java.util.Arrays;
public class 唯一成对的数1_1 {
public static void main(String[] args)
{
int N=1001;
int [] arr=new int[N];
for(int i=0;i<N-1;i++){
arr[i]=i+1;
}
//产生随机数
arr[N-1]=new Random().nextInt(N-1)+1;//1~10之间的整数
//随机下标
int index=new Random().nextInt(N);//0~10
swap(arr,index,arr.length-1);//arr[arr.length-1]与arr[index]交换
System.out.println(Arrays.toString(arr));//输出
//法一:
int x1=0;
for(int i=0;i<N-1;i++){
x1=x1^(i+1);
}
for(int i=0;i<N;i++){
x1=arr[i]^x1;
}
System.out.println(x1);
//法二
int[] helper= new int[arr.length];
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);
break;
}
}
}
//数组元素的交换
private static void swap(int[] arr,int i,int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
思路:异或(依据:x^x=0)
import java.util.Scanner;
public class 找出落单的数1_2 {
public static void main(String[] args)
{
Scanner sc=new Scanner(System.in);
int N=sc.nextInt();
int[] arr=new int[N];
for(int i=0;i<N;i++){
arr[i]=sc.nextInt();
}
find1(arr);
}
public static void find1(int[] arr){
int x1=0;
for (int i=0;i<arr.length;i++){
x1=x1^arr[i];
}
System.out.println(x1);
}
}
题3:二进制中1的个数
思路:
法一.左移<< : (num&(1<<i))==(1<<i)
法二.右移>>> : ((num>>>i)&1)==1
法三.-1,再&
import java.util.Scanner;
public class 二进制中1的个数1_3 {
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
int num=sc.nextInt();
System.out.println(Integer.toString(num,2));
//--------------法一:左移 1<<i
int count=0;
for(int i=0;i<32;i++)
{
if((num&(1<<i))==(1<<i))
{
count++;
}
}
System.out.println(count);
//--------------法二:右移
count=0;
for(int i=0;i<32;i++)
{
if(((num>>>i)&1)==1)
{
count++;
}
}
System.out.println(count);
//--------------法三:-1,再&
count=0;
while(num!=0)
{
num=((num-1)&num);
count++;
}
System.out.println(count);
}
}
思路:
只需判断其二进制数中1只出现在一个位上或者无1。
if(((N-1)&N)==0){
System.out.println("yes");
}
思路:
(1)分离出奇数位和偶数位对应的数字:与运算;
(2)再将奇偶数位对应的数字替换:位运算–偶数位右移,奇数位左移。
import java.util.Scanner;
public class 将整数的奇偶位互换1_5 {
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
int x1=sc.nextInt();
int x2=exchange(x1);
System.out.println(x2);
}
private static int exchange(int x){
/* * 做与运算分别取出偶数位,奇数位 */
int even=x&0xaaaaaaaa;//1010 1010 ……(16位)对应的16进制:0xaaaaaaaa
int odd =x&0x55555555;//0101 0101 ……
return (even>>1)^(odd<<1);//达到互换的效果
}
}
import java.util.Scanner;
public class 一以内的浮点数的二进制表示1_6 {
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
double n=sc.nextDouble();
ToBin1(n);
ToBin2(n);
}
//法一
public static void ToBin1(double x){
StringBuffer s=new StringBuffer("0.");
int i=1;
for ( ;i<=32;i++){
x=x*2;
s.append((int)x/1);
x=x%1;
if(x==0)
break;
}
if(i>32){
System.out.println("Error");
return;
}
System.out.println(s);
}
//法二
public static void ToBin2(double num){
StringBuilder s=new StringBuilder("0.");
while(num>0){
//乘2:挪整
double r=num*2;
//判断整数部分
if(r>=1){
s.append("1");
//消除整数部分
num=r-1;
}else {
s.append("0");
num=r;
}
if(s.length()>34){
//前面“0.”占2个字符
System.out.println("Error");
return;
}
}
System.out.println(s);
}
}
思路:
k个相同的数对应的k进制相加,若不进位,相应位上为0;
public class 出现K次与出现1次1_7 {
public static void main(String[] args){
int[] arr={
2,2,2,9,7,7,7,3,3,3,6,6,6,0,0,0,2,2,2,7,7,7,3,3,3,6,6,6,0,0,0};
int len=arr.length;
char[][] kRadix=new char[len][];//二维数组:存放k进制数
int k=6; //k次
int maxLen=0;//数转为k进制中的最长长度
//转成k进制字符数组
//对于每个数字
for(int i=0;i<len;i++){
//求每个数字的k进制字符串并翻转,然后转为字符数组
kRadix[i]=new StringBuilder(Integer.toString(arr[i],k)).reverse().toString().toCharArray();
if(maxLen<kRadix[i].length)
maxLen=kRadix[i].length;
}
int[] resArr=new int[maxLen];
for(int i=0;i<len;i++){
//不进位加法
for(int j=0;j<maxLen;j++){
if(j>=kRadix[i].length)
resArr[j]+=0;
else{
resArr[j]+=kRadix[i][j]-'0';
}
}
}
int result=0;
for(int i=0;i<maxLen;i++){
//k进制每位余数乘对应的k次方--得到所求数字
result+=(resArr[i]%k)*Math.pow(k,i);
}
System.out.println(result);
}
}
三. 扩:
1.产生一个随机数:
new Random().nextInt(10) //产生0~9的整数
2.用户输入:
Scanner sc=new Scanner(System.in);
int n=sc.nextInt(); //用户输入整数
3.输出数组:
System.out.println(Arrays.toString(arr));
4.Java修饰符区别及使用情况:
类内部 | 本包 | 子类 外部类 | |
---|---|---|---|
public | ✔ | ✔ | ✔ ✔ |
protected | ✔ | ✔ | ✔ ✘ |
default | ✔ | ✔ | ✘ ✘ |
private | ✔ | ✘ | ✘ ✘ |
5.StringBuffer(如:):
StringBuffer s=new StringBuffer(“0.”);
s.append(“0”);
6.>>与>>>区别:
右移运算符 | 有无符号 | 移到右端的低位被舍弃,最高位? | 举例 b=11010011 |
---|---|---|---|
>> | 有符号 | 移入原来低位的值 | b>>2 = 11110100 |
>>> | 无符号 | 补0 | b>>>2 = 00110100 |
7.求数字n的k进制字符串并翻转,然后转为字符数组:
kRadix=new StringBuilder(Integer.toString(n,k)).reverse().toString().toCharArray();