zoukankan      html  css  js  c++  java
  • 笔试算法题(18):常数时间删除节点 & 找到仅出现一次的两个数字

    出题:给定链表的头指针和一个节点指针,要求在O(1)的时间复杂度下删除该节点

    分析:

    • 如果需要删除的节点为A,其前序节点为A-,其后续节点为A+,所以删除A之后,需要使得A-的下一个节点就是A+,常规做法是设法得到A-的索引,需要 从链表头开始遍历所以时间复杂度为O(N),但实际情况是只要保证A-的下一个节点是A+就行;
    • 所以可将A+节点的内容直接复制到A节点,这时时间复杂度 为O(1),对于最后一个节点而言需要使用O(N)的时间复杂度,所以平均复杂度为(O(1)*(n-1) + O(n))/n,所以平均复杂度为O(1);

    解题:

     1 struct Node {
     2         int v;
     3         Node *next;
     4 };
     5 
     6 void deleteNode(Node *head, Node *target) {
     7         if(target == NULL) return;
     8         if(target->next != NULL) {
     9                 Node *temp=target->next;
    10                 target->v=temp->v;
    11                 target->next=temp->next;
    12                 delete temp;
    13         } else {
    14                 Node *temp=head;
    15                 while(temp!=NULL) {
    16                         if(temp->next != target)
    17                                 temp=temp->next;
    18                         else {
    19                                 temp->next=temp->next->next;
    20                                 delete target;
    21                                 break;
    22                         }
    23                 }
    24         }
    25 }

    出题:给定一个整型数组,除了两个数字只出现一次外其他数字都出现了两次,要求确定这个两个只出现一次的数字,时间复杂度为O(N),空间复杂度为O(1);

    分析:

    • 由于任何一个数字异或它本身的结果都为0,所以从左到右依次异或整型数组,数组中出现两次的数字的异或结果为0,则最终的结果就是出现一次的两个数字的异 或结果;由于这两个数字肯定不同,所以结果肯定非0,为了将这两个数字分别放到一个子数组中,选取结果中第一个出现的1(第k位),这样根据第k位是否为 1将数组元素分成两个子数组,他们分别包含了一个只出现一次的数字,然后针对每一个子数组重新进行异或运算,最终就可分别得到这两个仅出现一次的数字;
    • 本题参考何海涛老师的解法,海涛老师威武!!非常感谢何海涛老师的无私奉献,其博客地址为:
      http://zhedahht.blog.163.com/

    解题:

     1 void findInteger(int *array, int length) {
     2         /**
     3          * 获取整个数组的异或结果
     4          * sum1为两个目标数字的异或结果
     5          * */
     6         int sum1=array[0];
     7         for(int i=1;i<length;i++)
     8                 sum1^=array[i];
     9         /**
    10          * 找到sum1中最低位出现的1
    11          * k表示目标位上出现的1
    12          * */
    13         int k=1,i;
    14         for(i=0;i<sizeof(int)*8;i++) {
    15                 if(sum1 & k<<i) break;
    16         }
    17         k<<=i;
    18         /**
    19          * 使用k区分不同的子数组
    20          * 分别对子数组使用异或
    21          * */
    22         int int1=1, int2=1;
    23         for(int i=0;i<length;i++) {
    24                 if(array[i]&k)
    25                         int1^=array[i];
    26                 else
    27                         int2^=array[i];
    28         }
    29         int1^=1;int2^=1;
    30         printf("
    the first integer: %d",int1);
    31         printf("
    the second integer: %d",int2);
    32 }
    33 
    34 int main() {
    35         int array[]={11,22,11,22,23,-9,-9,15};
    36         findInteger(array,8);
    37         return 0;
    38 }
  • 相关阅读:
    实验0 了解和熟悉操作系统
    软件工程感想
    递归下降分析法--算数语法分析
    有限自动机的构造与识别
    评论
    文法解释
    【编译CEF3】2017-07 添加支持mp3 mp4的编译日记
    Visual Studio 2015/2013安装失败:Microsoft Visual Studio 2015 Shell (Minimum) Interop Assemblies 安装时发生严重错误
    [RAD Studio 10.2 Tokyo] Error:java.lang.UnsupportedClassVersionError: com/android/dx/command/Main : Unsupported major错误解决
    Delphi 编译出来的程序被小红伞报病毒 TR/Spy.Banker.Gen4 [trojan]
  • 原文地址:https://www.cnblogs.com/leo-chen-2014/p/3740580.html
Copyright © 2011-2022 走看看