leetcode136.只出现一次的数字 多种解法详解

本文探讨了在数组中查找唯一出现一次的元素的有效算法,包括暴力法、排序法、哈希集和异或操作。重点介绍了异或操作的高效性和原理,以及如何在C++和Java中实现这些算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
示例 2:
输入: [4,1,2,1,2]
输出: 4

分析

首先看到题目我先想到的是用两层循环的暴力解法(时间复杂度为n的平方)但很明显会超出时间限制,然后我就想将这个数组排序,就很容易得到那个出现一次的元素。另外的想法是通过hashset的不重复特性求解。最简单的想法是通过异或解决,因为任何一个数字异或它自己都等于0,也就是说,如果我们从头到尾依次异或数组中的每一个数字,那么最终的结果刚好是那个只出现一次的数字,因为那些出现两次的数字全部在异或中抵消掉了。

废话不多说,下面直接上代码,并附有详细解析。

解决方案

方法一:暴力法(c++)(注意:此方法在leetcode上运行超出时间限制,我在这里只是想展示一种思路)

 class Solution {
    public:
        int singleNumber(vector<int>& nums) {
            for(int i=0;i<nums.size();i++)//双重循环将nums中相等的值赋值为0
            {
                for(int j=0;j<i;j++)
                {
                    if(nums[i]==nums[j]){
                        nums[i]=0;
                        nums[j]=0;
                    }
                }
            }
            for(int i=0;i<nums.size();i++)//遍历nums找出唯一不为零的值并给nums[0],或者该元素为0则返回0,不影响结果
            {
                if(nums[i]!=0)
                    nums[0]=nums[i];
            }
            return nums[0];
        }
    };

方法二:排序(c++)

形式一:

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        sort(nums.begin(),nums.end());//排序
        int temp;//作为返回值
        if(nums.size()==1)//考虑nums只有一个的情况
            return nums[0];
        if(nums[0]!=nums[1])//考虑开头
            return nums[0];
        if(nums[nums.size()-1]!=nums[nums.size()-2])//考虑结尾
            return nums[nums.size()-1];
        for(int i=1;i<nums.size()-1;i++)//考虑中间
        {
            if(nums[i-1]!=nums[i]&&nums[i+1]!=nums[i])
                temp= nums[i];
        }
        return temp;
    }
};

形式二:先排序,再用双指针

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        for(int i = 0, j = 1; j < nums.size(); i += 2, j += 2){
            if(nums[i] != nums[j])  return nums[i];
        }
        return nums[nums.size() - 1];
    }
};

方法三:哈希集(Java)

class Solution {
    public int singleNumber(int[] nums) {
        int res=0;//作为返回值,必须初始化
        HashSet<Integer>temp =new HashSet<Integer>();
        for(int x:nums)//遍历nums,先判断temp中是否包含x,若包含则将temp中的x值删除,否则继续向temp中添加新值
        {
            if(temp.contains(x))
                temp.remove(x);
            else
                temp.add(x);
        }
        for(int y:temp)
            res=y;
        return res;
    }
}

方法四:异或(c++)
任何一个数字异或它自己都等于0。也就是说,如果我们从头到尾依次异或数组中的每一个数字,那么最终的结果刚好是那个只出现一次的数字,因为那些出现两次的数字全部在异或中抵消掉了。

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int res=nums[0];
        for(int i=1;i<nums.size();i++)
            res=res^nums[i];
        return res;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值