📌  相关文章
📜  从三个链表中找到一个总和等于给定数字的三元组

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

从三个链表中找到一个总和等于给定数字的三元组

给定三个链表,比如 a、b 和 c,从每个链表中找到一个节点,使得节点的值之和等于给定的数字。
例如,如果三个链表分别为 12->6->29、23->5->8 和 90->20->59,并且给定的数为 101,则输出应为三元组“6 5 90 ”。
在以下解决方案中,为了分析简单,假设所有三个链表的大小相同。以下解决方案也适用于不同大小的链表。

解决这个问题的一个简单方法是运行三个嵌套循环。最外层循环从列表 a 中选取一个元素,中间循环从 b 中选取一个元素,最内层循环从 c 中选取一个元素。最内层循环还检查 a、b 和 c 的当前节点的值之和是否等于给定数字。该方法的时间复杂度为 O(n^3)。
排序可用于将时间复杂度降低到 O(n*n)。以下是详细步骤。
1) 按升序对列表 b 进行排序,并按降序对列表 c 进行排序。
2) b 和 c 排序后,从列表 a 中一一选取一个元素,遍历 b 和 c 找到一对。请参阅以下代码中的 isSumSorted()。这个想法类似于3和问题的二次算法。

以下代码仅实现第 2 步。通过添加此处讨论的合并排序代码,可以轻松修改未排序列表的解决方案。

C++
// C++ program to find a triplet
// from three linked lists with
// sum equal to a given number
#include 
using namespace std;
 
/* Link list node */
class Node
{
    public:
    int data;
    Node* next;
};
 
/* A utility function to insert
a node at the beginning of a
linked list*/
void push (Node** head_ref, int new_data)
{
    /* allocate node */
    Node* new_node = new 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;
}
 
/* A function to check if there are three elements in a, b
and c whose sum is equal to givenNumber. The function
assumes that the list b is sorted in ascending order
and c is sorted in descending order. */
bool isSumSorted(Node *headA, Node *headB,
                Node *headC, int givenNumber)
{
    Node *a = headA;
 
    // Traverse through all nodes of a
    while (a != NULL)
    {
        Node *b = headB;
        Node *c = headC;
 
        // For every node of list a, prick two nodes
        // from lists b abd c
        while (b != NULL && c != NULL)
        {
            // If this a triplet with given sum, print
            // it and return true
            int sum = a->data + b->data + c->data;
            if (sum == givenNumber)
            {
            cout << "Triplet Found: " << a->data << " " <<
                                b->data << " " << c->data;
            return true;
            }
 
            // If sum of this triplet is smaller, look for
            // greater values in b
            else if (sum < givenNumber)
                b = b->next;
            else // If sum is greater, look for smaller values in c
                c = c->next;
        }
        a = a->next; // Move ahead in list a
    }
 
    cout << "No such triplet";
    return false;
}
 
 
/* Driver code*/
int main()
{
    /* Start with the empty list */
    Node* headA = NULL;
    Node* headB = NULL;
    Node* headC = NULL;
 
    /*create a linked list 'a' 10->15->5->20 */
    push (&headA, 20);
    push (&headA, 4);
    push (&headA, 15);
    push (&headA, 10);
 
    /*create a sorted linked list 'b' 2->4->9->10 */
    push (&headB, 10);
    push (&headB, 9);
    push (&headB, 4);
    push (&headB, 2);
 
    /*create another sorted
    linked list 'c' 8->4->2->1 */
    push (&headC, 1);
    push (&headC, 2);
    push (&headC, 4);
    push (&headC, 8);
 
    int givenNumber = 25;
 
    isSumSorted (headA, headB, headC, givenNumber);
 
    return 0;
}
 
// This code is contributed by rathbhupendra


C
// C program to find a triplet from three linked lists with
// sum equal to a given number
#include
#include
#include
 
/* Link list node */
struct Node
{
    int data;
    struct Node* next;
};
 
/* A utility function to insert a node at the beginning of a
   linked 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;
}
 
/* A function to check if there are three elements in a, b
   and c whose sum is equal to givenNumber.  The function
   assumes that the list b is sorted in ascending order
   and c is sorted in descending order. */
