目录
Single Number 2 :
给定一个非空的整数数组,每个元素都会出现三次,只有一个出现一次。找到那个只出现一次的元素
思路:
对每一个位上出现的所有元素的1的个数统计,如果是出现三次的数,那么模3的结果为0;如果是出现1次的数,那么模3的结果为1。这样就可以利用取模的结果找出待求的数。
难点:
如何统计每一个位上出现1的总个数?这个问题可以通过两个步骤解决,第一步是循环,外循环是针对32个位置,内循环是针对每个数;第二步是判断,对每个数字的每个位置判断是否为1.
code:
//注意到,出现3次,对每个位上的1的个数做出统计,发现会被3整除也就是模3为0
//我们对每一位统计,并且对统计结果模3,只出现一次的数模3过后的结果为1
class Solution {
public int singleNumber(int[] nums) {
int res = 0;
for(int i=0;i<32;i++){
int sum = 0;
for(int n:nums){
sum += (n>>i)&1;
}
res |= sum%3 << i;
}
return res;
}
}
Single Number 3 :
给定一个数字数组num,其中正好有两个元素只出现一次,而所有其他元素恰好出现两次。查找只出现一次的两个元素。
思路:
首先对整个num进行分组,使得待求的两个数字各自处于一个分组中,这样两个分组单独求出一个元素即可。
难点:
如何分组?可以对整个数组求抑或运算。对于非待求元素,都出现了两次,因此,抑或运算的结果相当与待求元素做抑或运算。那么只需要找到这个结果中的任意一位为1,自说明,待求结果的两个元素在这个位置上不同。可以利用这一点分组。
code:
//思路:首先对整个nums抑或,这个结果是需要求得的两个不同的数字的抑或的结果
//找到这个结果中的一个为 1 的位(为一表示,这两个不同的数字在这个位置上一个为0,一个为1)
//根据这个条件,将整个nums分成两组,每组单独抑或的结果,就是,想要求得的结果
class Solution {
public int[] singleNumber(int[] nums) {
int div = 0;
for(int num : nums){
div ^= num;
}
//取出最低位的1
//int d = Integer.lowestOneBit(div);
div &= -div;//负值的表示方法
int res1 =0;
int res2 =0;
for(int num : nums){
if((div&num) != 0){
res1 ^= num;
}
else{
res2 ^= num;
}
}
return new int[]{res1,res2};
}
}
补充:
1、Integer类中的highestOneBit是如何实现的?
参考 https://blog.youkuaiyun.com/u011544437/article/details/78497190
/**
* Returns an {@code int} value with at most a single one-bit, in the
* position of the highest-order ("leftmost") one-bit in the specified
* {@code int} value. Returns zero if the specified value has no
* one-bits in its two's complement binary representation, that is, if it
* is equal to zero.
*
* @param i the value whose highest one bit is to be computed
* @return an {@code int} value with a single one-bit, in the position
* of the highest-order one-bit in the specified value, or zero if
* the specified value is itself equal to zero.
* @since 1.5
*/
public static int highestOneBit(int i) {
// HD, Figure 3-1
i |= (i >> 1);
i |= (i >> 2);
i |= (i >> 4);
i |= (i >> 8);
i |= (i >> 16);
return i - (i >>> 1);
}
/**
* Returns an {@code int} value with at most a single one-bit, in the
* position of the lowest-order ("rightmost") one-bit in the specified
* {@code int} value. Returns zero if the specified value has no
* one-bits in its two's complement binary representation, that is, if it
* is equal to zero.
*
* @param i the value whose lowest one bit is to be computed
* @return an {@code int} value with a single one-bit, in the position
* of the lowest-order one-bit in the specified value, or zero if
* the specified value is itself equal to zero.
* @since 1.5
*/
public static int lowestOneBit(int i) {
// HD, Section 2-1
return i & -i;
}
例子:highestOneBit:保留最高位的1,低位都置为0
i |= (i >> 1);//使得最高位1以及它的后面一位变成1:1000|0100 = 1100
i |= (i >> 2);//使得前四位变成1:1100|0011 = 1111;
i |= (i >> 4);
i |= (i >> 8);
i |= (i >> 16);//使得最高位及其以后的低位全部变成1:00111111...
return i - (i >>> 1);//无符号左移,再相减 00111111...- 00011111.. = 00100000..
例子:lowestOneBit:保留低位的1,高位都置为0
return i & -i;
实验代码:
System.out.println(Integer.toBinaryString(4));
System.out.println(Integer.toBinaryString(-4));
System.out.println(Integer.toBinaryString(4&-4));
System.out.println(Integer.toBinaryString(5));
System.out.println(Integer.toBinaryString(-5));
System.out.println(Integer.toBinaryString(5&-5));
System.out.println(Integer.toBinaryString(6));
System.out.println(Integer.toBinaryString(-6));
System.out.println(Integer.toBinaryString(6&-6));
结果:
100
11111111111111111111111111111100
100
101
11111111111111111111111111111011
1
110
11111111111111111111111111111010
10