lc137. 只出现一次的数字 II

lc137. 只出现一次的数字 II_第1张图片

 

数组排序,既和前不一样又和后不一样的就是唯一的一个

    public static int numberOnce(int[] nums) {
        Arrays.sort(nums);
        if (nums.length > 2 && nums[0] != nums[1]) {//避免只有一个元素的数组
            return nums[0];
        }
        if (nums.length > 2 && nums[nums.length - 2] != nums[nums.length - 1]) {
            return nums[nums.length - 1];
        }
        for (int i = 1; i < nums.length - 1; i++) {
            if (nums[i] != nums[i - 1] && nums[i] != nums[i + 1]) {
                return nums[i];
            }
        }
        return nums[0];//只有一个元素的数组
    }

哈希表

位运算 

 

只有一个数出现了一次,其他数都出现了三次,那么别的数的每个二进制位加起来的和除3一定为0。

所以如果某个二进制位取余3不为0那么这个数就是所要求的答案的某个二进制位,再把它导出来加起来就得到答案。

lc137. 只出现一次的数字 II_第2张图片

 力扣每日一题:137. 只出现一次的数字 II(C++) - 知乎 (zhihu.com)

一些符号解释

(num >> i) & 1是将num左移i位进行按位与,即为保留num的第i位,其余位置零

如果num的第i位为0,则(num >> i) & 1的值为0,否则不为0

|=  按位或赋值运算符

按位或赋值运算符使用两个操作数的二进制表示,对它们执行按位或运算并将结果分配给变量

x |= y // x = x | y

与运算:针对补码进行运算 

lc137. 只出现一次的数字 II_第3张图片 

    public int singleNumber(int[] nums) {
        int ans = 0;
        for (int i = 0; i < 32; ++i) {
            int total = 0;
            for (int num: nums) {
                //将每个二进制位加一起
                total += ((num >> i) & 1);//保留num的第i位,其余位为0,对于每个元素的第i位进行相加
            }
            if (total % 3 != 0) {//是否整除3,即为是否是所求的数
                ans |= (1 << i);//1 << i表示将1左移i位
                //ans = ans | (1 << i) 将二进制还原为十进制数
            }
        }
        return ans;
    }

 

代码

import org.junit.Test;
import java.util.Arrays;

public class NumberOnce {
    @Test
    public void test() {
        int[] nums = new int[]{2, 2, 3, 2};
        System.out.println(numberOnce(nums));
        int[] nums1 = new int[]{0,1,0,1,0,1,99};
        System.out.println(numberOnce(nums1));
        System.out.println(singleNumber(nums1));
    }

    public static int numberOnce(int[] nums) {
        Arrays.sort(nums);
        if (nums.length > 2 && nums[0] != nums[1]) {//避免只有一个元素的数组
            return nums[0];
        }
        if (nums.length > 2 && nums[nums.length - 2] != nums[nums.length - 1]) {
            return nums[nums.length - 1];
        }
        for (int i = 1; i < nums.length - 1; i++) {
            if (nums[i] != nums[i - 1] && nums[i] != nums[i + 1]) {
                return nums[i];
            }
        }
        return nums[0];//只有一个元素的数组
    }

    public int singleNumber(int[] nums) {
        int ans = 0;
        for (int i = 0; i < 32; ++i) {
            int total = 0;
            for (int num: nums) {
                //将每个二进制位加一起
                total += ((num >> i) & 1);//保留num的第i位,其余位为0,对于每个元素的第i位进行相加
            }
            if (total % 3 != 0) {//是否整除3,即为是否是所求的数
                ans |= (1 << i);//1 << i表示将1左移i位
                //ans = ans | (1 << i) 将二进制还原为十进制数
            }
        }
        return ans;
    }

}

 

你可能感兴趣的:(排序算法,算法,数据结构)