• 笔试算法题(27):判断单向链表是否有环并找出环入口节点 & 判断两棵二元树是否相等


    出题:判断一个单向链表是否有环,如果有环则找到环入口节点;

    分析:

    • 第一个问题:使用快慢指针(fast指针一次走两步,slow指针一次走一步,并判断是否到达NULL,如果fast==slow成立,则说明链表有环);
    • 第二个问题:fast与slow相遇时,slow一定还没有走完一圈(反证法可证明);
       
       示意图

      A为起始点,B为环入口点,C为相遇点,则a1=|AB|表示起始点到换入口的距离,a2=|CB|表示相遇点到环入口点的距离,s1=|AB|+|BC|表示slow指针走的长度,s2表示fast指针走的长度,C=|BCB|表示环的长度
      由于fast的速度是slow的2倍,所以相遇的时候走过的长度也是2倍
      s2=2*s1=a1+N*C+(s1-a1) (1)
      N表示fast在环中走的圈数,化解(1)得到:
      s1=N*C (2)
      找到a1和a2的关系:
      a2=C-(s1-a1) (3)
      将(2)代入(3)得到:
      a1=a2+(N-1)*C (4)
      所以如果指针m从起始点A出发,指针n从相遇点C出发,n绕行(N-1)圈环之后最终跟m指针在B点相遇

    解题:

     1 struct Node {
     2         int v;
     3         Node *next;
     4 };
     5 Node* IsCycle(Node *head) {
     6         Node *fast=head, *slow=head;
     7 
     8         while(true) {
     9                 if(fast!=NULL)
    10                         fast=fast->next;
    11                 if(fast!=NULL)
    12                         fast=fast->next;
    13                 else
    14                         return NULL;
    15                 if(slow!=NULL)
    16                         slow=slow->next;
    17                 else
    18                         return NULL;
    19 
    20                 if(fast==slow)
    21                         return fast;
    22         }
    23 }
    24 Node* FindEntry(Node *head, Node *joint) {
    25         Node *m=head, *n=joint;
    26         while(true) {
    27                 if(m==n)
    28                         return m;
    29                 m=m->next;
    30                 n=n->next;
    31         }
    32 }
    33 int main() {
    34         Node* b1=new Node(); b1->v=1;
    35         Node* b2=new Node(); b2->v=2;b1->next=b2;
    36         Node* b3=new Node(); b3->v=3;b2->next=b3;
    37         Node* b4=new Node(); b4->v=4;b3->next=b4;
    38         Node* b5=new Node(); b5->v=5;b4->next=b5;
    39         Node* b6=new Node(); b6->v=6;b5->next=b6;
    40         Node* b7=new Node(); b7->v=7;b6->next=b7;
    41         Node* b8=new Node(); b8->v=8;b7->next=b8; b8->next=b3;
    42 
    43         Node* temp;
    44         if((temp=IsCycle(b1))!=NULL) {
    45                 printf("
    the joint point is: %d",temp->v);
    46                 printf("
    the entry of cycle is: %d",FindEntry(b1,temp)->v);
    47         }
    48         else
    49                 printf("
    there is no cycle.");
    50         return 0;
    51 }

    出题:判断两棵二元树是否相等(左右子树不能交叉比较);

    分析:使用递归实现,在树的K层,有2^K 个节点,所以会进行(2^K)*2次调用,所以时间复杂度为O(N);

    解题:

     1 struct Node {
     2         int value;
     3         Node *left;
     4         Node *right;
     5 };
     6 
     7 bool CompareTree(Node *first, Node *second) {
     8         if(first==NULL && second==NULL)
     9                 return true;
    10         if((first==NULL && second!=NULL) ||
    11                         (first!=NULL && second==NULL))
    12                 return false;
    13         if(first->value!=second->value)
    14                 return false;
    15         return CompareTree(first->left,second->left) &&
    16                         CompareTree(first->right, second->right);
    17 }
  • 相关阅读:
    新的页面事件的添加
    excel里数字0不显示
    VB6接口、对象比较等
    SQL SERVER服务停止和启动命令行
    如何更改VS2008的字体和大小
    如何部署windows service
    模式应用 - 利用工厂模式制作自己的"小程序测试工厂"
    解决Oracle Temp01.dbf不断变大的问题
    如何配置VS2008让它用外置IIS进行调试
    使用JQuery Autocomplete插件(一)
  • 原文地址:https://www.cnblogs.com/leo-chen-2014/p/3747122.html
Copyright © 2020-2023  润新知