java源代码Integer类中提供了reverse(int i)方法,这个方法的作用是用来将int类型变量的二进制表示进行按位反转。数值类型变量进行按位反转的问题和常见的数字反转以及字符串反转和数组反转其实都是同一类型的问题,所以对于这个问题的讨论也有利于我们在遇到这种类型的其他问题时可以举一反三,开拓思维。
对于int变量的按位反转有几种方式,http://blog.csdn.net/ammana_babi/article/details/1641868这篇博客里提供的几种方法非常好,我在这里就对这几种方法进行下自己的整理:
第一种方法:
static int reverseBits01(int n){
int result = 0;
for (int i = 0; i < Integer.SIZE; i++) {
result <<= 1;
result |= n & 1;
n >>>= 1;
}
return result;
}
这种方式的思路跟网上大部分的整数反转的思路是相同的,所以在处理整数反转和字符串反转的问题时可以考虑这种方法。
第二种方法:
static int reverseBits02(int n){
int result = 0;
for (int i = 0; i < Integer.SIZE/2; i++) {
result |= (n & (1 << i)) << (Integer.SIZE - 1 - 2 * i);
result |= (n & (0x80000000 >>> i)) >>> (Integer.SIZE - 1 - 2 * i);
}
return result;
}
这种方法的核心思想类似于排序算法中的简单选择排序,挑出某个位置的数字并将其置入最终应该存在的位置。
第三种方法,也是最重要的方法:
static int reverseBits03(int n){
n = (n & 0x55555555) << 1 | (n >>> 1) & 0x55555555;
n = (n & 0x33333333) << 2 | (n >>> 2) & 0x33333333;
n = (n & 0x0f0f0f0f) << 4 | (n >>> 4) & 0x0f0f0f0f;
n = (n & 0x00ff00ff) << 8 | (n >>> 8) & 0x00ff00ff;
n = (n & 0x0000ffff) << 16 | (n >>> 16) & 0x0000ffff;
return n;
}
static int reverseBits04(int n){
n = (n & 0x55555555) << 1 | (n & 0xAAAAAAAA) >>> 1;
n = (n & 0x33333333) << 2 | (n & 0xCCCCCCCC) >>> 2;
n = (n & 0x0f0f0f0f) << 4 | (n & 0xF0F0F0F0) >>> 4;
n = (n & 0x00ff00ff) << 8 | (n & 0xFF00FF00) >>> 8;
n = (n & 0x0000ffff) << 16 | (n & 0xFFFF0000) >>> 16;
return n;
}
**以上两个代码段其实是同一算法的不同写法,这个算法采用了分治法的策略,将一个32个数字序列的反转问题,不断划分进而转化成16,8,4,2个数字序列的反转问题。
这种分治再整合的思想再很多方面都有应用,比如此处的数字序列反转的问题,再比如排序问题,归并排序便是排序问题中分治算法的具体体现,同时,求序列中逆序对的问题也可以采用这种方式进行求解。
这些问题具有一些共同特征,也是分治算法可以应用的必要条件:问题求解可以根据分解的小问题的解进行求解,比如此处,序列的反转可以通过两个内部已经反转好了的子序列的反转来进行,还有归并排序中序列的排序可以通过已经有序的序列的整合进行。
算法的关键在于将问题逐级分解最终找到不能被分解的元问题,通过对元问题的求解进而找到规律进行求解,比如归并算法中序列长度为1或2便是归并算法的原问题**