在已排序的双链表 (DLL) 中查找最接近 X 的三元组和
给定一个由N个节点和一个整数X组成的有序双向链表,任务是找到列表中最接近X的三个节点的总和。
例子:
Input: DLL: -8 ↔ 2 ↔ 3 ↔ 4 ↔ 5, X = 1
Output: 1
Explanation: The required three integers {-8, 4, 5} whose sum is 1 and is closest to 1.
Input: DLL: 1 ↔ 2 ↔ 3 ↔ 4, X = 3
Output: 6
Explanation: The required three integers are {1, 2, 3} whose sum is 6 and is closest to X = 3.
朴素方法:解决给定问题的最简单方法是使用三个嵌套循环生成所有可能的三元组,然后选择总和最接近X的三元组并打印三元组的总和。
时间复杂度: O(N 3 )
辅助空间: O(1)
高效方法:为了优化上述方法,想法是使用 3 指针技术。请按照以下步骤解决此问题:
- 初始化4个变量, first和second指向双向链表的头节点,即first=head , second = head , tail和third都初始化为双向链表的最后一个节点。
- 初始化一个变量diff ,初始化为INT_MAX ,它存储最接近X的总和。
- 在第一个节点不为NULL时进行迭代并执行以下步骤:
- 初始化first的second到 next ,即second = first→next和third = 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)