• 一道面试题想到的


            两道题目,1、有一堆的数,其中所以的数都出现了两次,只有一个出现了一次,找出那个只出现一次的数。

                          2、有一堆的数,其中所以的数都出现了三次,只有一个出现了一次,找出那个只出现一次的数。

           对于这种题目,我们可能首先想到是排序。当然,排序可以解决问题,但是排序的复杂度实在是太高了,至少也得O(nlogn)吧。

           那么有没有什么方式可以使得其复杂度下降呢?

           对于第一道题,我们可能会想到很多种方式,最简单的就是异或运算了,最终得到的结果肯定是只出现一次的那个数。

            那么对于第二道题,我们应该怎么解呢?我想了很久,好像只能通过排序来解。因为似乎第一道题的方法都不行。后来我想到,也许可以建立哈希表,同时保留出现的次数,那么他的复杂度就是O(n).相比O(nlogn)方式快不少吧。

            我这里哈希表冲突处理方式是链接法:

           下面是数据结构的定义

       

     1 #define Count 100
     2 typedef int ElemType;
     3 typedef int Times;
     4 using namespace std;
     5 struct Elem{
     6     ElemType data;
     7     Times time;
     8 };
     9 struct HashTable{
    10     Elem elem;  //元素信息
    11     int len;    //长度
    12     HashTable *next;  //冲突处理
    13 };
    14 typedef HashTable HT;
    15 HT ht[Count];

     下面是主要函数方法:

    1 Elem&  createElem(ElemType data,Elem &x);//生成元素信息
    2 HT* createHTNode(Elem x);//生成一个冲突处理节点
    3 int pushHash(ElemType data);//增加一个元素到哈希表中
    4 int popHash(ElemType data);//查找一个元素,并返回出现的次数
    5 void InitHash();//初始化哈希函数
     1 //生成元素信息
     2 Elem&  createElem(ElemType data,Elem &x){
     3     x.data=data;
     4     x.time=1;
     5     return x;
     6 }
     7 //冲突后生成节点
     8 HT* createHTNode(Elem x){
     9     HT* h=(HT*)malloc(sizeof(HT));
    10     (*h).elem=x;
    11     (*h).next=NULL;
    12     return h;
    13 }
     1 //初始化哈希表
     2 void InitHash(){
     3     for(int i=0;i<Count;i++){
     4         ht[i].len=0;
     5         ht[i].next=NULL;
     6     }
     7 }
     8 //把数字不断增加进哈希表中,代码感觉很累赘,希望高手指点下。
     9 int pushHash(ElemType data){
    10     int k=data%Count;
    11     Elem x;
    12     createElem(data,x);
    13     //长度为1直接加入
    14     if(ht[k].len==0){
    15         ht[k].elem=x;
    16         ht[k].len++;
    17         return 1;
    18     }
    19     //是否是第一个节点,若是直接增加次数
    20     if(ht[k].elem.data==data){
    21         ht[k].elem.time++;
    22         return 1;
    23     }
    24     HT *point=createHTNode(x);
    25     //判断是否没有next节点
    26     if(ht[k].len==1){
    27         ht[k].next=point;
    28         ht[k].len++;
    29         return 1;
    30     }
    31     HT *p=ht[k].next;
    32     while((*p).next!=NULL){
    33         if((*p).elem.data==data){
    34             (*p).elem.time++;
    35             return 1;
    36         }else
    37              p=(*p).next;
    38     }
    39     if((*p).elem.data==data)
    40         (*p).elem.time++;
    41     else{
    42         (*p).next=point;
    43         ht[k].len++;
    44     }
    45     return 0;
    46 }
     1 //返回出现的次数
     2 int popHash(ElemType data){
     3     int k=data%Count;
     4     if(ht[k].len==0)
     5             return 0;
     6     if(ht[k].elem.data==data)
     7         return ht[k].elem.time;
     8     HT* p=ht[k].next;
     9     while(p!=NULL)
    10         if((*p).elem.data==data)
    11             return (*p).elem.time;
    12         else
    13             p=(*p).next;
    14     return 0;
    15 }

    感觉代码还是有些累赘,希望后面自己再改进。

    留言中有位仁兄提到了别人的一种方法,觉得非常好。主要是利用出现三次的话,各个位肯定是3的整数倍,那么各位取余就得到了只出现一次的数。方法连接如下:

     新方法

  • 相关阅读:
    查看Linux 系统串口信息
    解决:Web server failed to start. Port XXX was already in use
    SpringBoot集成WebSocket长连接实际应用详解
    EMQTT安装与使用
    mysql 分组查每组里创建时间最大的那条数据
    前端 获取本地时间,ios兼容
    SpringBoot:访问Mysql报错message from server: "Host 'XXXX' is blocked because of many connection errors
    Doker:dockercompose安装与操作
    Docker:docker安装操作InfluxDB时序数据库
    ASP.NET Core gRPC服务基础小例子
  • 原文地址:https://www.cnblogs.com/xiaoyi115/p/3621768.html
Copyright © 2020-2023  润新知