📜  在已排序的双链表 (DLL) 中查找最接近 X 的三元组和

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

在已排序的双链表 (DLL) 中查找最接近 X 的三元组和

给定一个由N个节点和一个整数X组成的有序双向链表,任务是找到列表中最接近X的三个节点的总和。

例子:

朴素方法:解决给定问题的最简单方法是使用三个嵌套循环生成所有可能的三元组,然后选择总和最接近X的三元组并打印三元组的总和。

时间复杂度: O(N 3 )
辅助空间: O(1)

高效方法:为了优化上述方法,想法是使用 3 指针技术。请按照以下步骤解决此问题:

  • 初始化4个变量, firstsecond指向双向链表的头节点,即first=headsecond = headtailthird都初始化为双向链表的最后一个节点。
  • 初始化一个变量diff ,初始化为INT_MAX ,它存储最接近X的总和。
  • 在第一个节点不为NULL时进行迭代并执行以下步骤:
    • 初始化firstsecond到 next ,即second = first→nextthird = tail (双向链表的最后一个节点)。
    • 迭代,而第二个第三个不为NULL并且第三个不等于 第二个
      • 初始化一个变量,比如sum(first→data + second→data + third→data)
      • 如果X – sum的绝对值小于X diff的绝对值,则将diff的值更新为sum。
      • 如果sum小于X ,则增加第二个指针,即second = second→next
      • 否则,递减third ,即third =third→prev。
    • 将第一个指针移动到下一个指针,即first = first→next
  • 完成上述步骤后,打印diff的值作为结果。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Doubly linked list node
struct Node {
    int data;
    struct Node *next, *prev;
};
 
// Function to insert a new node at
// the beginning of doubly linked
// list
void insert(struct Node** head, int data)
{
    // Allocate node
    struct Node* temp = new Node();
 
    // Fill the data value in it
    temp->data = data;
    temp->next = temp->prev = NULL;
 
    // If head is NULL change
    // head to temp
    if ((*head) == NULL) {
        (*head) = temp;
    }
 
    // Insert the node before head
    else {
        temp->next = *head;
        (*head)->prev = temp;
        (*head) = temp;
    }
}
 
// Function to find sum of triplet
// closest to X
void closestTripletSum(struct Node* head, int X)
{
    // Points to the first node
    // of the triplet
    struct Node* first = head;
 
    // Points to the second node
    // of the triplet
    struct Node* second = head->next;
 
    // Stores the last node of
    // doubly linked list
    struct Node* tail = head;
 
    // Traverse till end of the list
    while (tail->next != NULL) {
        tail = tail->next;
    }
 
    // Stores the sum closest to X
    int diff = INT_MAX;
 
    // Points to the third node
    // of the triplet
    struct Node* third = tail;
 
    // Iterate till the end of the list
    while (first != NULL) {
        second = first->next;
        third = tail;
 
        while (second != NULL && third != NULL
               && third != second) {
            int sum = (first->data + second->data
                       + third->data);
 
            // Check if the current sum
            // is closest to X
            if (abs(X - sum) < abs(X - diff)) {
 
                // Update the value of diff
                diff = sum;
            }
 
            // Check if sum is less than X
            if (sum < X) {
 
                // Increment the second
                // pointer
                second = second->next;
            }
            else {
 
                // Decrement the third
                // pointer
                third = third->prev;
            }
        }
 
        // Move the first pointer
        // ahead
        first = first->next;
    }
 
    // Print the closest sum
    cout << diff;
}
 
// Driver Code
int main()
{
    // Given Input
    struct Node* head = NULL;
    insert(&head, 4);
    insert(&head, 3);
    insert(&head, 2);
    insert(&head, 1);
    int X = 3;
 
    // Function Call
    closestTripletSum(head, X);
 
    return 0;
}


Java
// Java program for the above approach
class GFG {
 
    // Doubly linked list node
    static class Node {
        int data;
        Node next, prev;
    };
    static Node head;
   
    // Function to insert a new node at
    // the beginning of doubly linked
    // list
    static void insert(int data)
    {
       
        // Allocate node
        Node temp = new Node();
 
        // Fill the data value in it
        temp.data = data;
        temp.next = temp.prev = null;
 
        // If head is null change
        // head to temp
        if ((head) == null) {
            (head) = temp;
        }
 
        // Insert the node before head
        else {
            temp.next = head;
            (head).prev = temp;
            (head) = temp;
        }
    }
 
    // Function to find sum of triplet
    // closest to X
    static void closestTripletSum(int X)
    {
        // Points to the first node
        // of the triplet
        Node first = head;
 
        // Points to the second node
        // of the triplet
        Node second = head.next;
 
        // Stores the last node of
        // doubly linked list
        Node tail = head;
 
        // Traverse till end of the list
        while (tail.next != null) {
            tail = tail.next;
        }
 
        // Stores the sum closest to X
        int diff = Integer.MAX_VALUE;
 
        // Points to the third node
        // of the triplet
        Node third = tail;
 
        // Iterate till the end of the list
        while (first != null) {
            second = first.next;
            third = tail;
 
            while (second != null && third != null
                   && third != second) {
                int sum = (first.data + second.data
                           + third.data);
 
                // Check if the current sum
                // is closest to X
                if (Math.abs(X - sum)
                    < Math.abs(X - diff)) {
 
                    // Update the value of diff
                    diff = sum;
                }
 
                // Check if sum is less than X
                if (sum < X) {
 
                    // Increment the second
                    // pointer
                    second = second.next;
                }
                else {
 
                    // Decrement the third
                    // pointer
                    third = third.prev;
                }
            }
 
            // Move the first pointer
            // ahead
            first = first.next;
        }
 
        // Print the closest sum
        System.out.print(diff);
    }
 
