算法31:只出现一次的数字

一、需求

给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。

示例 1 :

输入:nums = [2,2,1]
输出:1

示例 2 :

输入:nums = [4,1,2,1,2]
输出:4

示例 3 :

输入:nums = [1]
输出:1

提示:

  • 1 <= nums.length <= 3 * 104
  • -3 * 104 <= nums[i] <= 3 * 104
  • 除了某个元素只出现一次以外,其余每个元素均出现两次。

二、思路分析图

(一)异或破解方案

在这里插入图片描述
在这里插入图片描述

三、代码

(一)数据初始化/调用函数

/**
 * 入口
 *      136、只出现一次的数字
 * 输入:
 *      [4,1,2,1,2]
 * 输出:
 *      4
 * 解释:
 *      1.暴力破解方案
 *      2.异或破解方案
 *      3.HashSet方案
 */
@Test
public void suanfa31()
{
    // 初始化
    int[] nums = { 4, 1, 2, 1, 2 };

    // 打印
    int a = this.singleNumberViolence(nums);
    System.out.println("暴力破解方案 = " + a);

    int b = this.singleNumberXor(nums);
    System.out.println("异或破解方案 = " + b);

    int c = this.singleNumberHashSet(nums);
    System.out.println("HashSet方案 = " + c);
}

(二)暴力破解方案

/**
 * 暴力破解方案
 *
 * @param nums
 * @return
 */
private int singleNumberViolence(int[] nums)
{
    int a;
    int result = 0;
    for (int i = 0; i < nums.length; i++)
    {
        a = nums[i];
        int index = 0;
        for (int j = 0; j < nums.length; j++)
        {
            if (i != j && a == nums[j])
            {
                index++;
            }
        }
        if (index == 0)
        {
            result = a;
        }
    }
    return result;
}

(三)异或破解方案

/**
 * 异或破解方案
 * 
 * @param nums
 * @return
 */
private int singleNumberXor(int[] nums)
{
    int result = nums[0];
    for (int i = 1; i < nums.length; i++)
        result ^= nums[i];
    return result;
}

(四)HashSet方案

/**
 * HashSet方案
 *
 * @param nums
 * @return
 */
private int singleNumberHashSet(int[] nums)
{
    HashSet<Integer> a = new HashSet<>();
    for (int num : nums)
        if (!a.add(num))
            a.remove(num);
    return a.iterator().next();
}

(五)结果图

在这里插入图片描述

作者:王子威

四、总结

  • 学习了只出现一次的数字
  • 只写出了暴力破解,异或完全没想到…
  • 因为异或的特性,重复的值会在下次出现时删掉对方,这个特性很有用,但注意这里适用于int或Integer类型
  • HashSet的应用学习
  • 算法兴趣+1 总:31
  • 加强了对算法的分析能力
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值