就地合并两个链表而不改变第一个链表的链接
给定两个分别具有 n 和 m 个元素的已排序单链表,使用常量空间合并它们。两个列表中的前 n 个最小元素应成为第一个列表的一部分,其余元素应成为第二个列表的一部分。应保持排序顺序。我们不允许更改第一个链表的指针。
例如,
Input:
First List: 2->4->7->8->10
Second List: 1->3->12
Output:
First List: 1->2->3->4->7
Second List: 8->10->12
我们强烈建议您将浏览器最小化,然后自己先尝试一下。
如果我们允许改变第一个链表的指针,问题就变得很简单了。如果我们被允许更改链接,我们可以简单地做一些类似归并排序算法合并的事情。我们将前 n 个最小元素分配给第一个链表,其中 n 是第一个链表中元素的数量,其余的分配给第二个链表。我们可以在 O(m + n) 时间和 O(1) 空间内实现这一点,但是这个解决方案违反了我们不能更改第一个列表的链接的要求。
这个问题变得有点棘手,因为我们不允许更改第一个链表中的指针。这个想法类似于这篇文章,但是由于我们给出了单向链表,我们无法向后处理 LL2 的最后一个元素。
这个想法是对于 LL1 的每个元素,我们将它与 LL2 的第一个元素进行比较。如果 LL1 的元素大于 LL2 的第一个元素,那么我们交换所涉及的两个元素。为了保持 LL2 排序,我们需要将 LL2 的第一个元素放在正确的位置。我们可以通过遍历 LL2 一次并纠正指针来发现不匹配。
下面是这个想法的实现。
C++
// C++ Program to merge two sorted linked lists without
// using any extra space and without changing links
// of first list
#include
using namespace std;
/* Structure for a linked list node */
struct Node
{
int data;
struct Node *next;
};
/* Given a reference (pointer to pointer) to the head
of a list and an int, push a new node on the front
of the list. */
void push(struct Node** head_ref, int new_data)
{
/* allocate node */
struct Node* new_node =
(struct Node*) malloc(sizeof(struct Node));
/* put in the data */
new_node->data = new_data;
/* link the old list off the new node */
new_node->next = (*head_ref);
/* move the head to point to the new node */
(*head_ref) = new_node;
}
// Function to merge two sorted linked lists
// LL1 and LL2 without using any extra space.
void mergeLists(struct Node *a, struct Node * &b)
{
// run till either one of a or b runs out
while (a && b)
{
// for each element of LL1,
// compare it with first element of LL2.
if (a->data > b->data)
{
// swap the two elements involved
// if LL1 has a greater element
swap(a->data, b->data);
struct Node *temp = b;
// To keep LL2 sorted, place first
// element of LL2 at its correct place
if (b->next && b->data > b->next->data)
{
b = b->next;
struct Node *ptr= b, *prev = NULL;
// find mismatch by traversing the
// second linked list once
while (ptr && ptr->data < temp->data)
{
prev = ptr;
ptr = ptr -> next;
}
// correct the pointers
prev->next = temp;
temp->next = ptr;
}
}
// move LL1 pointer to next element
a = a->next;
}
}
// Code to print the linked link
void printList(struct Node *head)
{
while (head)
{
cout << head->data << "->" ;
head = head->next;
}
cout << "NULL" << endl;
}
// Driver code
int main()
{
struct Node *a = NULL;
push(&a, 10);
push(&a, 8);
push(&a, 7);
push(&a, 4);
push(&a, 2);
struct Node *b = NULL;
push(&b, 12);
push(&b, 3);
push(&b, 1);
mergeLists(a, b);
cout << "First List: ";
printList(a);
cout << "Second List: ";
printList(b);
return 0;
}
Python3
# Python3 program to merge two sorted linked
# lists without using any extra space and
# without changing links of first list
# Structure for a linked list node
class Node:
def __init__(self):
self.data = 0
self.next = None
# Given a reference (pointer to pointer) to
# the head of a list and an int, push a new
# node on the front of the list.
def push(head_ref, new_data):
# Allocate node
new_node = Node()
# Put in the data
new_node.data = new_data
# Link the old list off the new node
new_node.next = (head_ref)
# Move the head to point to the new node
(head_ref) = new_node
return head_ref
# Function to merge two sorted linked lists
# LL1 and LL2 without using any extra space.
def mergeLists(a, b):
# Run till either one of a
# or b runs out
while (a and b):
# For each element of LL1, compare
# it with first element of LL2.
if (a.data > b.data):
# Swap the two elements involved
# if LL1 has a greater element
a.data, b.data = b.data, a.data
temp = b
# To keep LL2 sorted, place first
# element of LL2 at its correct place
if (b.next and b.data > b.next.data):
b = b.next
ptr = b
prev = None
# Find mismatch by traversing the
# second linked list once
while (ptr and ptr.data < temp.data):
prev = ptr
ptr = ptr.next
# Correct the pointers
prev.next = temp
temp.next = ptr
# Move LL1 pointer to next element
a = a.next
# Function to print the linked link
def printList(head):
while (head):
print(head.data, end = '->')
head = head.next
print('NULL')
# Driver code
if __name__=='__main__':
a = None
a = push(a, 10)
a = push(a, 8)
a = push(a, 7)
a = push(a, 4)
a = push(a, 2)
b = None
b = push(b, 12)
b = push(b, 3)
b = push(b, 1)
mergeLists(a, b)
print("First List: ", end = '')
printList(a)
print("Second List: ", end = '')
printList(b)
# This code is contributed by rutvik_56
输出 :
First List: 1->2->3->4->7->NULL
Second List: 8->10->12->NULL
时间复杂度: O(mn)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。