zoukankan      html  css  js  c++  java
  • 帮朋友 解决一道 LeetCode QJ上问题

    引言

      对于刷题,自己是没能力的. 最经一个朋友同事考我一道数组题 . 也许能当面试分享吧. 娱乐娱乐.

    事情的开始是这样的.

     

    前言

      题目 截图

    大概意思 是 在一个 数组中,找出其中两个不重复出现的元素. 其它元素都是两两出现. 返回结果顺序不要求. 

    好这里 看这个系统给我们的答题界面 . 我们选择C

    后面你只要做好题,就可以先 Run Code检测,后面 Submit Solution 提交了.

    下面我会讲出我的思路. 我没有Goolge答案, 也许不是最屌解. 大家可以再优化.  

    正文

    1.思索算法出路

      首选对于算法复杂度大于O(n),肯定不行.这里那就采用O(n)级别的套路. 这里有个 数学尝试

    a ^ a = 0, a ^ 0 = a, a ^ b = b ^ a. => a ^ b ^ a = a ^ a ^ b = 0 ^ b = b

    其中 ^ 表示异或的意思. 记得学习电子的是偶 好像 a ⊕ b是吧,不记得了,过吧.

      从上面算学只是我们很容易知道.

    a ^ a = 0, 那么 我们把上面 int* nums; 所有结果 异或, 最后得到 要找的两个数的异或值.

      好,那我们需要找出 其中一个数, 假定最后得到的数需要为 a,b

    那么上面 最后结果 就是 a ^ b => 转成二进制码 假如为 0x001100, 那么 a 和 b 在第三位 和第四位 二进制是不一样的.

    那么我们只需要找到 第一个 不一样的二进制位数, 再把 nums 中 这些位相同的 再异或一下就得到其中一个 结果.

    第一版代码如下

     1 /**
     2  * Return an array of size *returnSize.
     3  * Note: The returned array must be malloced, assume caller calls free().
     4  */
     5 int* singleNumber(int* nums, int numsSize, int* returnSize) {
     6     int* nnums = malloc(sizeof(int)*2);
     7     int i,j,sum = 0, flag = 1;
     8     int a = 0, b;
     9     
    10     // 先求所有的异或结果
    11     for(i=0; i<numsSize; ++i)
    12         sum ^= nums[i];
    13     //找到第一个位
    14     while(!(flag&sum))
    15         flag <<= 1;
    16     
    17     for(i=0; i<numsSize; ++i)
    18         if(flag & nums[i])
    19             a ^= nums[i];
    20     
    21     nnums[0] = a;
    22     nnums[1] = a ^ sum;
    23     
    24     *returnSize = 2;
    25     return nnums;
    26 }

    这样的代码 比较普通.

    测试通过要求, 下面我会优化一下!

    2.简单优化

    到这里我们优化一下,先直接看代码

     1 /**
     2  * Return an array of size *returnSize.
     3  * Note: The returned array must be malloced, assume caller calls free().
     4  */
     5 int* singleNumber(int* nums, int numsSize, int* returnSize) {
     6     int sl = 0, x, a = 0;
     7     int* end = nums + numsSize;
     8     int* pt = nums;
     9     //得到所有数据的异或和
    10     while(pt<end)
    11         sl ^= *pt++;
    12         
    13     // 找到第一个 位数
    14     x = sl & -sl;
    15     //先找到第一个数
    16     while(pt > nums){
    17         int t = *--pt;
    18         if(x&t) 
            a ^= t; 19 } 20 21 nums[0] = a; 22 nums[1] = a^sl; 23 *returnSize = 2; 24 return nums; 25 }

    用的技巧比较多, 例如  sl & -sl 找到最低位1出现的 位置值. 例如 sl = 0x0110 => sl & -sl => 0x0010.

    最后看运行结果图

    运行测试 平均时间 4ms, 第一梯队. 可能有更好的算法. 这里就这样了. 有机会 再被问,再同大家分享吧.

    大家有机会有时间尝试尝试 LeetCode QJ.

    后记

      错误是难免的. 有问题留言交流. 祝 今天 阳光明媚, 现在物价太高, 日子有点难,.....

    再扯一点, 30年前 一部大哥大 5000元多贵,现在印度安卓手机 包邮170, 其中150是邮费.

    我觉得房价也是这样, 租个10年. 后面也就是大白菜了......

      每个时代总有忽悠的主题, 缓一缓,思索后前进总有路子,

  • 相关阅读:
    windows下安装部署RocketMQ
    Windows安装RabbitMQ
    HttpClient工具类
    Docker部署Spring Boot项目
    在Docker中安装Redis以及主从环境搭建
    df命令得到一个诡异的现象
    一个“稍后再读”的软件 POCKET
    也是关于 Stay Hungry. Stay Foolish.
    改用thebrain做思维导图
    文件系统只读,一个没有解决的问题(续)
  • 原文地址:https://www.cnblogs.com/life2refuel/p/5235527.html
Copyright © 2011-2022 走看看