แนวคิด
สำหรับ Doubly Linked List ที่เรียงลำดับแล้วของสมาชิกบวกที่ไม่ซ้ำกัน ภารกิจของเราคือหาคู่ใน Doubly Linked List ที่ผลคูณเท่ากับค่า x ที่กำหนด โดยไม่ใช้พื้นที่เพิ่มเติม (extra space)
อินพุต
List = 1 <=> 2 <=> 4 <=> 5 <=> 6 <=> 8 <=> 9, x = 8
เอาต์พุต
(1, 8), (2, 4)
อินพุต
List1 = 1 <=> 2 <=> 3 <=> 4 <=> 5 <=> 6 <=> 7, x = 6
เอาต์พุต
(1, 4), (2, 3)
วิธีการ
ตาม Simple Approach เราเดิน linked list ด้วย nested loops สองชั้นหาคู่ทั้งหมดและตรวจสอบคู่ที่ผลคูณเท่ากับ x Time complexity จะเป็น O(n^2) โดย n คือจำนวนโหนดทั้งหมด
Efficient Solution ที่มีประสิทธิภาพกว่านี้ ขั้นตอนของอัลกอริทึม:
- กำหนด pointer สองตัวเพื่อหาสมาชิกที่เป็นผู้สมัครใน sorted doubly linked list
- กำหนด first1 ให้ชี้ที่ head (เริ่มต้น) และ second1 ให้ชี้ที่ last_node (ท้าย)
- เริ่มต้น first และ second pointers เป็น first และ last nodes เนื่องจากไม่มี random access การหา second pointer ต้องเดิน list จนถึงท้าย
- ถ้าผลคูณของ first1 และ second1 น้อยกว่า x ให้เลื่อน first1 ไปข้างหน้า ถ้ามากกว่า x ให้เลื่อน second1 ไปข้างหลัง
- เงื่อนไขหยุดลูปต่างจาก array: ลูปจบเมื่อ pointer ใด pointer หนึ่งเป็น NULL หรือพวกมันทับซ้อนกัน (second1->next == first1) หรือกลายเป็นตัวเดียวกัน (first1 == second1)
ตัวอย่างโค้ด
// C++ program to find a pair with
// given product x in sorted Doubly
// Linked List
#include <bits/stdc++.h>
using namespace std;
// Doubly Linked List Node
struct Node1 {
int data1;
struct Node1 *next1, *prev1;
};
// ฟังก์ชันหาคู่ที่ผลคูณเท่ากับ x
void pairProduct(struct Node1* head1, int x1) {
// กำหนด two pointers
// first at beginning of DLL, second at end of DLL
struct Node1* first1 = head1;
struct Node1* second1 = head1;
while (second1->next1 != NULL)
second1 = second1->next1;
// ติดตามว่าพบคู่หรือไม่
bool found1 = false;
// ลูปจบเมื่อ pointer ใดเป็น NULL หรือทับซ้อนหรือเหมือนกัน
while (first1 != NULL && second1 != NULL && first1 != second1 && second1->next1 != first1) {
// พบคู่
if ((first1->data1 * second1->data1) == x1) {
found1 = true;
cout << "(" << first1->data1 << ", " << second1->data1 << ")" << endl;
// เลื่อน first ไปข้างหน้า
first1 = first1->next1;
// เลื่อน second ไปข้างหลัง
second1 = second1->prev1;
} else {
if ((first1->data1 * second1->data1) < x1)
first1 = first1->next1;
else
second1 = second1->prev1;
}
}
// ถ้าไม่พบคู่
if (found1 == false)
cout << "No pair found";
}
// ฟังก์ชันช่วยสร้างโหนดใหม่ที่ head
void insert(struct Node1** head1, int data1) {
struct Node1* temp1 = new Node1;
temp1->data1 = data1;
temp1->next1 = temp1->prev1 = NULL;
if (!(*head1))
(*head1) = temp1;
else {
temp1->next1 = *head1;
(*head1)->prev1 = temp1;
(*head1) = temp1;
}
}
// Driver Code
int main() {
// สร้าง Doubly Linked List
struct Node1* head1 = NULL;
insert(&head1, 7);
insert(&head1, 6);
insert(&head1, 5);
insert(&head1, 4);
insert(&head1, 3);
insert(&head1, 2);
insert(&head1, 1);
int x1 = 6;
pairProduct(head1, x1);
return 0;
}
ผลลัพธ์
(1, 6) (2, 3)