bool isSumSorted(struct Node *headA, struct Node *headB,
                 struct Node *headC, int givenNumber)
{
    struct Node *a = headA;
 
    // Traverse through all nodes of a
    while (a != NULL)
    {
        struct Node *b = headB;
        struct Node *c = headC;
 
        // For every node of list a, prick two nodes
        // from lists b abd c
        while (b != NULL && c != NULL)
        {
            // If this a triplet with given sum, print
            // it and return true
            int sum = a->data + b->data + c->data;
            if (sum == givenNumber)
            {
               printf ("Triplet Found: %d %d %d ", a->data,
                                         b->data, c->data);
               return true;
            }
 
            // If sum of this triplet is smaller, look for
            // greater values in b
            else if (sum < givenNumber)
                b = b->next;
            else // If sum is greater, look for smaller values in c
                c = c->next;
        }
        a = a->next;  // Move ahead in list a
    }
 
    printf ("No such triplet");
    return false;
}
 
 
/* Driver program to test above function*/
int main()
{
    /* Start with the empty list */
    struct Node* headA = NULL;
    struct Node* headB = NULL;
    struct Node* headC = NULL;
 
    /*create a linked list 'a' 10->15->5->20 */
    push (&headA, 20);
    push (&headA, 4);
    push (&headA, 15);
    push (&headA, 10);
 
    /*create a sorted linked list 'b' 2->4->9->10 */
    push (&headB, 10);
    push (&headB, 9);
    push (&headB, 4);
    push (&headB, 2);
 
    /*create another sorted linked list 'c' 8->4->2->1 */
    push (&headC, 1);
    push (&headC, 2);
    push (&headC, 4);
    push (&headC, 8);
 
    int givenNumber = 25;
 
    isSumSorted (headA, headB, headC, givenNumber);
 
    return 0;
}


Java
// Java program to find a triplet from three linked lists with
// sum equal to a given number
class LinkedList
{
    Node head;  // head of list
 
    /* Linked list Node*/
    class Node
    {
        int data;
        Node next;
        Node(int d) {data = d; next = null; }
    }
 
    /* A function to check if there are three elements in a, b
      and c whose sum is equal to givenNumber.  The function
      assumes that the list b is sorted in ascending order and
      c is sorted in descending order. */
   boolean isSumSorted(LinkedList la, LinkedList lb, LinkedList lc,
                       int givenNumber)
   {
      Node a = la.head;
 
      // Traverse all nodes of la
      while (a != null)
      {
          Node b = lb.head;
          Node c = lc.head;
 
          // for every node in la pick 2 nodes from lb and lc
          while (b != null && c!=null)
          {
              int sum = a.data + b.data + c.data;
              if (sum == givenNumber)
              {
                 System.out.println("Triplet found " + a.data +
                                     " " + b.data + " " + c.data);
                 return true;
              }
 
              // If sum is smaller then look for greater value of b
              else if (sum < givenNumber)
                b = b.next;
 
              else
                c = c.next;
          }
          a = a.next;
      }
      System.out.println("No Triplet found");
      return false;
   }
 
 
    /*  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(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();
        LinkedList llist3 = new LinkedList();
 
        /* Create Linked List llist1 100->15->5->20 */
        llist1.push(20);
        llist1.push(5);
        llist1.push(15);
        llist1.push(100);
 
        /*create a sorted linked list 'b' 2->4->9->10 */
        llist2.push(10);
        llist2.push(9);
        llist2.push(4);
        llist2.push(2);
 
        /*create another sorted linked list 'c' 8->4->2->1 */
        llist3.push(1);
        llist3.push(2);
        llist3.push(4);
        llist3.push(8);
 
        int givenNumber = 25;
        llist1.isSumSorted(llist1,llist2,llist3,givenNumber);
    }
} /* This code is contributed by Rajat Mishra */


Python
# Python program to find a triplet
# from three linked lists with
# sum equal to a given number
 
# Link list node
class Node:
    def __init__(self, new_data):
        self.data = new_data
        self.next = None
 
# A utility function to insert
# a node at the beginning of a
# linked list
def push ( head_ref, new_data) :
 
    # allocate node
    new_node = Node(0)
 
    # 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;
 
