【问题标题】:Merge Two Sorted Lists got RUNTIME ERROR合并两个排序列表得到 RUNTIME ERROR
【发布时间】:2015-11-12 06:30:21
【问题描述】:

这是我在 Leetcode 上的“合并两个排序列表”算法问题的代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode *dummy, *pre;
        dummy->next = l1;
        pre = dummy;
        while(l1 != NULL & l2 != NULL) {
            if(l1->val < l2->val) {
                pre = l1;
                l1 = l1->next;
            } else {
                pre->next = l2;
                l2->next = l1;
                pre = l2;
                l2 = l2->next;
            }
        }
        if(l2 != NULL) {
            pre->next = l2;
        }
        return dummy->next;

    }
};

我得到了一个运行时错误。但是我的代码有什么问题?

【问题讨论】:

  • 首先在dummy中分配内存。然后访问其next 字段。
  • 请查看下面给出的答案,谢谢。

标签: c++ algorithm list


【解决方案1】:

我认为你得到了Segmentation Fault(Core Dump),因为你试图访问无效的内存:

dummy->next = l1;

您应该在访问*dummy*pre 之前为其成员分配内存。

还在循环中使用&amp;&amp;(逻辑运算符)而不是&amp;(位运算符)。替换:

while(l1 != NULL & l2 != NULL) {

while(l1 != NULL && l2 != NULL) {

使用new操作符分配内存,请使用delete释放内存,避免内存泄漏。

另请注意,实现本身在逻辑上是错误。请参考here 以获得更好的实现。

这是一个简单的递归实现:

ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { 
{
  ListNode* result = NULL;

  /* Base cases */
  if (l1 == NULL) 
     return (l2);
  else if (l2 == NULL) 
     return (l1);

  if (l1->data <= l2->data) 
  {
     result = l1;
     result->next = mergeTwoLists(l1->next, l2);
  }
  else
  {
     result = l2;
     result->next = mergeTwoLists(l1, l2->next);
  }
  return(result);
}

【讨论】:

  • 没错,这是错误的直接原因,但您不需要分配任何内存来破坏性地合并两个排序列表。 OP 应该重写他们的代码
  • Leetcode alert "RUNTIME ERROR Last executed input: [], []"
【解决方案2】:

我相信正确的实现将需要比 OP 中的代码更多的代码。这是您可以尝试的正确实现。我假设输入列表l1l2 按降序排列(即从头到尾从大到小)。

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode *pnt1 = l1;
        ListNode *pnt2 = l2;
        ListNode *head;

        // assign the head pointer to larger head of the two input lists
        if (l1->val > l2->val) {
            head = l1;
        }
        else {
            head = l2;
        }

        // walk through both lists sequentially,
        // and splice together the sorted list
        while (pnt1->next != NULL & pnt2->next != NULL) {
            if(pnt2->val > pnt1->next->val && pnt1->val > pnt2->val) {
                ListNode* next = pnt1->next;
                pnt1->next = pnt2;
                pnt1 = next;
            }
            else if(pnt2->val > pnt1->next->val && pnt1->val <= pnt2->val) {
                ListNode* next = pnt2->next;
                pnt2->next = pnt1;
                pnt2 = next;
            }
            else if(pnt2->val <= pnt1->next->val && pnt1->val > pnt2->val) {
                pnt1 = pnt1->next;
            }
        }

        // handle edge case where end of one or two list(s) has been reached
        if (pnt1->next == NULL && pnt2->next == NULL) {
            if (pnt1->val > pnt2->val) {
                pnt1->next = pnt2;
            }
            else {
                pnt2->next = pnt1;
            }
        }
        else if (pnt1->next == NULL) {
            while (pnt2->next != NULL) {
                if (pnt1->val > pnt2->next->val) {
                    ListNode* next = pnt2->next;
                    pnt2->next = pnt1;
                    pnt1->next = next;
                    break;
                }
                pnt2 = pnt2->next;
            }
            if (pnt2->next == NULL) {
                pnt2->next = pnt1;
            }
        }
        else if (pnt2->next == NULL) {
            while (pnt1->next != NULL) {
                if (pnt2->val > pnt1->next->val) {
                    ListNode* next = pnt1->next;
                    pnt1->next = pnt2;
                    pnt2->next = next;
                    break;
                }
                pnt1 = pnt1->next;
            }
            if (pnt1->next == NULL) {
                pnt1->next = pnt2;
            }
        }

        return head;
    }
};

【讨论】:

  • 他的原始代码看起来很乱,我认为写一个新的答案会更有益。如果出现问题,Stack Overflow 没有义务使用原始代码。
【解决方案3】:

您的代码中的主要问题是您正在使用:

    dummy->next = l1;

dummy 尚未初始化为指向有效对象时。

您还使用了按位&amp;,其中逻辑&amp;&amp; 是合适的。

    while(l1 != NULL & l2 != NULL) {

这是一个建议的实现。

PS它没有经过测试,但在我看来是正确的。

ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {

   ListNode* ret = NULL;
   ListNode* pre = NULL;

   // Make sure the start of the list to be returned points to the right
   // ListNode.
   if ( l1 != NULL && l2 != NULL )
   {
      if ( l1->val < l2->val )
      {
         ret = l1;
         l1 = l1->next;
      }
      else
      {
         ret = l2;
         l2 = l2->next;
      }
   }
   else if ( l1 != NULL )
   {
      return l1;
   }
   else
   {
      return l2;
   }

   pre = ret;

   while(l1 != NULL && l2 != NULL) {

      // Figure out where pre->next must point to.
      // Advance l1 and l2 appropriately.
      if(l1->val < l2->val) {
         pre->next = l1;
         pre = l1;
         l1 = l1->next;
      } else {
         pre->next = l2;
         pre = l2;
         l2 = l2->next;
      }
   }

   // Make sure pre->next points to the remaining ListNodes.
   // They could be in l1 or l2.
   if ( l1 != NULL )
   {
      pre->next = l1;
   }

   if( l2 != NULL)
   {
      pre->next = l2;
   }

   return ret;
}

【讨论】:

    【解决方案4】:

    除了已经指出的问题之外,原始代码没有处理首先到达列表 2 末尾的情况,在这种情况下,列表 1 的其余部分应该附加到合并列表中。使用指向指针的指针(而不是前一个指针)使代码更简单。这是合并两个列表的示例代码,也是使用合并列表功能的自下而上合并排序。排序使用指向列表的指针数组,其中 array[i] 要么为 null,要么指向其中包含 pow(2,i) 元素的列表。

    ListNode * MergeLists(ListNode *pl1, ListNode *pl2)
    {
    ListNode *plm = NULL;                   /* merged list head ptr */
    ListNode **pplm = &plm;                 /* ptr to head or prev->next */
        if(pl1 == NULL)
            return pl2;
        if(pl2 == NULL)
            return pl1;
        while(1){
            if(pl2->val < pl1->val){        /* if src2 < src1 */
                *pplm = pl2;
                pl2 = *(pplm = &(pl2->next));
                if(pl2 == NULL){
                    *pplm = pl1;
                    break;
                }
            } else {                        /* src1 <= src2 */
                *pplm = pl1;
                pl1 = *(pplm = &(pl1->next));
                if(pl1 == NULL){
                    *pplm = pl2;
                    break;
                }
            }
        }
        return plm;
    }
    
    #define NUMLISTS 32                     /* number of lists */
    ListNode * SortList(ListNode *pList)
    {
    ListNode * aList[NUMLISTS];             /* array of lists */
    ListNode * pNode;
    ListNode * pNext;
    int i;
        if(pList == NULL)                   /* check for empty list */
            return NULL;
        for(i = 0; i < NUMLISTS; i++)       /* zero array */
            aList[i] = NULL;
        pNode = pList;                      /* merge nodes into aList[] */
        while(pNode != NULL){
            pNext = pNode->next;
            pNode->next = NULL;
            for(i = 0; (i < NUMLISTS) && (aList[i] != NULL); i++){
                pNode = MergeLists(aList[i], pNode);
                aList[i] = NULL;
            }
            if(i == NUMLISTS)
                i--;
            aList[i] = pNode;
            pNode = pNext;
        }
        pNode = NULL;                       /* merge array into one list */
        for(i = 0; i < NUMLISTS; i++)
            pNode = MergeLists(aList[i], pNode);
        return pNode;
    }
    

    【讨论】:

      猜你喜欢
      • 2015-05-12
      • 1970-01-01
      • 2022-10-05
      • 1970-01-01
      • 2022-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-16
      相关资源
      最近更新 更多