บทช่วยสอนนี้จะกล่าวถึงปัญหาที่เราได้รับอาร์เรย์ของจำนวนเต็มบวกที่แตกต่างกัน เราจำเป็นต้องหาชุดย่อยที่ใหญ่ที่สุดเพื่อให้องค์ประกอบที่ใหญ่กว่าทุกคู่ถูกหารด้วยองค์ประกอบที่เล็กกว่า ตัวอย่างเช่น −
Input: nums[ ] = { 1, 4, 2, 6, 7}
Output: 1 2 4
Explanation:
All Divisible subsets are: (1, 2, 4), (1, 2, 6), (1, 7), etc
We have 2 subsets of length 3 in which all the pairs satisfy the condition.
Input: nums[ ] = { 1, 2, 3, 6 }
Output: 6 2 1 แนวทางในการหาแนวทางแก้ไข
มีสองแนวทางที่แตกต่างกันที่เราจะอธิบายในบทช่วยสอนนี้
แนวทางง่ายๆ
ในแนวทางง่ายๆ เราสามารถใช้การเรียกซ้ำเพื่อแก้ปัญหานี้ได้ เราจะนำแต่ละองค์ประกอบและตรวจสอบว่าควรรวมไว้ในเซตย่อยหรือไม่ สมมติว่าเราเริ่มต้นด้วยองค์ประกอบแรก เราจะมีสองตัวเลือก ไม่ว่าจะรวมอยู่ในเซตย่อยหรือไม่สำหรับองค์ประกอบแรก มารวมองค์ประกอบแรกกัน จากนั้นสำหรับองค์ประกอบที่สองที่จะรวมอยู่ในเซตย่อย องค์ประกอบนั้นควรถูกหารด้วยหรือแบ่งองค์ประกอบในสตริงย่อย นั่นคือองค์ประกอบแรก นี่คือวิธีที่เราจะไปทั่วทั้งอาร์เรย์ ดังนั้นจะมี 2^n เส้นทางที่เป็นไปได้ที่จะสร้างความซับซ้อนของเวลาของ O(2^n) มาดูแนวทางที่เป็นไปได้ในการแก้ปัญหานี้กัน
แนวทางที่มีประสิทธิภาพ
แนวทางที่มีประสิทธิภาพสามารถนำมาใช้โดยใช้โปรแกรมแบบไดนามิกในปัญหานี้
-
จัดเรียงอาร์เรย์เพื่อให้องค์ประกอบด้านซ้ายหารด้วยองค์ประกอบที่ถูกต้อง เราต้องตรวจสอบการหาร 1 ครั้ง
-
เราจะใช้ลำดับที่ยาวที่สุดที่เพิ่มขึ้น นั่นคืออาร์เรย์ dp[ ] ของเรา เพื่อเก็บเซ็ตย่อยที่ใหญ่ที่สุดที่หารได้ของดัชนี till ith เราจะเริ่มต้นแต่ละดัชนีด้วยหนึ่งรายการเพราะทุกองค์ประกอบแบ่งตัวมันเอง
-
ตอนนี้เราจะวนซ้ำจากดัชนีที่ 2 และตรวจสอบแต่ละองค์ประกอบเพื่อหาชุดย่อยที่หารได้มากที่สุดที่ลงท้ายด้วยดัชนีปัจจุบัน ด้วยวิธีนี้ เราจะพบเซตย่อยสูงสุดสำหรับแต่ละดัชนี
-
ตอนนี้สำรวจผ่านอาร์เรย์ และสำหรับทุกองค์ประกอบ ให้ค้นหาตัวหารที่มีจำนวนที่หารได้มากที่สุด และเปลี่ยนค่าการนับที่หารได้ของดัชนีปัจจุบันเป็นจำนวนที่หารได้ขององค์ประกอบนั้น + 1
ตัวอย่าง
รหัส C++ สำหรับแนวทางข้างต้น
#include<bits/stdc++.h>
using namespace std;
int main(){
int nums[] = {1, 2, 3, 6};
int n = sizeof(nums)/sizeof(int);
// sorting the array to exclude one condition for division.
sort(nums, nums+n);
vector <int> prev_res(n, -1);
// vector to store divisors of all the elements
vector <int> dp(n, 1);
int max = 1;
for (int i=1; i<n; i++){ // Check if there's a divisor of ith element present at jth index.
for (int j=0; j<i; j++){
if (nums[i]%nums[j] == 0){
// check If adding that increases the number of elements in subsequence.
if (dp[i] < dp[j] + 1){
dp[i] = dp[j]+1;
prev_res[i] = j;
}
}
}
// finding index having a maximum number of subsets.
if(max<dp[i])
max = dp[i];
}
cout << "Largest divisible subset in the array: ";
// printing the maximum subset
int k = max;
while (k >= 0){
cout << nums[k] << " ";
k = prev_res[k];
}
return 0;
} ผลลัพธ์
Largest divisible subset in the array: 6 2 1
บทสรุป
ในบทช่วยสอนนี้ เราได้พูดถึงปัญหา:เราจำเป็นต้องค้นหาเซตย่อยที่หารได้มากที่สุดในอาร์เรย์ที่กำหนดโดยที่จำนวนเต็มในแต่ละคู่จะหารลงตัว เราได้พูดคุยถึงแนวทางจากการเรียกซ้ำซึ่งสร้างความซับซ้อนของเวลาแบบเอ็กซ์โพเนนเชียล ดังนั้นเราจึงพูดถึงโซลูชันการเขียนโปรแกรมแบบไดนามิก เรายังพูดถึงโปรแกรม C++ สำหรับปัญหานี้ ซึ่งเราสามารถทำได้ด้วยภาษาโปรแกรม เช่น C, Java, Python เป็นต้น เราหวังว่าคุณจะพบว่าบทช่วยสอนนี้มีประโยชน์