lc137. 只出现一次的数字 II

 

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

    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那么这个数就是所要求的答案的某个二进制位,再把它导出来加起来就得到答案。

 力扣每日一题: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

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

 

    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;
    }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值