[置顶] 与位运算相关的编程算法技巧的总结java实现
2017-03-11 16:08
489 查看
与位运算相关的编程算法技巧的总结java实现
计算机所有的运算最终都是转换为位运算和移位的操作,效率也很高,在很多场合具有很强的技巧,所以做个总结供大家学习。
1.1 交换a,b的值,不使用第三个变量?
通常使用第三个变量:
法一:【法一需要考虑a+b会不会超过a表达的数值范围,导致内存溢出】
法二:
------------------------------------------------------------------------------------------------------------------------------------------------
1.2 实现一个函数,输入一个整数,输出为该整数的二进制表示有多少个1?
思路1::判断该整数是否能被2整除,如果不能被2整除,则最后一位肯定为1,计数器加一,然后右移一位;
存在问题:如果把移位改为除以2,那样效率又太低,如果输入时一个负数,0x8000 0000右边移动一位,变为0xC000 0000 。而不等价于理想的右移动一位的时候相当于除以2,得0x4000 0000。这样最终就会都变为1,引起死循环;
思路2:思路1中右移n可能会导致是负数的时候造成死循环。那么我们改进,每次左移1.
思路3: (n-1)&n相当于把n的最右边一个1变为0;
n-1:相当于把最右边的1变为0,左边保持不变,该1右边的0变为1;10100---减1--->10011
(n-1)&n:10100---&---10011------------> 10 000
------------------------------------------------------------------------------------------------------------------------------------------------
1.3 实现一个函数不用加减乘除求两个数的和
思路:num1^num2:相当于只做加法不做进位(不同为1,相同为0,此时都为1的二进制位没有进位);
num1&num2<<1:相当于进位(都为1,才为1.左移1位)
把上面两步相加,反复迭代即可。
------------------------------------------------------------------------------------------------------------------------------------------------
1.4 判断一个数是不是2的整数次方?
思路:如果一个数是2的整数次方,那么这个数的二进制表示中有且仅有一位为1. (n-1)&n那么这个数唯一的一个1就会变为0;(n-1)&n==0 就是2的整数次方。
------------------------------------------------------------------------------------------------------------------------------------------------
1.5 两个整数m,n,改变多少位二进制表示才能从m变为n.
思路:求异或,然后求异或中有多少个1.
------------------------------------------------------------------------------------------------------------------------------------------------
1.6 一个整形数组里面除了两个数字,其他数字都出现了两次,找出只出现了一次的两个数字。时间复杂O(n),空间O(1)
思路:如果只有一个数字是只出现了一次,其他数字都出现了两次,那么只需要异或数组中的的所有元素,最后得到的值就是那个只出现一次的数字,出现偶数次的数字都被异或得0了。a^a==0。现在是两个只出现了一次的数字,那么想办法分组,每个组里面包含一个只出现一次的数字,要保证其他一样的数字出现在同一个组里。
首先异或数组里面所有的数字得到一个结果值。由于有两个数字只出现了一次,其他数字异或抵消掉了,这两个不同的数字异或结果不等于0,结果的二进制表示中肯定至少有一位为1.我们找该结果的第一个为1的位置。这两个只出现一次的数字,肯定该对应位一个为1,一个为0.我们依据每个元素该位置是否为1分为两组,这2个不同的只出现一次的数字就被分到两个组里,数字出现两次的数字由于一样肯定会被分到同一个组里。最后,分别异或两个组,得到两个数字就是唯一出现一次的两个不同的数字。
代码:(java)
好像总结完了,还没看到图片之类的养眼的,配个在线编程本题的图吧!^_^
![](https://img-blog.csdn.net/20170311164100099)
------------------------------------------------------------------------------------------------------------------------------------------------
总结完毕!
计算机所有的运算最终都是转换为位运算和移位的操作,效率也很高,在很多场合具有很强的技巧,所以做个总结供大家学习。
1.1 交换a,b的值,不使用第三个变量?
通常使用第三个变量:
int a=3,b=4; int temp; temp=a; a=b; b=temp;
法一:【法一需要考虑a+b会不会超过a表达的数值范围,导致内存溢出】
a=a+b; b=a-b; // 右边等价于a+b-b=====a a=a-b; //此时b等于a,右边等价于a+b-a====b
法二:
a=a^b; b=a^b; // 右边等价于a^b^b=====a a=a^b; //此时b===a; 此式右边等于a^b^a=====b
------------------------------------------------------------------------------------------------------------------------------------------------
1.2 实现一个函数,输入一个整数,输出为该整数的二进制表示有多少个1?
思路1::判断该整数是否能被2整除,如果不能被2整除,则最后一位肯定为1,计数器加一,然后右移一位;
int Numberof1(int n){ int count=0; while(n){ if(n&1) // if(n%2==1) count++; n=n>>1; } return count; }
存在问题:如果把移位改为除以2,那样效率又太低,如果输入时一个负数,0x8000 0000右边移动一位,变为0xC000 0000 。而不等价于理想的右移动一位的时候相当于除以2,得0x4000 0000。这样最终就会都变为1,引起死循环;
思路2:思路1中右移n可能会导致是负数的时候造成死循环。那么我们改进,每次左移1.
int Numberof1(int n){ int count=0; unsigned int flag=1; while(flag){ if(n&flag) // 判断某位是否为1 count++; flag=flag<<1; } return count; }
思路3: (n-1)&n相当于把n的最右边一个1变为0;
n-1:相当于把最右边的1变为0,左边保持不变,该1右边的0变为1;10100---减1--->10011
(n-1)&n:10100---&---10011------------> 10 000
int Numberof1(int n){ int count=0; while(n){ count++; n=(n-1) && n; } return count; }
------------------------------------------------------------------------------------------------------------------------------------------------
1.3 实现一个函数不用加减乘除求两个数的和
思路:num1^num2:相当于只做加法不做进位(不同为1,相同为0,此时都为1的二进制位没有进位);
num1&num2<<1:相当于进位(都为1,才为1.左移1位)
把上面两步相加,反复迭代即可。
public int add(int num1,int num2){ int sum,carray; do{ sum=num1^num2; carray=num1&num2<<1; num1=sum; num2=carray; }while(num2!=0); }
------------------------------------------------------------------------------------------------------------------------------------------------
1.4 判断一个数是不是2的整数次方?
思路:如果一个数是2的整数次方,那么这个数的二进制表示中有且仅有一位为1. (n-1)&n那么这个数唯一的一个1就会变为0;(n-1)&n==0 就是2的整数次方。
------------------------------------------------------------------------------------------------------------------------------------------------
1.5 两个整数m,n,改变多少位二进制表示才能从m变为n.
思路:求异或,然后求异或中有多少个1.
------------------------------------------------------------------------------------------------------------------------------------------------
1.6 一个整形数组里面除了两个数字,其他数字都出现了两次,找出只出现了一次的两个数字。时间复杂O(n),空间O(1)
思路:如果只有一个数字是只出现了一次,其他数字都出现了两次,那么只需要异或数组中的的所有元素,最后得到的值就是那个只出现一次的数字,出现偶数次的数字都被异或得0了。a^a==0。现在是两个只出现了一次的数字,那么想办法分组,每个组里面包含一个只出现一次的数字,要保证其他一样的数字出现在同一个组里。
首先异或数组里面所有的数字得到一个结果值。由于有两个数字只出现了一次,其他数字异或抵消掉了,这两个不同的数字异或结果不等于0,结果的二进制表示中肯定至少有一位为1.我们找该结果的第一个为1的位置。这两个只出现一次的数字,肯定该对应位一个为1,一个为0.我们依据每个元素该位置是否为1分为两组,这2个不同的只出现一次的数字就被分到两个组里,数字出现两次的数字由于一样肯定会被分到同一个组里。最后,分别异或两个组,得到两个数字就是唯一出现一次的两个不同的数字。
代码:(java)
public void findNumAppearOne(int[] a){ if(a==null || a.length<2) return ; int sum=0; for(int i:a) sum^=i; int index=findFirstBitIs1(sum); //发现第一个为1的位置; int sum1=0; int sum2=0; for(int i:a){ if(isBit1(i,index)) //判断i的index位置是不是1; sum1^=i; else sum2^=i; } System.out.println(sum1); System.out.println(sum2); } public int findFirstBitIs1(int sum){//判断从右往左的第n位置是不是1,是1返回。 int index=0; while((sum&1)==0){ sum=sum>>1; index++; } return index; } public booleam isBit1(int i,int index){ i=i>>index; return (i&1)==0 ; }
好像总结完了,还没看到图片之类的养眼的,配个在线编程本题的图吧!^_^
------------------------------------------------------------------------------------------------------------------------------------------------
总结完毕!
相关文章推荐
- Java编程中快速排序算法的实现及相关算法优化
- 容易理解的快速排序算法及其相关算法的总结(含java实现方法)
- java学习笔记(一)--编程规范和技巧总结
- JAVA编程技巧之如何实现HTTP的断点续传
- 【算法学习】图相关算法编程实现-深度优先遍历和广度优先遍历
- BP神经网络java实现,按照算法步骤也参考网上相关资源写的,若君有高见,非常欢迎指教
- Java容器学习笔记(二) Set接口及其实现类的相关知识总结
- Java编程技巧—— JDBC编程总结
- java实现的18位身份证格式验证算法-Java基础-Java-编程开发
- 【算法总结】KMP算法及java实现
- JAVA--第三周实验--任务1--实现分数的加法运算(编程思想)
- 【shell】相关编程技巧点和常规总结
- JAVA--第3周实验--任务2--实现二维数组的一种加法运算(编程思想)
- JAVA编程技巧之如何实现HTTP的断点续传
- 【算法学习】图相关算法编程实现-深度优先遍历和广度优先遍历
- Java 访问数据库 --java与DataBase相关知识总结(四) java数据库连接池嵌套内部类实现
- JAVA编程技巧之如何实现HTTP的断点续传
- [置顶]程序员面试、算法研究、编程艺术、红黑树4大系列集锦与总结
- java编程心得(十八)——关于日期的相关处理技巧
- 位运算在算法编程中的使用技巧