leetcode:136. 只出现一次的数字

题目来源

leetcode

题目描述

在这里插入图片描述

题目解析

关键点在于两两相消

使用set

题目中让我们在线性的时间复杂度内求解,那么一个非常直接的思路就是使用 HashSet,利用其常数级的查找速度。遍历数组中的每个数字,若当前数字已经在 HashSet 中了,则将 HashSet 中的该数字移除,否则就加入 HashSet。这相当于两两抵消了,最终凡事出现两次的数字都被移除了 HashSet,唯一剩下的那个就是单独数字了

  • cpp
int singleNumber(vector<int>& nums) {
    std::unordered_set<int> set;
    set.insert(nums[0]);
    for (int i = 1; i < nums.size(); ++i) {
        if(set.count(nums[i]) ){
            set.erase(nums[i]);
        }else{
            set.insert(nums[i]);
        }
    }

    return *set.begin();
}

使用异或相消

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int ans = nums[0];
        for (int i = 1; i < nums.size(); ++i) {
            ans ^= nums[i];
        }
        return ans;
    }
};

判断排序数组前后元素是否相等

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        int size = nums.size();
        if(size == 1){
            return nums[0];
        }
        
        // 判断第一个
        if(nums[0] != nums[1]){
            return nums[0];
        }
        
        // 判断最后一个
        if(nums[size - 1] != nums[size - 2]){
            return nums[size - 1];
        }

        // 判断其他
        for (int i = 1; i < size - 1; ++i) {
            if(nums[i - 1] != nums[i] && nums[i] != nums[i + 1]){
                return nums[i];
            }
        }

        return -1;
    }
};

请添加图片描述

求和

通过 HashSet 保存数组内的元素,然后进行求和(setsum),那么得到的这个和则为去除掉重复元素的和,我们也可以得到所有元素和(numsum)。因为我们其他元素都出现两次,仅有一个元素出现一次,那我们通过 setsum * 2 - numsum 得到的元素则为出现一次的数。

在这里插入图片描述

 class Solution {
     int singleNumber(std::vector<int> nums) {
         if (nums.size() == 1){
             return nums[0];
         }
         std::set<int> set;
         int setsum = 0;
         int numsum = 0;
         for (int x : nums) {
             //所有元素的和
             numsum += x;
             if (!set.count(x)) {
                 //HashSet内元素的和
                 setsum += x;
             }
             set.emplace(x);
         }
         //返回值
         return setsum * 2 - numsum;
     }
 }

类似题目

题目思路
leetcode:41. 无序数组中缺失的第一个正整数(数组数据范围[-oo, +oo]) First Missing Positive应该去垃圾区的情况:当前数 <= L ,当前数 > 右边界 ,出现了重复
leetcode:268. 无序数组缺失的那个数(数组数据范围在[0, n],数据长度为n) Missing Number如果我们补充一个完整的数组和原数组进行组合,那所求解的问题就变成了 只出现一次的数字。
leetcode:448. 无序数组缺失的那个数(数组数据范围在[1, n],数据长度为n) Find All Numbers Disappeared in an Array标记法:在原数组上进行一次遍历,在遍历的过程中,将遇到的元素所对应的index下的元素标记为负。最终哪些index下的元素没有被标记的则说明,这个index对应额元素没有出现过。置换法
leetcode:136. 无序数组出现一次的数字(出现一次的数字有一个,其他出现两次)Single Number异或相消,剩下来的就是想要的
leetcode:137. 无序数组出现一次的数字(出现一次的数字有一个,其他出现三次) II Single Number IISingle Number II对于出现三次的数字,各个二进制位出现的次数都是3的倍数。因此,统计所有数字的各二进制位中1的出现次数,并对3求余,结果则为只出现一次的数字(通用解法)。实现:对int的32个位每个位进行依次判断该位1的个数求余3后是否为1,如果为1说明结果该位二进制为1可以将结果加上去。最终得到的值即为答案。
leetcode:260. 无序数组出现一次的数字(出现一次的数字有两个,其余出现两次)Single Number III先将元素分成两组,然后每组包含一个目标值,那么异或之后,每组得到一个目标值。比如a,b,a,b,c,d,e,f,e,f,分组后;A组:a, a , b, b, c 异或得到 c;B组:e, e, f, f, d 异或得到 d
leetcode:287.无序数组出现多次的数字(一个数出现多次,其他数出现一次或者零次) (数组数据范围在[1, n],数据长度为n+1) Find the Duplicate Number因为不允许修改原数组,所以不能用标记法。而一般对于链表,数组中要求找重复的数字或者节点,都可以考虑用快慢指针的方法来解,也就是入环节点就是那个重复的数
leetcode:442.无序数组出现两次的整数(每个数出现一次或者两次,数组数据范围在[1, n])) Find All Duplicates in an Array标记法:对于每个nums[i],我们将其对应的nums[nums[i] - 1]取相反数,如果其已经是负数了,说明之前存在过,我们将其加入结果res中即可;置换法: 将nums[i]置换到其对应的位置nums[nums[i]-1]上去,最后在对应位置检验,如果nums[i]和i+1不等,那么我们将nums[i]存入结果res中即可
leetcode:645. 无序数组,有一个数字重复出现了一次,从而造成了另一个数字的缺失,请找出重复的数字和缺失的数字(数据范围在[1, n],数据长度为n) Set Mismatch 假设每个人各司其职, 那么每个岗位上就是相应的人员,并且各司其职, 但是现在混入了一个;闲杂人等, 他又害怕被人发现, 于是他就别人的岗位上站着, 结果等着等着, 这个岗位上应该来的人来了;他一看, 自己掩饰不过去了(毕竟人家不会跑到别的岗位上,抢别人的活干, 于是他就这么一直碰运气。 一直走到那个没来上岗的那个人的岗位上去, 这样谁都不会发现他是的闲杂人等.而且每个岗位上都满员了.
leetcode:142. 环形链表 II
leetcode:540. 有序数组中的单一元素(其他出现两次)二分
leetcode:389. 字符t比字符s多出的那个数 Find the Difference 异或
765. 情侣牵手Couples Holding Hands
565. 数组嵌套 Array Nesting
1207. 独一无二的出现次数先统计数字出现的频率,然后看相同频率是否重复出现
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值