📜  从具有一些公共节点的两个排序链表中构建最大和链表

📅  最后修改于: 2022-05-13 01:57:44.100000             🧑  作者: Mango

从具有一些公共节点的两个排序链表中构建最大和链表

给定两个已排序的链表,构造一个包含从开始到结束的最大和路径的链表。结果列表可能包含来自两个输入列表的节点。在构造结果列表时,我们可能只在交点处切换到另一个输入列表(这意味着列表中具有相同值的两个节点)。您可以使用 O(1) 额外空间。

Input:
List1 =  1->3->30->90->120->240->511
List2 =  0->3->12->32->90->125->240->249

Output: Following is maximum sum linked list out of two input lists
list =  1->3->12->32->90->125->240->511
we switch at 3 and 240 to get above maximum sum linked list

我们强烈建议您将浏览器最小化,然后自己先尝试一下。

以下解决方案中的想法是在公共节点之后调整下一个指针。
1. 从两个链表的头开始,找到第一个公共节点。为此使用排序链表的合并技术。
2. 这样做时也要跟踪元素的总和,并根据更大的总和设置结果列表的头部,直到第一个公共节点。
3. 在此之后,直到两个列表的当前指针都没有变为 NULL,我们需要根据更大的总和来调整下一个 prev 指针。

通过这种方式,它可以以恒定的额外空间就地完成。
以下解决方案的时间复杂度为 O(n)。

C++
// C++ program to construct the maximum sum linked
// list out of two given sorted lists
#include
using namespace std;
  
//A linked list node
struct Node
{
    int data; //data belong to that node
    Node *next; //next pointer
};
  
// Push the data to the head of the linked list
void push(Node **head, int data)
{
    //Allocation memory to the new node
    Node *newnode = new Node;
  
    //Assigning data to the new node
    newnode->data = data;
  
    //Adjusting next pointer of the new node
    newnode->next = *head;
  
    //New node becomes the head of the list
    *head = newnode;
}
  
// Method that adjusts the pointers and prints the final list
void finalMaxSumList(Node *a, Node *b)
{
    Node *result = NULL;
  
    // Assigning pre and cur to the head of the
    // linked list.
    Node *pre1 = a, *curr1 = a;
    Node *pre2 = b, *curr2 = b;
  
    // Till either of the current pointers is not
    // NULL execute the loop
    while (curr1 != NULL || curr2 != NULL)
    {
        // Keeping 2 local variables at the start of every
        // loop run to keep track of the sum between pre
        // and cur pointer elements.
        int sum1 = 0, sum2 = 0;
  
        // Calculating sum by traversing the nodes of linked
        // list as the merging of two linked list.  The loop
        // stops at a common node
        while (curr1!=NULL && curr2!=NULL && curr1->data!=curr2->data)
        {
            if (curr1->data < curr2->data)
            {
                sum1 += curr1->data;
                curr1 = curr1->next;
            }
            else // (curr2->data < curr1->data)
            {
                sum2 += curr2->data;
                curr2 = curr2->next;
            }
        }
  
        // If either of current pointers becomes NULL
        // carry on the sum calculation for other one.
        if (curr1 == NULL)
        {
            while (curr2 != NULL)
            {
                sum2 += curr2->data;
                curr2 = curr2->next;
            }
        }
        if (curr2 == NULL)
        {
            while (curr1 != NULL)
            {
                sum1 += curr1->data;
                curr1 = curr1->next;
            }
        }
  
        // First time adjustment of resultant head based on
        // the maximum sum.
        if (pre1 == a && pre2 == b)
            result = (sum1 > sum2)? pre1 : pre2;
  
        // If pre1 and pre2 don't contain the head pointers of
        // lists adjust the next pointers of previous pointers.
        else
        {
            if (sum1 > sum2)
                pre2->next = pre1->next;
            else
                pre1->next = pre2->next;
        }
  
        // Adjusting previous pointers
        pre1 = curr1, pre2 = curr2;
  
        // If curr1 is not NULL move to the next.
        if (curr1)
            curr1 = curr1->next;
        // If curr2 is not NULL move to the next.
        if (curr2)
            curr2 = curr2->next;
    }
  
    // Print the resultant list.
    while (result != NULL)
    {
        cout << result->data << " ";
        result = result->next;
    }
}
  
//Main driver program
int main()
{
    //Linked List 1 : 1->3->30->90->110->120->NULL
    //Linked List 2 : 0->3->12->32->90->100->120->130->NULL
    Node *head1 = NULL, *head2 = NULL;
    push(&head1, 120);
    push(&head1, 110);
    push(&head1, 90);
    push(&head1, 30);
    push(&head1, 3);
    push(&head1, 1);
  
    push(&head2, 130);
    push(&head2, 120);
    push(&head2, 100);
    push(&head2, 90);
    push(&head2, 32);
    push(&head2, 12);
    push(&head2, 3);
    push(&head2, 0);
  
    finalMaxSumList(head1, head2);
    return 0;
}


