访谈:合并两个排序的单一链接列表

dha*_*ram 80 algorithm singly-linked-list

这是在面试的书面测试期间提出的编程问题."你有两个已经排序的单链表,你必须合并它们并返回新列表的头部而不创建任何新的额外节点.返回的列表也应该排序"

方法签名是:Node MergeLists(Node list1,Node list2);

节点类如下:

class Node{
    int data;
    Node next;
}
Run Code Online (Sandbox Code Playgroud)

我尝试了很多解决方案,但没有创建一个额外的节点螺丝.请帮忙.

以下是随附的博客文章http://techieme.in/merging-two-sorted-singly-linked-list/

Ste*_*ein 185

Node MergeLists(Node list1, Node list2) {
  if (list1 == null) return list2;
  if (list2 == null) return list1;

  if (list1.data < list2.data) {
    list1.next = MergeLists(list1.next, list2);
    return list1;
  } else {
    list2.next = MergeLists(list2.next, list1);
    return list2;
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 任意长列表的递归是堆栈溢出的一个配方.但我想这是Stack Overflow.哦,具有讽刺意味!;-) (109认同)
  • 不只是面试问题!我正处于截止日期之前,需要将其用于生产代码.谢谢! (8认同)
  • @PaulChernoch的prod代码你可能想使用下面的迭代版本.... (8认同)

Ste*_*ein 115

不应该需要递归来避免分配新节点:

Node MergeLists(Node list1, Node list2) {
  if (list1 == null) return list2;
  if (list2 == null) return list1;

  Node head;
  if (list1.data < list2.data) {
    head = list1;
  } else {
    head = list2;
    list2 = list1;
    list1 = head;
  }
  while(list1.next != null) {
    if (list1.next.data > list2.data) {
      Node tmp = list1.next;
      list1.next = list2;
      list2 = tmp;
    }
    list1 = list1.next;
  } 
  list1.next = list2;
  return head;
}
Run Code Online (Sandbox Code Playgroud)

  • +1 - 迭代方法几乎总是优于递归,在允许的情况下. (8认同)
  • 在一次采访中,您通常希望从符合标准的最干净/最短/最优雅的解决方案开始,然后进行改进 - 特别是,如果存在风险,您可能会用尽其他时间. (5认同)
  • @SonDo 选择接受的答案是OP的特权。所选择的答案没有任何问题。如果您认为这应该是公认的答案,您可以投票赞成。 (2认同)

小智 12

Node MergeLists(Node node1, Node node2)
{
   if(node1 == null)
      return node2;
   else (node2 == null)
      return node1;

   Node head;
   if(node1.data < node2.data)
   {
      head = node1;
      node1 = node1.next;
   else
   {
      head = node2;
      node2 = node2.next;
   }

   Node current = head;
   while((node1 != null) ||( node2 != null))
   {
      if (node1 == null) {
         current.next = node2;
         return head;
      }
      else if (node2 == null) {
         current.next = node1;
         return head;
      }

      if (node1.data < node2.data)
      {
          current.next = node1;
          current = current.next;

          node1 = node1.next;
      }
      else
      {
          current.next = node2;
          current = current.next;

          node2 = node2.next;
      }
   }
   current.next = NULL // needed to complete the tail of the merged list
   return head;

}
Run Code Online (Sandbox Code Playgroud)


Jai*_*dra 6

以下是如何合并两个已排序的链接列表A和B的算法:

while A not empty or B not empty:
   if first element of A < first element of B:
      remove first element from A
      insert element into C
   end if
   else:
      remove first element from B
      insert element into C
end while
Run Code Online (Sandbox Code Playgroud)

这里C将是输出列表.

  • 只有在创建新节点时才可以使用此选项.该问题限制了新节点的创建. (6认同)

wil*_*ser 5

看,没有递归!

struct llist * llist_merge(struct llist *one, struct llist *two, int (*cmp)(struct llist *l, struct llist *r) )
{
struct llist *result, **tail;

for (result=NULL, tail = &result; one && two; tail = &(*tail)->next ) {
        if (cmp(one,two) <=0) { *tail = one; one=one->next; }
        else { *tail = two; two=two->next; }
        }
*tail = one ? one: two;
return result;
}
Run Code Online (Sandbox Code Playgroud)