# A function to check if there are three elements in a, b
# and c whose sum is equal to givenNumber. The function
# assumes that the list b is sorted in ascending order
# and c is sorted in descending order.
def isSumSorted(headA, headB,headC, givenNumber) :
 
    a = headA
 
    # Traverse through all nodes of a
    while (a != None) :
     
        b = headB
        c = headC
 
        # For every node of list a, prick two nodes
        # from lists b abd c
        while (b != None and c != None) :
         
            # If this a triplet with given sum, print
            # it and return true
            sum = a.data + b.data + c.data
            if (sum == givenNumber) :
             
                print "Triplet Found: " , a.data , " " , b.data , " " , c.data,
                return True
             
            # If sum of this triplet is smaller, look for
            # greater values in b
            elif (sum < givenNumber):
                b = b.next
            else :# If sum is greater, look for smaller values in c
                c = c.next
         
        a = a.next # Move ahead in list a
     
    print("No such triplet")
    return False
 
# Driver code
 
# Start with the empty list
headA = None
headB = None
headC = None
 
# create a linked list 'a' 10.15.5.20
headA = push (headA, 20)
headA = push (headA, 4)
headA = push (headA, 15)
headA = push (headA, 10)
 
# create a sorted linked list 'b' 2.4.9.10
headB = push (headB, 10)
headB = push (headB, 9)
headB = push (headB, 4)
headB = push (headB, 2)
 
# create another sorted
# linked list 'c' 8.4.2.1
headC = push (headC, 1)
headC = push (headC, 2)
headC = push (headC, 4)
headC = push (headC, 8)
 
givenNumber = 25
 
isSumSorted (headA, headB, headC, givenNumber)
 
# This code is contributed by Arnab Kundu


C#
// C# program to find a triplet
// from three linked lists with
// sum equal to a given number
using System;
 
public class LinkedList
{
    public 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;
        }
    }
 
    /* A function to check if there
    are three elements in a, b
    and c whose sum is equal to
    givenNumber. The function
    assumes that the list b is
    sorted in ascending order and
    c is sorted in descending order. */
bool isSumSorted(LinkedList la, LinkedList lb,
                LinkedList lc, int givenNumber)
{
    Node a = la.head;
 
    // Traverse all nodes of la
    while (a != null)
    {
        Node b = lb.head;
        Node c = lc.head;
 
        // for every node in la pick
        // 2 nodes from lb and lc
        while (b != null && c!=null)
        {
            int sum = a.data + b.data + c.data;
            if (sum == givenNumber)
            {
                Console.WriteLine("Triplet found " + a.data +
                                    " " + b.data + " " + c.data);
                return true;
            }
 
            // If sum is smaller then
            // look for greater value of b
            else if (sum < givenNumber)
                b = b.next;
 
            else
                c = c.next;
        }
        a = a.next;
    }
    Console.WriteLine("No Triplet found");
    return false;
}
 
 
    /* 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(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(String []args)
    {
        LinkedList llist1 = new LinkedList();
        LinkedList llist2 = new LinkedList();
        LinkedList llist3 = new LinkedList();
 
        /* Create Linked List llist1 100->15->5->20 */
        llist1.push(20);
        llist1.push(5);
        llist1.push(15);
        llist1.push(100);
 
        /*create a sorted linked list 'b' 2->4->9->10 */
        llist2.push(10);
        llist2.push(9);
        llist2.push(4);
        llist2.push(2);
 
        /*create another sorted linked list 'c' 8->4->2->1 */
        llist3.push(1);
        llist3.push(2);
        llist3.push(4);
        llist3.push(8);
 
        int givenNumber = 25;
        llist1.isSumSorted(llist1,llist2,llist3,givenNumber);
    }
}
 
// This code contributed by Rajput-Ji


Javascript


输出:

Triplet Found: 15 2 8

时间复杂度:链表 b 和 c 可以使用 Merge Sort 在 O(nLogn) 时间内排序(参见这里)。第 2 步需要 O(n*n) 时间。所以总的时间复杂度是 O(nlogn) + O(nlogn) + O(n*n) = O(n*n)。
在这种方法中,链表 b 和 c 首先排序,因此它们的原始顺序将丢失。如果我们想保留 b 和 c 的原始顺序,我们可以创建 b 和 c 的副本。



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