在书面测试中,我遇到了一个问题,内容如下:
我们得到一个整数链表,其中前半部分和后半部分都是独立排序的。编写一个函数来合并这两个部分以创建一个单独的排序链表。
约束:不要使用任何额外的空间。
测试用例和输出:
输入列表1:
4-> 5-> 6-> 7-> 1-> 2-> 3;
输出:
1-> 2-> 3-> 4-> 5-> 6-> 7
输入2:
5-> 6-> 7-> 8-> 1-> 2-> 3-> 4;
输出2:
1-> 2-> 3-> 4-> 5-> 6-> 7-> 8 >
我能想到的是使用两个指针:一个用于前半遍历,一个用于后半遍历。使用它们我可以从头到中(使用第一个指针)和从中间到最后(使用第二个指针)。在同时遍历两个部分的同时,我可以比较值并在需要时进行交换。
但是这种解决方案使用两个消耗内存的指针。
可以不使用任何内存吗?
由于这是笔试,我不能要求澄清。
协助表示赞赏。感谢。
答案 0 :(得分:4)
当他们说“不要使用额外的空间”时,他们并不意味着指针和标量;它们的意思是“数组”和“动态分配的结构”。在您的情况下,内存量是固定的。
合并两个有序列表很简单:首先,将列表切成两半,然后重新排列其元素的next
指针,使列表排序。
您需要三个指针 - newHead
,head1
和head2
。
head1
和head2
初始化为原始列表的head
head2
,直到您看到排序顺序中断(即head2->next->value
小于head2->value
时)。将head2->next
设置为NULL
,将列表剪切在那里;保留原始head2->next
- 这是您的新head2
此时,您有两个独立排序的单独链接列表,您可以应用经典合并算法。将newHead
设置为head1
或head2
的较小元素,然后循环移动,将当前最后一个元素的next
指针设置为较小的{{1} }或head1
。点击head2
或head1->next == NULL
后,将另一个列表的头部分配给首先用完元素的列表的head2->next == NULL
。您已完成 - next
现在指向已排序列表的开头。