Java
// Java program to construct a Maximum Sum Linked List out of
// two Sorted Linked Lists having some Common nodes
class LinkedList
{
    Node head;  // head of list
  
    /* Linked list Node*/
    class Node
    {
        int data;
        Node next;
        Node(int d)
        {
            data = d;
            next = null;
        }
    }
  
    // Method to adjust pointers and print final list
    void finalMaxSumList(Node a, Node b)
    {
        Node result = null;
  
        /* assigning pre and cur to head
           of the linked list */
        Node pre1 = a, curr1 = a;
        Node pre2 = b, curr2 = b;
  
        /* Till either of current pointers is not null
           execute the loop */
        while (curr1 != null || curr2 != null)
        {
            // Keeping 2 local variables at the start of every
            // loop run to keep track of the sum between pre
            // and cur reference elements.
            int sum1 = 0, sum2 = 0;
  
            // Calculating sum by traversing the nodes of linked
            // list as the merging of two linked list.  The loop
            // stops at a common node
            while (curr1 != null && curr2 != null &&
                   curr1.data != curr2.data)
            {
  
                if (curr1.data sum2) ? pre1 : pre2;
  
            // If pre1 and pre2 don't contain the head references of
            // lists adjust the next pointers of previous pointers.
            else
            {
                if (sum1 > sum2)
                    pre2.next = pre1.next;
                else
                    pre1.next = pre2.next;
            }
  
            // Adjusting previous pointers
            pre1 = curr1;
            pre2 = curr2;
  
            // If curr1 is not NULL move to the next.
            if (curr1 != null)
                curr1 = curr1.next;
  
            // If curr2 is not NULL move to the next.
            if (curr2 != null)
                curr2 = curr2.next;
        }
  
        while (result != null)
        {
            System.out.print(result.data + " ");
            result = result.next;
        }
        System.out.println();
    }
  
    /*  Inserts a node at start of linked list */
    void push(int new_data)
    {
        /* 1 & 2: Allocate the Node &
                  Put in the data*/
        Node new_node = new Node(new_data);
  
        /* 3. Make next of new Node as head */
        new_node.next = head;
  
        /* 4. Move the head to point to new Node */
        head = new_node;
    }
  
  
    /* Driver program to test above functions */
    public static void main(String args[])
    {
        LinkedList llist1 = new LinkedList();
        LinkedList llist2 = new LinkedList();
  
        //Linked List 1 : 1->3->30->90->110->120->NULL
        //Linked List 2 : 0->3->12->32->90->100->120->130->NULL
  
        llist1.push(120);
        llist1.push(110);
        llist1.push(90);
        llist1.push(30);
        llist1.push(3);
        llist1.push(1);
  
        llist2.push(130);
        llist2.push(120);
        llist2.push(100);
        llist2.push(90);
        llist2.push(32);
        llist2.push(12);
        llist2.push(3);
        llist2.push(0);
  
        llist1.finalMaxSumList(llist1.head, llist2.head);
    }
} /* This code is contributed by Rajat Mishra */


Python
# Python program to construct a Maximum Sum Linked List out of
# two Sorted Linked Lists having some Common nodes
class LinkedList(object):
    def __init__(self):
     # head of list
         self.head = None
  
    # Linked list Node
    class Node(object):
        def __init__(self, d):
            self.data = d
            self.next = None
  
    # Method to adjust pointers and print final list
    def finalMaxSumList(self, a, b):
        result = None
        # assigning pre and cur to head
        # of the linked list
        pre1 = a
        curr1 = a
        pre2 = b
        curr2 = b
        # Till either of current pointers is not null
        # execute the loop
        while curr1 != None or curr2 != None:
            # Keeping 2 local variables at the start of every
            # loop run to keep track of the sum between pre
            # and cur reference elements.
            sum1 = 0
            sum2 = 0
            # Calculating sum by traversing the nodes of linked
            # list as the merging of two linked list.  The loop
            # stops at a common node
            while curr1 != None and curr2 != None and curr1.data != curr2.data:
                if curr1.data < curr2.data:
                    sum1 += curr1.data
                    curr1 = curr1.next
                else:
                    sum2 += curr2.data
                    curr2 = curr2.next
            # If either of current pointers becomes null
            # carry on the sum calculation for other one.
            if curr1 == None:
                while curr2 != None:
                    sum2 += curr2.data
                    curr2 = curr2.next
            if curr2 == None:
                while curr1 != None:
                    sum1 += curr1.data
                    curr1 = curr1.next
            # First time adjustment of resultant head based on
            # the maximum sum.
            if pre1 == a and pre2 == b:
                result = pre1 if (sum1 > sum2) else pre2
            else:
                # If pre1 and pre2 don't contain the head references of
                # lists adjust the next pointers of previous pointers.
                if sum1 > sum2:
                    pre2.next = pre1.next
                else:
                    pre1.next = pre2.next
            # Adjusting previous pointers
            pre1 = curr1
            pre2 = curr2
            # If curr1 is not NULL move to the next.
            if curr1 != None:
                curr1 = curr1.next
            # If curr2 is not NULL move to the next.
            if curr2 != None:
                curr2 = curr2.next
  
