zoukankan      html  css  js  c++  java
  • 《Cracking the Coding Interview》——第2章:链表——题目6

    2014-03-18 02:41

    题目:给定一个带有环的单链表,找出环的入口节点。

    解法1:用hash来检测重复节点肯定是容易想而且效率也高的好办法。

    代码:

     1 // 2.6 You have a circular Linked List: a->b->c->d->e->c. Find where the cycle starts.
     2 #include <cstdio>
     3 #include <unordered_set>
     4 using namespace std;
     5 
     6 struct ListNode {
     7     int val;
     8     ListNode *next;
     9     ListNode(int x): val(x), next(nullptr) {};
    10 };
    11 
    12 class Solution {
    13 public:
    14     ListNode* firstFirstNodeInCycle(ListNode *head) {
    15         if (head == nullptr) {
    16             return head;
    17         }
    18         
    19         // hash the pointers.
    20         unordered_set<ListNode *> us;
    21         ListNode *ptr;
    22         
    23         ptr = head;
    24         while (ptr != nullptr) {
    25             if (us.find(ptr) != us.end()) {
    26                 // the first node of the cycle is found.
    27                 return ptr;
    28             } else {
    29                 us.insert(ptr);
    30                 ptr = ptr->next;
    31             }
    32         }
    33         
    34         // the list has no cycle.
    35         return nullptr;
    36     }
    37 };
    38 
    39 int main()
    40 {
    41     int i;
    42     int n, k;
    43     int val;
    44     struct ListNode *head, *tail, *ptr;
    45     Solution sol;
    46     
    47     while (scanf("%d", &n) == 1 && n > 0) {
    48         // create a linked list
    49         ptr = head = tail = nullptr;
    50         for (i = 0; i < n; ++i) {
    51             scanf("%d", &val);
    52             if (head == nullptr) {
    53                 head = ptr = new ListNode(val);
    54             } else {
    55                 ptr->next = new ListNode(val);
    56                 ptr = ptr->next;
    57             }
    58         }
    59         tail = ptr;
    60         
    61         // create a cycle in the list
    62         scanf("%d", &k);
    63         if (k >= 1 && k <= n) {
    64             ptr = head;
    65             for (i = 1; i < k; ++i) {
    66                 ptr = ptr->next;
    67             }
    68             tail->next = ptr;
    69         }
    70         
    71         // find the first node in the cycle.
    72         ListNode *first_node = sol.firstFirstNodeInCycle(head);
    73         if (first_node != nullptr) {
    74             printf("%d
    ", first_node->val);
    75         } else {
    76             printf("no cycle
    ");
    77         }
    78         
    79         /*
    80         // print the list
    81         ptr = head;
    82         for (i = 0; i < n; ++i) {
    83             printf("%d->", ptr->val);
    84             ptr = ptr->next;
    85         }
    86         printf("
    ");
    87         */
    88 
    89         // delete the list
    90         for (i = 0; i < n; ++i) {
    91             ptr = head->next;
    92             delete head;
    93             head = ptr;
    94         }
    95     }
    96     
    97     return 0;
    98 }

    解法2:如果你非不让我用hash,就只有观察一下几个特殊节点了。既然这个环有“第一个”点,那肯定也有“最后一个”点。我特地打了引号,是因为最后一个点恰好指向第一个。如果你从链表的头开始向后遍历,必然是先到达“第一个”,然后才能到达“最后一个的”。只有对于“最后一个”点,才会出现先到达ptr->next,后到达ptr的情况,所以如果存在符合这个情况的节点ptr,ptr->next就是我们要找的环的入口。这种方法效率不高而且不容易想,除了面试之外基本没有别的用处了。但为了面试淘汰一些人,这点用处也很重要了。

    代码:

      1 // 2.6 You have a circular Linked List: a->b->c->d->e->c. Find where the cycle starts.
      2 #include <cstdio>
      3 #include <unordered_set>
      4 using namespace std;
      5 
      6 struct ListNode {
      7     int val;
      8     ListNode *next;
      9     ListNode(int x): val(x), next(nullptr) {};
     10 };
     11 
     12 class Solution {
     13 public:
     14     ListNode* firstFirstNodeInCycle(ListNode *head) {
     15         if (head == nullptr) {
     16             return head;
     17         }
     18         
     19         ListNode *p1, *p2;
     20         
     21         p1 = head;
     22         while (p1 != nullptr) {
     23             p2 = head;
     24             while (p2 != p1->next && p2 != nullptr) {
     25                 if (p2 == p1) {
     26                     break;
     27                 } else {
     28                     p2 = p2->next;
     29                 }
     30             }
     31             if (p2 == p1->next) {
     32                 return p2;
     33             } else {
     34                 p1 = p1->next;
     35             }
     36         }
     37         
     38         return nullptr;
     39     }
     40 };
     41 
     42 int main()
     43 {
     44     int i;
     45     int n, k;
     46     int val;
     47     struct ListNode *head, *tail, *ptr;
     48     Solution sol;
     49     
     50     while (scanf("%d", &n) == 1 && n > 0) {
     51         // create a linked list
     52         ptr = head = tail = nullptr;
     53         for (i = 0; i < n; ++i) {
     54             scanf("%d", &val);
     55             if (head == nullptr) {
     56                 head = ptr = new ListNode(val);
     57             } else {
     58                 ptr->next = new ListNode(val);
     59                 ptr = ptr->next;
     60             }
     61         }
     62         tail = ptr;
     63         
     64         // create a cycle in the list
     65         scanf("%d", &k);
     66         if (k >= 1 && k <= n) {
     67             ptr = head;
     68             for (i = 1; i < k; ++i) {
     69                 ptr = ptr->next;
     70             }
     71             tail->next = ptr;
     72         }
     73         
     74         // find the first node in the cycle.
     75         ListNode *first_node = sol.firstFirstNodeInCycle(head);
     76         if (first_node != nullptr) {
     77             printf("%d
    ", first_node->val);
     78         } else {
     79             printf("no cycle
    ");
     80         }
     81         
     82         /*
     83         // print the list
     84         ptr = head;
     85         for (i = 0; i < n; ++i) {
     86             printf("%d->", ptr->val);
     87             ptr = ptr->next;
     88         }
     89         printf("
    ");
     90         */
     91 
     92         // delete the list
     93         for (i = 0; i < n; ++i) {
     94             ptr = head->next;
     95             delete head;
     96             head = ptr;
     97         }
     98     }
     99     
    100     return 0;
    101 }
  • 相关阅读:
    Deep Reinforcement Learning with Population-Coded Spiking Neural Network for Continuous Control
    A Survey of Robotics Control Based on Learning-Inspired Spiking Neural Networks
    The neurobiology of deep reinforcement learning
    【Matplotlib】线设置,坐标显示范围
    MarkdownPad2 下一些设置
    MarkdownPad2 在 Windows10 下 预览无法显示
    【Scipy】初步认识
    【Matplotlib】详解图像各个部分
    【Matplotlib】概要总览第一讲
    【Python】重载模块
  • 原文地址:https://www.cnblogs.com/zhuli19901106/p/3606698.html
Copyright © 2011-2022 走看看