算法:位运算
Posted nuist__NJUPT
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法:位运算相关的知识,希望对你有一定的参考价值。
位运算
位运算:与 &,或 |,非 ~,异或 ^, 左移 << , 右移 >> >>> : 运算符用0填充高位 >> : 运算符用符号位填充高位 判断奇数与偶数:x & 1 == 1 , x为奇数 ; x & 1 == 0, x为偶数 题1:找出唯一成对的数 1-1000这1000个数放在含有1001个元素的数组中,只有唯一的一个元素值重复,其它均只出现一次。 每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空间,能否设计一个算法实现? 算法思路:利用异或可以消除重复元素,将0和1-1000分别异或,再和arr数组元素分别异或,消除重复元素,剩下的一个元素即是要找的元素。
public class FindNumber {
public static void main(String[] args){
int N = 1001 ;
int [] arr = new int [N] ;
for(int i=0; i<N-1; i++){ //将1-1000存储到数组中
arr[i] = i + 1 ;
}
arr[N - 1] = (int)(Math.random() * 999 + 1) ; //最后一个数字是随机数
for(int i=0; i<arr.length; i++){
System.out.println(arr[i] + " ") ;
}
System.out.println() ;
int value = 0 ;
for(int i=1; i<N; i++){ //0与其它值异或得到其它值
value = value ^ i ;
}
for(int j=0; j<N; j++){ //异或可以消除重复的值
value = value ^ arr[j] ;
}
System.out.println(value) ;
}
}
题2:判断十进制数对应二进制数1的个数 输入一个十进制数字,判断对应二进制数各位上共有多少个1 ? 思路1:number与1按位与,然后1依次左移,number & (1 << i) 等于 1 << i, 则说明number对应二进制该位置为1.
public class CountOne {
public static void main(String[] args){
Scanner input = new Scanner(System.in) ;
int number = input.nextInt() ;
int count = 0 ;
for(int i=0; i<32; i++){
if((number & (1 << i)) == (1 << i)){
count ++ ;
}
}
System.out.println(count) ;
}
}
思路2:将number依次按位右移,然后和1按位与,如果结果为1,则可以说明number对应位置为1
import java.util.Scanner;
public class CountOneNumber {
public static void main(String[] args){
Scanner input = new Scanner(System.in) ;
int number = input.nextInt() ;
int count = 0 ;
for(int i=0; i<32; i++){
if(((number >>> i) & 1 ) == 1){
count ++ ;
}
}
System.out.println(count) ;
}
}
思路3:将number和number-1进行按位与运算,消除最低位,直至number等于0
import java.util.Scanner;
public class CountOneNumber {
public static void main(String[] args){
Scanner input = new Scanner(System.in) ;
int number = input.nextInt() ;
int count = 0 ;
while(number != 0){
number = (number - 1) & number ;
count ++ ;
}
System.out.println(count) ;
}
}
题目3:0~1间浮点实数的二进制表示 键盘输入一个介于0和1之间的实数, (如0.625), 类型为double,打印它的二进制表示(0.101), 因为小数点后的二进制分别表示0.5,0.25,0.125......)如果该数字无法精确地用32位以内的二进制表示,则打印“ERROR” 思路:小数,乘2,取整;整数,除2,取余
import java.util.Scanner;
public class PrintBinaryNumber {
public static void main(String[] args){
Scanner input = new Scanner(System.in) ;
double number = input.nextDouble() ;
StringBuilder result = new StringBuilder("0.") ;
while(number > 0){
double value = number * 2 ;
if(value >= 1){ //乘2,大于等于1,则在结果后面追加1
number = value - 1 ;
result = result.append(1) ;
}
else{ //乘2小于等于1,则在结果后面追加0
number = value ;
result = result.append(0) ;
}
if(result.length() > 34){ //不能用32位表示,则打印ERROR
System.out.println("ERROR") ;
}
}
}
}
题目4: 键盘输入一个正整数,判断一个数字是否是2的整数次方,是则输出YES,否则输出NO。 思路:该正整数对应的二进制数各位上一共只有一个1,因此只需要判断整数数对应二进制数各位上共有1的个数即可。
import java.util.Scanner;
public class TwoPowerDemo {
public static boolean judge(int number){
int count = 0 ;
for(int i=0; i<32; i++){
if((number & (1 << i)) == (1 << i)){
count ++ ;
}
}
if(count == 1){
return true ;
}
return false ;
}
public static void main(String[] args){
Scanner input = new Scanner(System.in) ;
int number = input.nextInt() ;
if(judge(number)){
System.out.println("YES") ;
}else{
System.out.println("NO") ;
}
}
}
题目5:将键盘输入的十进制整数对应的二进制整数的奇偶位互换 思路:将整数与0xaaaaaaaa按位与,提取偶数位,将整数与0x55555555按位与,提取出奇数位,然后将提取出的偶数位右移一位,将提取出的奇数位左移一位,然后将偶数位与奇数位进行异或处理就是将奇数位与偶数位互换。
import java.util.Scanner;
public class SwapOddEven {
public static void main(String[] args){
Scanner input = new Scanner(System.in) ;
int number = input.nextInt() ;
int even = number & 0xaaaaaaaa ;
int odd = number & 0x55555555 ;
int result = (even >> 1) ^ (odd << 1) ;
System.out.println(result) ;
}
}
题目6: 出现k次与出现1次 数组中只有一个数出现了1次, 其他的数都出现了k次, 请输出只出现了1次的数。(假设k等于3) 思路1:将每个数字转换成k进制字符数组并翻转,然后做不进位加法,求出对应的数字就是只出现1次的数字
public class PrintSpecialNumber {
public static void main(String[] args){
int [] arr = {2,2,2,4,4,4,1,7,7,7,3,3,3,6,6,6,0,0,0} ;
int length = arr.length ;
char [][] elements = new char [length][] ;
int k = 3;
int maxLength = 0 ;
//对每个数字,转成k进制字符数组
for(int i=0; i<length; i++){
//求每个数字的三进制字符串并翻转,然后转为字符数组
elements[i] = new StringBuilder(Integer.toString(arr[i],k)).reverse().toString().toCharArray() ;
if(elements[i].length > maxLength){//记录二维数组的最大长度
maxLength = elements[i].length ;
}
}
//做不进位加法
int [] resArray = new int [maxLength] ;
for(int i=0; i<length; i++){
for(int j=0; j<maxLength; j++){
if(j >= elements[i].length) {
resArray[j] += 0;
}
else{
resArray[j] += (elements[i][j] - '0') ;
}
}
}
int result = 0 ;
for(int i=0; i<maxLength; i++){
result += (resArray[i] % k) * (int)Math.pow(k,i) ;
}
System.out.println(result) ;
}
}
思路2:HashMap键值对的方法,将数组元素存为键,数组元素出现的次数存为值,找到对应键的值等于1,则该键就是只出现1次的数字。
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class HashMapDemo {
public static int findKey(int [] arr){
Map<Integer, Integer> map = new HashMap<>() ; //键和值都是Integer类型的HashMap对象
for(int i=0; i<arr.length; i++){
if(map.containsKey(arr[i])){ //键存在
int value = map.get(arr[i]) ; //得到对应的值
map.put(arr[i],value+1) ; //将对应的键值存入到HashMap
}
else{//键不存在
map.put(arr[i],1) ;
}
}
Iterator <Integer> iterator = map.keySet().iterator() ;//迭代器对象
while(iterator.hasNext()){//遍历迭代器对象
int key = iterator.next() ;
if(map.get(key) == 1){ //对应键的值等于1,则只出现1次
return key ;
}
}
return -1 ;
}
public static void main(String[] args){
int [] arr = {1,1,1,2,2,2,4,4,4,3,5,5,5} ;
if(findKey(arr) != -1){
System.out.println(findKey(arr)) ;
}
}
}
以上是关于算法:位运算的主要内容,如果未能解决你的问题,请参考以下文章