相关用法
相关习题
习题一
找出唯一成对的数
1-1000这1000个数放在含有1001个元素的数组中,只有唯一的一个元素值重复,其他均只出现一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不同辅助存储空间,能否实现?
public class _唯一成对的值 {
public static void main(String[] args) {
int N = 1001;
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;
System.out.println(Arrays.toString(arr));
int x = 0;//异或运算用,任何数和0异或都等于它本身,任何数和它本身异或都为0
for (int i = 0; i < arr.length-1; i++) {
if((arr[i]^arr[N-1]) == 0) { //异或优先级比较低,一般需要用括号括起来
System.out.println("重复值是:"+arr[i]);
}
}
}
}
习题二
找出落单的那个数
一个数组里除了某一个数字之外,其他的数字都出现了两次。请写出程序找出这个只出现一次的数字。
这道题用异或,凡是成对异或的数最后变为0消掉,剩下的数就是落单的数。例如x=A ^ B ^ C ^ B ^ A,最后x=C。
public class _找出落单的那个数 {
public static void main(String[] args) {
int[] arr = {3,4,1,4,5,3,1};
int x = 0;
for (int i = 0; i < arr.length; i++) {
x = x^arr[i];
}
System.out.println("落单的数是:"+x);
}
}
//落单的数是:5
习题三
二进制中1的个数
请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例:9的二进制是1001,有2个1。
基本思想是每次将1往左移一位就与原来的数进行与运算,结果与1移位后相等就计数。
public class _二进制中1的个数 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int k = sc.nextInt();
int count = 0;
String kb = Integer.toBinaryString(k);
System.out.println(k+"的二进制形式:"+kb);
for (int i = 0; i < kb.length(); i++) {
if((k&(1<<i)) == (1<<i))
count++;
}
System.out.println("1的个数:"+count);
}
}
从另外的思考角度想,当一个数(N-1)&N时,它的结果是会消掉从右数起的第一个1,例如整数104的二进制数1101000,减去1,变成1100111,与运算后变为1100000,可见右边的第一个1已经被消去。利用这种特性,可写处另外一种解法:
public class _二进制中1的个数 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int k = sc.nextInt();
int count = 0;
String kb = Integer.toBinaryString(k);
System.out.println(k+"的二进制形式:"+kb);
while(k!=0) {
k=(k-1)&k;
count++;
}
System.out.println("1的个数:"+count);
}
}
/*
54
54的二进制形式:110110
1的个数:4
*/
习题四
用一条语句判断一个整数是不是2的整数次方。
经过上一道题,可以很简单的解答这道题。当一个数是2的整数次方时,它的二进制数中只有一个1。因此有:
public class _判断是否是2的整数次方 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int k = sc.nextInt();
if(((k-1)&k) == 0)
System.out.println("是");
else
System.out.println("否");
}
}
习题五
交换奇数位和偶数位。例如10010110交换后变为01101001,值从150变为105。
具体实现是先保留出偶数位,奇数位消为0,在保留出奇数位,偶数位消为0。然后偶数位向右移动,奇数位向左移动,错位之后做异或运算。由于错位之后,偶数位和奇数位的每一位都是和0做异或,结果还是该位的值本身,所以结果就相当于偶数位和奇数位交换了位置。
public class _交换奇偶位 {
public static void main(String[] args) {
int a = 150;
int b = exc(a);
System.out.println(b);
}
private static int exc(int a) {
int ou = a&0xaaaaaaaa;//0xaaaaaaaa是十六进制的1010 1010 1010...共32位,与运算可以保留二进制数的偶数位
int ji = a&0x55555555;//0x55555555是十六进制的0101 0101 0101...共32位,与运算可以保留二进制数的寄数位
return (ou>>1)^(ji<<1);//偶数位右移一位,奇数位左移一位,再异或
}
}
//105
习题六
0~1之间浮点实数的二进制表示
给定一个介于0-1之间的实数(如0.625),类型为double,打印它的二进制表示(0.101,小数点后的二进制分别表示0.5,0.25,0.125…)如果该数字无法精确地用32位以内的二进制表示,则打印“ERROR”。
public class _转二进制小数 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
double num = sc.nextDouble();
StringBuilder sb = new StringBuilder("0.");
while(num > 0) {
num = num *2;
if(num >=1) {
sb.append("1");
num = num - 1;
}
else {
sb.append("0");
}
}
if(sb.length() > 34) {
System.out.println("ERROR");
}
System.out.println(sb);
}
}
/*0.625
0.101
*/
习题七
出现k次与出现1次
数组中只有一个数出现了1次,其他的数都出现了k次,请输出只出现了1次的数。
利用一下知识:
2位二进制的数字做不进位加法,结果为0
10个十进制的数字做不进位加法,结果为0
k个k进制的数字做不进位加法,结果为0
另外,n个k进制的数做不进位加法时,每一位上的数字是对应位数的和模k的结果。
解法:以k=3为例
1.定义一个数组存放一组数据
2.定义一个二维数组,每个元素是每一个数转换为3进制后再转换成字符串反转再变为字符数组
(这里反转是因为数字变为3进制后的位数并不一致,为了方便比较,反转后位数比较少的可以再后面添0而不影响大小)
3.找出位数最多的是几位
4.遍历二维数组的行和列,行位数不够的添0,然后每一列上的数字相加,存放在另一个新的数组resArr中
5.如果一个数出现3次后,它模3的结果为0.因此遍历数组reaAll,让每一个数模3,结果不是0的就是要找的那个数
public class _出现k次与出现1次 {
public static void main(String[] args) {
int[] arr = {2,2,2,29,7,7,7,3,3,3,6,6,6,0,0,0};
int len = arr.length;
char[][] kRadix = new char[len][];
int k = 3;
int maxlen = 0;
for (int i = 0; i < len; i++) {
kRadix[i] = new StringBuilder(Integer.toString(arr[i], k)).reverse().toString().toCharArray();
if(kRadix[i].length > maxlen) {
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 res = 0;
for (int i = 0; i < maxlen; i++) {
res += (resArr[i]%3)*(int)(Math.pow(k, i)); //相当于做不进位加法后,把数字转为10进制
}
System.out.println(res);
}
}