当前位置: 首页 > 知识库问答 >
问题:

Leetcode简易链表问题:为什么我的解决方案是错误的?(21.合并2个排序列表)

百里修真
2023-03-14

问题:合并两个排序链表,并将其作为一个新的排序列表返回。新列表应该通过将前两个列表的节点拼接在一起来制作。

示例:输入:1-

我的解决方案:

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */

var mergeTwoLists = function(l1, l2, l3) {
    if (l2 === null) {
        l3.next = l1;
        return l3;
    }
    if (l1 === null) {
        l3.next = l2;
        return l3;
    }
    if (l2.val < l1.val) {
        if (l3) {
            l3.next = new ListNode(l2.val) 
        }
        else {
            l3 = new ListNode(l2.val)
        }
        return mergeTwoLists(l1, l2.next, l3)
    } else {
        if (l3) {
            l3.next = new ListNode(l1.val);
        }
        else {
            l3 = new ListNode(l1.val);
        }
        return mergeTwoLists(l1.next, l2, l3)
    }
};

我的输出只有1-

共有3个答案

庾勇军
2023-03-14

您的答案仅返回1-

下面是应该为您提供所需结果的代码

function ListNode(val, next) {
  this.val = (val === undefined ? 0 : val)
  this.next = (next === undefined ? null : next)
}
var mergeTwoLists = function(l1, l2, l3) {
  let addToMergedList = (l3, val) => {
    let rootNode = l3
    while (l3.next !== null)
      l3 = l3.next;
    l3.next = new ListNode(val);
    return rootNode;
  }
  if (l2 === null) {
    let root = l3
    if(!root)
      return l1
    while (l3.next)
      l3 = l3.next;
    l3.next = l1;
    return root;
  }
  if (l1 === null) {
    let root = l3
    if(!root)
     return l2
    while (l3.next)
      l3 = l3.next;
    l3.next = l2;
    return root;
  }
  if (l2.val < l1.val) {
    if (l3) {
      l3 = addToMergedList(l3, l2.val)
    } else {
      l3 = new ListNode(l2.val)
    }
    return mergeTwoLists(l1, l2.next, l3)
  } else {
    if (l3) {
      l3 = addToMergedList(l3, l1.val)
    } else {
      l3 = new ListNode(l1.val);
    }
    return mergeTwoLists(l1.next, l2, l3)
  }
};

