zoukankan      html  css  js  c++  java
  • 【LeetCode】136. Single Number

    题目:

    给定一个非空整数数组,除其中一个元素外,每个元素都出现了两次,找出那个只出现了一次的元素。

    例1:

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

    例2:

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

    思路:

    对数组元素进行依次统计,如果一个元素已经出现了两次,则不再关注,直到找到只出现一次的元素。

    #include <stdio.h>
    
    //统计在数组arr中数字k出现的次数,n是数组的大小
    int countLetter(int* arr, int n, int k) {
        int count = 0;
        for (int i=0; i<n; i++) {
            if (arr[i] == k) {
                count++;
            }
        }
        return count;
    }
    
    int singleNumber(int* nums, int numsSize) {
        for (int i=0; i<numsSize; i++) {
            int count = countLetter(nums, numsSize, nums[i]);
            if (count == 1)
                return nums[i];
        }
        return 0;
    }
    
    int main()
    {
        int nums[] = {5, 8, 5, 6, 8, 7, 7};
        int number = singleNumber(nums, 7);
        printf("The single number is %d.
    ", number);
    }

    结果:

    系统虽然接受了这个程序,但是运行时间长达400ms,排名也十分靠后。

    很明显是时间上吃了亏。在这个程序中,singleNumber函数中有一个for循环,在这个for循环中调用了countLetter函数,而countLetter函数中也有一个for循环,这样时间复杂度就达到了O(n2),这样的时间复杂度太高了。

    所以要想改进的话就要从时间复杂度来入手了


    改进思路:

    用异或的性质

    异或有交换性,还有一个很有意思的性质,a^b^b=a,即数a两次异或同一个数b(a=a^b^b)仍然为原值a。又如:a^b^a^c^b^c^d=d。

    令k等于数组中任意一个数字,并与剩余元素进行异或运算,最后结果就是那个single number。

    #include <stdio.h>
    
    int singleNumber(int* nums, int numsSize) {
        int k = nums[0];
        for (int i=1; i<numsSize; i++) {
            k = (k ^ nums[i]);
        }
        return k;
    }
    
    int main()
    {
        int nums[] = {5, 6, 5, 6, 8, 7, 7};
        int number = singleNumber(nums, 7);
        printf("The single number is %d.
    ", number);
    }

    结果:

    这次运行时间为4ms,相比400ms效率不知道高到哪里去了,排名自然也非常靠前。

    异或还有一些其他有意思的性质,比如可以在不引入临时变量的情况下交换两个变量的值等等。

    a=10100001,   b=00000110
    
    a=a^b; //a=10100111
    
    b=b^a; //b=10100001
    
    a=a^b; //a=00000110

    参考:一起玩算法02

    推荐一位干货up主:正月点灯笼

  • 相关阅读:
    springboot 和 spring clould 的版本匹配问题
    行到水穷处,坐看云起时!
    转: 从单体应用 -> SOA--> 微服务 ,服务治理 [熔断,限流,降级,服务恢复,服务容错,监控等等]---> RPC ---> 下一代技术[Service Mesh]
    spring-boot自定义线程池
    千与千寻的内容抓手
    哲学三问
    简约的人生
    关于中间件整理
    此心光明,亦复何言!
    能容的下你身边比你优秀的人---是一种修行
  • 原文地址:https://www.cnblogs.com/ME-WE/p/12433598.html
Copyright © 2011-2022 走看看