• 算法练习- LeetCode 剑指 Offer 56 - I. 数组中数字出现的次数


    今日心情:生活在慢慢走上正轨,慢慢走总能达到想去的地方。

    题目描述:

    LeetCode 剑指 Offer 56 - I. 数组中数字出现的次数

    一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。


    解题代码:(满足题目对于时间和空间复杂度要求的解法:异或+位判断)

    1. class Solution {
    2. //使用 异或进位
    3. public int[] singleNumbers(int[] nums) {
    4. //获取划分两组的
    5. int th = 0;
    6. for(int num:nums){
    7. th ^= num;
    8. }
    9. //找到最低位进行划分
    10. // 1. 相同的划分到同一组
    11. // 2. 不同的划分到不同组
    12. int div = 1;
    13. while((th & div) == 0){
    14. div <<= 1;
    15. }
    16. int group1 = 0;
    17. int group2 = 0;
    18. for(int num: nums){
    19. if((num & div) != 0){
    20. group1 ^= num;
    21. }else{
    22. group2 ^= num;
    23. }
    24. }
    25. return new int[]{group1,group2};
    26. }
    27. }

    解题代码:(自己首先拿到题的时候想的,但是不满足题目对于空间复杂度的要求:HashMap) 

    1. class Solution {
    2. //使用 map 记录可以实现(但是不满足题目空间复杂度的要求)
    3. public int[] singleNumbers(int[] nums) {
    4. HashMap<Integer,Boolean> map= new HashMap<>();
    5. LinkedList<Integer> arr = new LinkedList<>();
    6. for(int num: nums){
    7. map.put(num,!map.containsKey(num));
    8. }
    9. for(int num:nums){
    10. if(map.get(num)){
    11. arr.add(num);
    12. }
    13. }
    14. int len = arr.size();
    15. int[] res = new int[len];
    16. for(int i=0;i<len;i++){
    17. res[i] = arr.get(i);
    18. }
    19. return res;
    20. }
    21. }

    解题思路:

    自己首先拿到题的时候想到就是用HashMap进行记录然后找没有重复的,满足时间复杂度O(n)但是不满足空间复杂度O(1)的要求。然后想不出来就直接看题解,看如何进行操作能否达到要求的空间复杂度,题解用的就是 位 操作的方法。所以看两个数相不相同 除了可以用==比较,也可以用异或进行比较,相同为0,不同为1。0 异或 任何数 为 该数本身。

    题解方法:

    (1)要找出这两个只出现一次的数字,如果数组全部进行异或,那么最后的异或结果就是那两个只出现一次的数字。所以这两个不同的数字的区别信息其实就在他们的异或结果之中,题解的方法很巧妙,使用的异或结果中的最低为1的位来将数组划分为不同的两个组,划分的要求是将相同的数划分在同一个组中,不同的数分别在两个组中,这样分别对两个组里的所有数进行异或操作,最后的结果就是要找的不同的数。

    (2)首先对数组中所有的数进行异或,得到的异或结果就是两个不同数的异或结果,因为其他的数都有重复异或结果为0,0异或其他数的结果为该数的本身。

    (3)获得异或结果之后,找最低位为1(div):div起始为1,找th的最低位,div 与 th 进行位与 如果为0 则进行左移,否则找到了th的最低位。

    (4)通过 div 将数组划分为两个组分别进行异或,因为div 是 两个不同数字的异或结果所以 可以直接通过 div 区分 两个不同数组,如果div 与 num 进行 位与,结果为1 划分到 group1 进行异或,如果为 0 划分到 group2进行异或。因为相同数的位相同,所以通过div 可以直接划分到同一组中,div 本身就是用来区别不同数字的所以,不同数组会被分别划分到group1和group2。

    (5)返回 group1 和 group2 的异或结果就是这两个不同数。


  • 相关阅读:
    C++之类(持续更新)
    <C++>再识构造函数和static成员
    爬虫入门——1、基本概念
    scikit-learn算法精讲 之 层次聚类和树状图
    PHP代码审计DVWA[XSS (DOM)]
    多线程-异步编排
    Hudi源码 | Insert源码分析总结(二)(WorkloadProfile)
    点云滤波--一种点云异常值检测和稳健法线估计方法
    Entertainment in MAC(Round 932)
    前端学习笔记
  • 原文地址:https://blog.csdn.net/qq_41758969/article/details/125620785