let l1={val:1,next:{val:2,next:{val:4,next:null}}}
let l2={val:1,next:{val:3,next:{val:4,next:null}}
console.log(mergeTwoLists(l1, l2))

邢飞白
2023-03-14

您可以使用Sentinel节点,以便更轻松:

const mergeTwoLists = function(l1, l2) {
    const sentinel = {
        val: -1,
        next: null
    }

    let head = sentinel
    while (l1 && l2) {
        if (l1.val > l2.val) {
            head.next = l2
            l2 = l2.next
        } else {
            head.next = l1
            l1 = l1.next
        }
        
        head = head.next
    }

    head.next = l1 || l2

    return sentinel.next
}

如果您希望递归执行,我们将不需要l3

const mergeTwoLists = function(l1, l2) {
    if (l1 === null) {
        return l2
    }

    if (l2 === null) {
        return l1
    }

    if (l1.val < l2.val) {
        l1.next = mergeTwoLists(l1.next, l2)
        return l1

    } else {
        l2.next = mergeTwoLists(l1, l2.next)
        return l2
    }
}
吴嘉禧
2023-03-14

您遇到的问题的主要原因是函数的第三个参数:这与挑战的描述不一致。没有第三个参数。您需要创建不带此值的返回列表。

我知道您试图将部分结果作为第三个参数传递,并希望在每次递归调用中扩展该部分结果,但随后出现了问题:

首先,在前两个if块中,假设l3不是null,但您不能确定这一点。如果输入由空列表组成,代码将生成异常。

其次,如果l3表示包含多个元素的列表,则此代码将覆盖l3l3之间的现有链接。接下来是原始的l3。接下来(以及随后的所有节点)将丢失。

尽管您可以通过首先在l3中查找终止节点来解决此问题,但还有一种更好的方法。这种更好的方法实际上是精心设计的递归的核心原则:

如果可能,不要为了将部分结果扩展到最终结果而将部分结果传递给递归调用。相反,尝试以这样一种方式创建函数,即它不需要调用者提供任何这样的部分结果,但可以对输入执行其工作,就好像这是最原始的输入一样。调用者应该使用返回的值将其视为部分结果,并在将其返回给调用者之前对其进行扩展。

function ListNode(val, next) {
    this.val = (val===undefined ? 0 : val)
    this.next = (next===undefined ? null : next)
}

var mergeTwoLists = function(l1, l2) { // Only 2 parameters
    if (l2 === null) return l1; // don't prepend anything
    if (l1 === null) return l2; // don't prepend anything
    let node;
    if (l2.val < l1.val) {
        node = new ListNode(l2.val);
        node.next = mergeTwoLists(l1, l2.next);
    } else {
        node = new ListNode(l1.val);
        node.next = mergeTwoLists(l1.next, l2);
    }
    return node;
};

// Helper function for demo
const listFromArray = a => a.length ? new ListNode(a[0], listFromArray(a.slice(1)))  
                                    : null;

let l1 = listFromArray([1, 2, 4]);
let l2 = listFromArray([1, 3, 4]);
console.log(mergeTwoLists(l1, l2));

 类似资料:
  • 我有一个关于python中链接列表的快速问题。在下面显示的解决方案代码中,当我尝试合并两个排序的链接列表时。我对包含的if和elif语句的条件感到困惑。例如,如果l1不为空,l2为空,我想将l1中的其余3个元素添加到我的新链接列表中,但代码显示l1和tail没有更新,所以它不是只添加3个元素中的一个吗? 我的另一个问题是关于返回head.next.返回会自动返回从head.next到null pt

  • LeetCode上说明的问题如下: 合并k个排序链表,并将其作为一个排序列表返回。分析并描述其复杂性。 例子: 输入:[1- 我能够通过131个测试案例中的129个,但在案例130中达到了“超出时间限制”。下面是我的实现。 有人能发现瓶颈吗?对提高时间复杂度有什么建议吗? 我在没有使用的情况下遇到了超过时间限制的问题。测试用例130包含10,000个LinkedList。

  • 将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 我的链表合并以及排序的函数(mergeTwoLists)代码是哪里有问题吗,为什么我在VS上运行没报错,leetcode上运行就报错了 效果图片 leetcode报错图片

  • 我在计算机课上遇到了合并排序的问题。我不断收到错误或返回原始ArrayList。 我相信合并排序涉及到将数组(列表)递归地对半拆分,直到只剩下一个元素,然后从这些单独的元素开始,按排序顺序合并它们。直到数组(列表)被排序为止。至于实际的排序部分,我试图在新的ArrayList中插入两半之间的较高值,直到它们都为空,在这种情况下,填充的ArrayList现在被排序。 这是我当前的代码: 我将感谢任何

  • 以下是对不熟悉此问题的人的问题声明: 给定一个二维板和一个单词,找出这个单词是否存在于网格中。这个词可以由顺序相邻单元格的字母构成,其中“相邻”单元格是那些水平或垂直相邻的单元格。同一个字母单元格不能使用不止一次。 解决方案2 现在,据我所知,随着Java的短路,的两个版本都应该停止探索其他路径,如果任何子问题返回true。事实上,我可以评估的两个版本之间唯一的操作差异是,如果找到解决方案,第一个

  • 对于python我是新手,我正在做leetcode问题94,二叉树顺序遍历。给定二叉树的根,返回对其节点值的inorder遍历。 但我还是不明白它为什么有用。在之后,在递归过程中,res变量不会被重新分配给[]吗?或者res变量在不同的递归中应该是不同的变量吗?