    // Driver Code
    public static void main(String[] args)
    {
       
        // Given Input
        head = null;
        insert(4);
        insert(3);
        insert(2);
        insert(1);
        int X = 3;
 
        // Function Call
        closestTripletSum(X);
    }
}
 
// This code is contributed by umadevi9616


Python3
# Python program for the above approach
import sys
 
# Doubly linked list Node
class Node:
    def __init__(self):
        self.data = 0;
        self.next = None;
        self.prev = None;
 
head = None;
 
# Function to insert a new Node at
# the beginning of doubly linked
# list
def insert(data):
 
    # Allocate Node
    temp = Node();
 
    # Fill the data value in it
    temp.data = data;
    temp.next = temp.prev = None;
 
    # If head is None change
    # head to temp
    global head;
    if ((head) == None):
        (head) = temp;
     
    # Insert the Node before head
    else:
        temp.next = head;
        (head).prev = temp;
        (head) = temp;
     
# Function to find sum of triplet
# closest to X
def closestTripletSum(X):
   
    # Points to the first Node
    # of the triplet
    first = head;
 
    # Points to the second Node
    # of the triplet
    second = head.next;
 
    # Stores the last Node of
    # doubly linked list
    tail = head;
 
    # Traverse till end of the list
    while (tail.next != None):
        tail = tail.next;
     
 
    # Stores the sum closest to X
    diff = sys.maxsize;
 
    # Points to the third Node
    # of the triplet
    third = tail;
 
    # Iterate till the end of the list
    while (first != None):
        second = first.next;
        third = tail;
 
        while (second != None and third != None and third != second):
            sum = (first.data + second.data + third.data);
 
            # Check if the current sum
            # is closest to X
            if (abs(X - sum) < abs(X - diff)):
 
                # Update the value of diff
                diff = sum;
             
 
            # Check if sum is less than X
            if (sum < X):
 
                # Increment the second
                # pointer
                second = second.next;
            else:
 
                # Decrement the third
                # pointer
                third = third.prev;
             
        # Move the first pointer
        # ahead
        first = first.next;
     
    # Print the closest sum
    print(diff);
 
# Driver Code
if __name__ == '__main__':
 
    # Given Input
    head = None;
    insert(4);
    insert(3);
    insert(2);
    insert(1);
    X = 3;
 
    # Function Call
    closestTripletSum(X);
 
# This code is contributed by umadevi9616


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
public class GFG {
 
    // Doubly linked list node
public    class Node {
    public    int data;
    public    Node next, prev;
    };
 
    static Node head;
 
    // Function to insert a new node at
    // the beginning of doubly linked
    // list
    static void insert(int data) {
 
        // Allocate node
        Node temp = new Node();
 
        // Fill the data value in it
        temp.data = data;
        temp.next = temp.prev = null;
 
        // If head is null change
        // head to temp
        if ((head) == null) {
            (head) = temp;
        }
 
        // Insert the node before head
        else {
            temp.next = head;
            (head).prev = temp;
            (head) = temp;
        }
    }
 
    // Function to find sum of triplet
    // closest to X
    static void closestTripletSum(int X) {
        // Points to the first node
        // of the triplet
        Node first = head;
 
        // Points to the second node
        // of the triplet
        Node second = head.next;
 
        // Stores the last node of
        // doubly linked list
        Node tail = head;
 
        // Traverse till end of the list
        while (tail.next != null) {
            tail = tail.next;
        }
 
        // Stores the sum closest to X
        int diff = int.MaxValue;
 
        // Points to the third node
        // of the triplet
        Node third = tail;
 
        // Iterate till the end of the list
        while (first != null) {
            second = first.next;
            third = tail;
 
            while (second != null && third != null && third != second) {
                int sum = (first.data + second.data + third.data);
 
                // Check if the current sum
                // is closest to X
                if (Math.Abs(X - sum) < Math.Abs(X - diff)) {
 
                    // Update the value of diff
                    diff = sum;
                }
 
                // Check if sum is less than X
                if (sum < X) {
 
                    // Increment the second
                    // pointer
                    second = second.next;
                } else {
 
                    // Decrement the third
                    // pointer
                    third = third.prev;
                }
            }
 
            // Move the first pointer
            // ahead
            first = first.next;
        }
 
        // Print the closest sum
        Console.Write(diff);
    }
 
    // Driver Code
    public static void Main(String[] args) {
 
        // Given Input
        head = null;
        insert(4);
        insert(3);
        insert(2);
        insert(1);
        int X = 3;
 
        // Function Call
        closestTripletSum(X);
    }
}
 
// This code is contributed by umadevi9616


Javascript


输出
6

时间复杂度: O(N 2 )
辅助空间: O(1)