數字只出現一次
代碼:
public static void main(String[] args) {
// int[] arr = {2, 2, 1};
// int num = singleNumber(arr);
// System.out.println(num);
// int[] arr={2,1,2,3,4,1};
// int[] nums = singleNumber2(arr);
// System.out.println(Arrays.toString(nums));
// int[] arr={2,2,3,2};
int[] arr={0,1,0,1,0,1,99};
int num = singleNumber3(arr);
System.out.println(num);
}
/**
* 只出現一次的數字 其餘數字都出現兩次,只有一個數字出現一次
* 達到只使用線性的時間複雜度 不使用額外的空間
* 使用異或運算 相同的元素進行異或運算 爲0 0與任何元素異或都是元素本身
*
* @Date: 2020/6/9 23:15
* @Author: fuGuoWen
* @Return int 返回出現一次的數字
* @Throws 無
*/
public static int singleNumber(int[] nums) {
int result = 0;
for (int i = 0; i < nums.length; i++) {
result ^= nums[i];
}
return result;
}
/**
* 恰好有兩個元素出現一次,其餘的元素都是出現兩次
* 解決方案:
* 1.對所有的元素做異或操作
* 2.對異或以後的結果取低位第一個爲1 的值 temp
* 3.對整個元素繼續進行遍歷,如果當前元素的值與temp 最高位的值相同 返回的值不爲0,
* 如果當前元素的值與temp 最高位的值不同,返回的是0
*
* 算法 具備 線性的時間複雜度 和常量的空間複雜度
*
* @Date: 2020/6/9 23:28
* @Author: fuGuoWen
* @Return int[] 整形數組
* @Throws 無
*/
public static int[] singleNumber2(int[] nums) {
int result=0;
/** 第一步: 所有的元素進行異或,會得到唯一的兩個元素的異或值 */
for(int i=0;i<nums.length;i++){
result^=nums[i];
}
/** 第二步 獲得result低位的第一個不爲0 的值 */
int temp = 1;
while (result != 0) {
if ((result & 1) == 1) {
break;
}
temp <<= 1;
result >>= 1;
}
int[] arr=new int[2];
for(int i=0;i<nums.length;i++){
if((nums[i]&temp)==0){
/**
* 第三步 對所有的元素進行與最高位的元素的值進行與運算 與最高位元素相同的值 進行的計算不爲0
* 與最高位元素相同的值 進行的計算結果爲0
* */
arr[0]^=nums[i];
}else{
arr[1]^=nums[i];
}
}
return arr;
}
/**
* 只有一個元素出現了一次,其他的元素都是出現了三次
* 解決思路
* 1.
* @Date: 2020/6/10 0:26
* @Author: fuguowen
* @Return
* @Throws
*/
public static int singleNumber3(int[] nums) {
/** 第一步 遍歷數組的每一位按照二進制位進行累加 */
int[] bits = new int[32];
for (int i = 0; i < 32; i++) {
for (int j = 0; j < nums.length; j++) {
bits[i] += (nums[j] & 1);
nums[j] >>= 1;
}
}
/**
* 第二步 高位元素存儲在下標比較大的位置
* 從高位元素進行遍歷,先進行右移,再進行跟3取模,求餘,最後獲得元素就是隻出現一次的元素
* */
int result = 0;
for (int i = 31; i >= 0; i--) {
result <<= 1;
result += (bits[i] % 3);
}
return result;
}