        while result != None:
            print str(result.data),
            result = result.next
        print ''
  
    # Utility functions
    # Inserts a new Node at front of the list.
    def push(self, new_data):
        # 1 & 2: Allocate the Node &
        # Put in the data
        new_node = self.Node(new_data)
        # 3. Make next of new Node as head
        new_node.next = self.head
        # 4. Move the head to point to new Node
        self.head = new_node
  
# Driver program
llist1 = LinkedList()
llist2 = LinkedList()
  
# Linked List 1 : 1->3->30->90->110->120->NULL
# Linked List 2 : 0->3->12->32->90->100->120->130->NULL
  
llist1.push(120)
llist1.push(110)
llist1.push(90)
llist1.push(30)
llist1.push(3)
llist1.push(1)
  
llist2.push(130)
llist2.push(120)
llist2.push(100)
llist2.push(90)
llist2.push(32)
llist2.push(12)
llist2.push(3)
llist2.push(0)
  
llist1.finalMaxSumList(llist1.head, llist2.head)
  
# This code is contributed by BHAVYA JAIN


C#
// C# program to construct a Maximum
// Sum Linked List out of two Sorted 
// Linked Lists having some Common nodes 
using System;
  
public class LinkedList 
{ 
    Node head; // head of list 
  
    /* Linked list Node*/
    public class Node 
    { 
        public int data; 
        public Node next; 
        public Node(int d) 
        { 
            data = d; 
            next = null; 
        } 
    } 
  
    // Method to adjust pointers
    // and print final list 
    void finalMaxSumList(Node a, Node b) 
    { 
        Node result = null; 
  
        /* assigning pre and cur to head 
        of the linked list */
        Node pre1 = a, curr1 = a; 
        Node pre2 = b, curr2 = b; 
  
        /* Till either of current pointers 
        is not null execute the loop */
        while (curr1 != null || curr2 != null) 
        { 
            // Keeping 2 local variables at the start
            //  of every loop run to keep track of the 
            // sum between pre and cur reference elements. 
            int sum1 = 0, sum2 = 0; 
  
            // Calculating sum by traversing the nodes of linked 
            // list as the merging of two linked list. The loop 
            // stops at a common node 
            while (curr1 != null && curr2 != null && 
                curr1.data != curr2.data) 
            { 
  
                if (curr1.data sum2) ? pre1 : pre2; 
  
            // If pre1 and pre2 don't contain 
            // the head references of lists adjust
            // the next pointers of previous pointers. 
            else
            { 
                if (sum1 > sum2) 
                    pre2.next = pre1.next; 
                else
                    pre1.next = pre2.next; 
            } 
  
            // Adjusting previous pointers 
            pre1 = curr1; 
            pre2 = curr2; 
  
            // If curr1 is not NULL move to the next. 
            if (curr1 != null) 
                curr1 = curr1.next; 
  
            // If curr2 is not NULL move to the next. 
            if (curr2 != null) 
                curr2 = curr2.next; 
        } 
  
        while (result != null) 
        { 
            Console.Write(result.data + " "); 
            result = result.next; 
        } 
        Console.WriteLine(); 
    } 
  
    /* Inserts a node at start of linked list */
    void push(int new_data) 
    { 
        /* 1 & 2: Allocate the Node & 
                Put in the data*/
        Node new_node = new Node(new_data); 
  
        /* 3. Make next of new Node as head */
        new_node.next = head; 
  
        /* 4. Move the head to point to new Node */
        head = new_node; 
    } 
  
  
    /* Driver code */
    public static void Main() 
    { 
        LinkedList llist1 = new LinkedList(); 
        LinkedList llist2 = new LinkedList(); 
  
        //Linked List 1 : 1->3->30->90->110->120->NULL 
        //Linked List 2 : 0->3->12->32->90->100->120->130->NULL 
  
        llist1.push(120); 
        llist1.push(110); 
        llist1.push(90); 
        llist1.push(30); 
        llist1.push(3); 
        llist1.push(1); 
  
        llist2.push(130); 
        llist2.push(120); 
        llist2.push(100); 
        llist2.push(90); 
        llist2.push(32); 
        llist2.push(12); 
        llist2.push(3); 
        llist2.push(0); 
  
        llist1.finalMaxSumList(llist1.head, llist2.head); 
    } 
} 
  
/* This code contributed by PrinciRaj1992 */



输出:

1 3 12 32 90 110 120 130

时间复杂度: O(n) 其中 n 是更大链表的长度
辅助空间: O(1)
但是,此解决方案中的一个问题是更改了原始列表。

锻炼
1. 当辅助空间不是约束时试试这个问题。
2.当我们不修改实际列表并创建结果列表时尝试这个问题。

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程