zoukankan      html  css  js  c++  java
  • Leetcode No.136 Single Number(c++实现)

    1. 题目

    1.1 英文题目

    Given a non-empty array of integers nums, every element appears twice except for one. Find that single one.

    You must implement a solution with a linear runtime complexity and use only constant extra space.

    1.2 中文题目

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

    说明:
    你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

    1.3输入输出

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

    1.4 约束条件

    • 1 <= nums.length <= 3 * 104
    • -3 * 104 <= nums[i] <= 3 * 104
    • Each element in the array appears twice except for one element which appears only once.

    2. 分析

    这一题我的第一反应是暴力搜索,先构建一个临时数组存储已遍历元素。若新遍历元素与之前重复,则不是目标值,从临时数组中删除;否则加入。遍历到最后,临时数组内只剩余目标值。代码如下:

    class Solution {
    public:
        int singleNumber(vector<int>& nums) {
            vector<int> temp;
            vector<int>::iterator iter;
            for (int i = 0; i < nums.size(); i++)
            {
                iter = find(temp.begin(), temp.end(), nums[i]);
                if (iter != temp.end()) //找到了,重复元素
                    temp.erase(iter);
                else
                    temp.push_back(nums[i]);
            }
            return temp[0];
        }
    };
    

    之后又看了下一些其他大神们的写法,让人直呼妙哉!其中一种是利用set集合不含重复元素的性质,通过将数组转为集合,之后用集合元素和的2倍减去原数组所有元素的和,就是结果,代码如下:

    class Solution {
    public:
        int singleNumber(vector<int>& nums) {
            set<int> setNums(nums.begin(), nums.end());
            int sum = accumulate(nums.begin(), nums.end(), 0);
            int setSum = accumulate(setNums.begin(), setNums.end(), 0);
            return 2 * setSum - sum;
        }
    };
    

    上面这种算法在时间和空间消耗上并不是太好,但是这种想法不错。另外还有一种做法是利用异或的性质,假设所有的数组为:abcbcda,则
    a ^ b ^ c ^ b ^ c ^ d ^ a
    = a ^ a ^ b ^ b ^ c ^ c ^ d
    = 0 ^ 0 ^ 0 ^ d
    = d。
    代码如下:

    class Solution {
    public:
        int singleNumber(vector<int>& nums) {
            int result = 0;
            for (auto num : nums)
                result ^= num;
            return result;
        }
    };
    

    3. 补充知识

    (1)vector

    a. 查找vector中的某一个元素

    可以利用algorithm头文件中find(),用法为:
    vector<A>::iterator iter = std::find(vec.begin(), vec.end(), findNum);

    b.vector删减元素

    • push_back()尾部添加元素
    • pop_back()尾部删除元素
    • erase(num)删除指定元素或指定迭代器位置元素

    c.vector与set互转

    • vector转set:set<int> st(v.begin(), v.end());//在构造函数中可以直接实现vector转set
    • set转vector:v.assign(st.begin(), st.end());

    (2) 异或

    a.异或的特性:

    • 恒定律:A ^ 0 = A
    • 归零率:A ^ A = 0
    • 交换律:A ^ B = B ^ A
    • 结合律:(A ^ B) ^ C = A ^ (B ^ C)

    b.用途

    异或可以快速比较两个值是否相等 a ^ b == 0,效率非常高,比 a - b == 0 高很多。

    异或还能在不定义临时变量的情况下,交换两个值(经典题目)
    a = a ^ b
    b = a ^ b // a ^ b ^ b = a ^ 0 = a
    a = a ^ b // a ^ b ^ a = b ^ 0 = b
    参考:https://www.jianshu.com/p/e3442ed3d874

    作者:云梦士
    本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
  • 相关阅读:
    BZOJ 5314: [Jsoi2018]潜入行动
    BZOJ 3420: Poi2013 Triumphal arch
    BZOJ 1135: [POI2009]Lyz
    BZOJ 4247: 挂饰
    本地
    生成config文件到内存中
    微信获取access_token和curl
    php生成静态页面
    curl
    分页
  • 原文地址:https://www.cnblogs.com/yunmeng-shi/p/14994044.html
Copyright © 2011-2022 走看看