ความแตกต่างระหว่างการบันทึกและการเขียนโปรแกรมแบบไดนามิกคืออะไร? ฉันคิดว่าการเขียนโปรแกรมแบบไดนามิกเป็นส่วนหนึ่งของการบันทึกความจำ ถูกต้องหรือไม่
ความแตกต่างระหว่างการบันทึกและการเขียนโปรแกรมแบบไดนามิกคืออะไร? ฉันคิดว่าการเขียนโปรแกรมแบบไดนามิกเป็นส่วนหนึ่งของการบันทึกความจำ ถูกต้องหรือไม่
คำตอบ:
บทความที่เกี่ยวข้องกับ Programming.Guide: Dynamic programming vs memoization vs tabulation
ความแตกต่างระหว่างการบันทึกและการเขียนโปรแกรมแบบไดนามิกคืออะไร?
การบันทึกเป็นคำศัพท์ที่อธิบายถึงเทคนิคการปรับให้เหมาะสมซึ่งคุณแคชผลลัพธ์ที่คำนวณไว้ก่อนหน้านี้และส่งกลับผลลัพธ์ที่แคชเมื่อต้องการคำนวณแบบเดียวกันอีกครั้ง
การเขียนโปรแกรมแบบไดนามิกเป็นเทคนิคสำหรับการแก้ปัญหาซ้ำธรรมชาติซ้ำแล้วซ้ำอีกและสามารถใช้งานได้เมื่อการคำนวณของปัญหาย่อยทับซ้อนกัน
โดยทั่วไปแล้วการเขียนโปรแกรมแบบไดนามิกถูกนำไปใช้โดยใช้ตาราง แต่ยังสามารถนำมาใช้โดยใช้การบันทึก อย่างที่คุณเห็นไม่มีใครเป็น "ส่วนย่อย" ของอีกคนหนึ่ง
คำถามติดตามผลที่สมเหตุสมผลคือ: ความแตกต่างระหว่างการจัดระเบียบ (เทคนิคการเขียนโปรแกรมแบบไดนามิกทั่วไป) และการบันทึกช่วยจำคืออะไร?
เมื่อคุณแก้ปัญหาการเขียนโปรแกรมแบบไดนามิกโดยใช้ตารางคุณแก้ปัญหา " bottom up " คือโดยการแก้ปัญหาย่อยที่เกี่ยวข้องทั้งหมดก่อนโดยทั่วไปเติมตารางn -dimensional จากการคำนวณผลลัพธ์ในตารางจะคำนวณวิธีแก้ปัญหา "top" / ต้นฉบับ
หากคุณใช้การบันทึกช่วยจำเพื่อแก้ปัญหาที่คุณทำโดยรักษาแผนที่ของปัญหาย่อยที่แก้ไขแล้ว คุณทำมัน " บนลงล่าง " ในแง่ที่ว่าคุณแก้ปัญหา "บนสุด" ก่อน (ซึ่งมักจะเกิดขึ้นอีกครั้งเพื่อแก้ปัญหาย่อย)
สไลด์ที่ดีจากที่นี่ (ลิงค์ตอนนี้ตายไปแล้วสไลด์ยังดีอยู่):
- หากปัญหาย่อยทั้งหมดต้องได้รับการแก้ไขอย่างน้อยหนึ่งครั้งอัลกอริธึมการเขียนโปรแกรมแบบไดนามิกจากล่างขึ้นบนมักจะมีประสิทธิภาพสูงกว่าอัลกอริทึมที่จดบันทึกจากบนลงล่างโดยปัจจัยคงที่
- ไม่มีค่าใช้จ่ายสำหรับการเรียกซ้ำและค่าใช้จ่ายน้อยลงสำหรับการบำรุงรักษาตาราง
- มีปัญหาบางประการที่รูปแบบปกติของการเข้าถึงตารางในอัลกอริทึมการเขียนโปรแกรมแบบไดนามิกสามารถใช้ประโยชน์เพื่อลดเวลาหรือความต้องการพื้นที่ได้มากขึ้น
- หากปัญหาย่อยบางอย่างในพื้นที่ย่อยไม่จำเป็นต้องแก้ไขเลยโซลูชันที่บันทึกช่วยจำจะมีข้อได้เปรียบในการแก้ปัญหาเฉพาะปัญหาย่อยที่จำเป็นต้องใช้อย่างแน่นอน
แหล่งข้อมูลเพิ่มเติม:
การเขียนโปรแกรมแบบไดนามิกเป็นกระบวนทัศน์ของอัลกอริทึมที่แก้ปัญหาที่ซับซ้อนโดยการแบ่งมันเป็นปัญหาย่อยและเก็บผลลัพธ์ของปัญหาย่อยเพื่อหลีกเลี่ยงการคำนวณผลลัพธ์เดียวกันอีกครั้ง
http://www.geeksforgeeks.org/dynamic-programming-set-1/
การบันทึกเป็นวิธีที่ง่ายในการติดตามโซลูชันที่แก้ไขก่อนหน้านี้ (มักใช้เป็นคู่ค่าคีย์แฮชซึ่งตรงข้ามกับการจัดเรียงซึ่งมักขึ้นอยู่กับอาร์เรย์) เพื่อไม่ให้คำนวณใหม่เมื่อพบอีกครั้ง มันสามารถใช้ในวิธีการจากล่างขึ้นบนหรือบนลงล่าง
ดูการสนทนานี้เกี่ยวกับบันทึกช่วยจำ vs ตาราง
ดังนั้นการเขียนโปรแกรมแบบไดนามิกเป็นวิธีการแก้ปัญหาบางระดับของปัญหาโดยการแก้ปัญหาความสัมพันธ์ / การเรียกซ้ำและการจัดเก็บการแก้ปัญหาที่พบก่อนหน้านี้ผ่านทางตารางหรือบันทึก การบันทึกเป็นวิธีการติดตามการแก้ไขปัญหาที่แก้ไขก่อนหน้านี้และสามารถใช้กับฟังก์ชั่นใด ๆ ที่มีวิธีการแก้ไขที่ไม่ซ้ำกันสำหรับชุดอินพุตที่กำหนด
การเขียนโปรแกรมแบบไดนามิกมักจะเรียกว่าการบันทึก!
การบันทึกเป็นเทคนิคจากบนลงล่าง (เริ่มแก้ไขปัญหาที่กำหนดโดยการแยกมันออก) และการเขียนโปรแกรมแบบไดนามิกเป็นเทคนิคจากล่างขึ้นบน (เริ่มแก้ไขจากปัญหาย่อยย่อย ๆ ไปจนถึงปัญหาที่กำหนด)
DP ค้นหาวิธีแก้ปัญหาโดยเริ่มจากตัวพิมพ์ใหญ่และทำงานจนสุดทาง DP ช่วยแก้ปัญหาย่อยทั้งหมดได้เพราะจะทำจากล่างขึ้นบน
แตกต่างจากการบันทึกซึ่งแก้ปัญหาย่อยที่จำเป็นเท่านั้น
DP มีศักยภาพในการแปลงการแก้ปัญหากำลังดุร้ายแบบเอ็กซ์โพเนนเชียลไทม์เป็นโพรซีเดอร์เวลาแบบพหุนาม
DP อาจมีประสิทธิภาพมากกว่านี้มากเพราะเป็นการทำซ้ำ
ในทางตรงกันข้ามการบันทึกจะต้องชำระค่าโสหุ้ย (มักสำคัญ) เนื่องจากการเรียกซ้ำ
เพื่อให้ง่ายยิ่งขึ้นการใช้การบันทึกจะใช้วิธีการจากบนลงล่างเพื่อแก้ไขปัญหาเช่นเริ่มจากปัญหาหลัก (หลัก) จากนั้นแบ่งให้เป็นปัญหาย่อยและแก้ปัญหาย่อยเหล่านี้ในทำนองเดียวกัน ในวิธีการนี้ปัญหาย่อยเดียวกันสามารถเกิดขึ้นได้หลายครั้งและใช้รอบ CPU มากขึ้นซึ่งจะเป็นการเพิ่มความซับซ้อนของเวลา ในขณะที่การเขียนโปรแกรมแบบไดนามิกปัญหาย่อยเดียวกันจะไม่ได้รับการแก้ไขหลายครั้ง แต่ผลลัพธ์ก่อนหน้านี้จะถูกใช้เพื่อเพิ่มประสิทธิภาพการแก้ปัญหา
(1) การบันทึกและ DP ในแนวความคิดเป็นสิ่งเดียวกัน เนื่องจาก: พิจารณาคำจำกัดความของ DP: "ปัญหาย่อยที่ทับซ้อนกัน" "และโครงสร้างย่อยที่ดีที่สุด" การบันทึกมีคุณสมบัติครบถ้วน 2 สิ่งเหล่านี้
(2) การบันทึกคือ DP ที่มีความเสี่ยงของการโอเวอร์โฟลว์ของสแต็กคือการเรียกซ้ำลึก DP bottom up ไม่มีความเสี่ยงนี้
(3) การบันทึกต้องการตารางแฮช พื้นที่เพิ่มเติมดังนั้นและเวลาค้นหา
ดังนั้นเพื่อตอบคำถาม:
- แนวคิด (1) หมายความว่าพวกเขาเป็นสิ่งเดียวกัน
- การพิจารณา (2) หากคุณต้องการจริงๆการบันทึกเป็นส่วนย่อยของ DP ในแง่ที่ว่าปัญหาที่แก้ไขได้โดยการบันทึกจะถูกแก้ไขโดย DP แต่ปัญหาที่แก้ได้โดย DP อาจไม่สามารถแก้ไขได้ด้วยการบันทึก อาจสแต็กล้น)
- เมื่อพิจารณา (3) พวกเขามีความแตกต่างเล็กน้อยในประสิทธิภาพ
จากวิกิพีเดีย:
memoization
ในการคำนวณการบันทึกเป็นเทคนิคการปรับให้เหมาะสมที่ใช้เพื่อเร่งความเร็วโปรแกรมคอมพิวเตอร์โดยให้การเรียกใช้ฟังก์ชันหลีกเลี่ยงการคำนวณผลลัพธ์ซ้ำสำหรับอินพุตที่ประมวลผลก่อนหน้านี้
การเขียนโปรแกรมแบบไดนามิก
ในวิชาคณิตศาสตร์และวิทยาศาสตร์คอมพิวเตอร์การเขียนโปรแกรมเชิงพลวัตเป็นวิธีการแก้ปัญหาที่ซับซ้อนโดยแบ่งย่อยเป็นปัญหาย่อยที่ง่ายกว่า
เมื่อแบ่งปัญหาออกเป็นปัญหาย่อยที่เล็กกว่า / ง่ายกว่าเรามักจะพบปัญหาย่อยเดียวกันมากกว่าหนึ่งครั้งดังนั้นเราจึงใช้การบันทึกเพื่อบันทึกผลลัพธ์ของการคำนวณก่อนหน้านี้ดังนั้นเราจึงไม่จำเป็นต้องทำซ้ำอีก
การเขียนโปรแกรมแบบไดนามิกมักจะพบกับสถานการณ์ที่เหมาะสมที่จะใช้การบันทึกความจำ แต่คุณสามารถใช้เทคนิคใดก็ได้โดยไม่จำเป็นต้องใช้วิธีอื่น
ทั้งการบันทึกและการเขียนโปรแกรมแบบไดนามิกแก้ปัญหาย่อยแต่ละรายการเพียงครั้งเดียว
การบันทึกใช้การเรียกซ้ำและทำงานจากบนลงล่างในขณะที่การเขียนโปรแกรมแบบไดนามิกจะย้ายไปในทิศทางตรงกันข้ามเพื่อแก้ปัญหาจากล่างขึ้นบน
ด้านล่างคือการเปรียบเทียบที่น่าสนใจ -
จากบนลงล่าง - ก่อนอื่นคุณต้องบอกว่าฉันจะยึดครองโลก คุณจะทำอย่างไร คุณบอกว่าฉันจะยึดครองเอเชียก่อน คุณจะทำอย่างไร ฉันจะไปอินเดียก่อน ฉันจะเป็นหัวหน้ารัฐมนตรีของนิวเดลี ฯลฯ ฯลฯ
จากล่างขึ้นบน - คุณบอกว่าฉันจะกลายเป็น CM ของนิวเดลี จากนั้นจะเข้ายึดครองอินเดียจากนั้นประเทศอื่น ๆ ทั้งหมดในเอเชียและในที่สุดฉันก็จะเข้ายึดครองโลก
ฉันต้องการไปด้วยตัวอย่าง ;
ปัญหา:
คุณกำลังปีนบันไดกรณี ใช้เวลาไม่เกิน n ก้าวไปถึงด้านบน
แต่ละครั้งคุณสามารถปีนขึ้นไป 1 หรือ 2 ขั้นตอน คุณสามารถปีนขึ้นไปด้านบนได้หลายวิธี
เรียกซ้ำด้วยการบันทึก
ด้วยวิธีนี้เรากำลังตัดแต่งกิ่ง (การกำจัดวัสดุส่วนเกินออกจากต้นไม้หรือไม้พุ่ม) ต้นไม้เรียกซ้ำด้วยความช่วยเหลือของชุดบันทึกและลดขนาดของต้นไม้เรียกซ้ำจนถึง nn
public class Solution {
public int climbStairs(int n) {
int memo[] = new int[n + 1];
return climb_Stairs(0, n, memo);
}
public int climb_Stairs(int i, int n, int memo[]) {
if (i > n) {
return 0;
}
if (i == n) {
return 1;
}
if (memo[i] > 0) {
return memo[i];
}
memo[i] = climb_Stairs(i + 1, n, memo) + climb_Stairs(i + 2, n, memo);
return memo[i];
}
}
การเขียนโปรแกรมแบบไดนามิก
เนื่องจากเราสามารถเห็นปัญหานี้สามารถแบ่งออกเป็นปัญหาย่อยและมีคุณสมบัติโครงสร้างพื้นฐานที่ดีที่สุดนั่นคือทางออกที่ดีที่สุดสามารถสร้างได้อย่างมีประสิทธิภาพจากการแก้ปัญหาที่ดีที่สุดของปัญหาย่อยเราสามารถใช้การเขียนโปรแกรมแบบไดนามิกเพื่อแก้ปัญหานี้
public class Solution {
public int climbStairs(int n) {
if (n == 1) {
return 1;
}
int[] dp = new int[n + 1];
dp[1] = 1;
dp[2] = 2;
for (int i = 3; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
}
ตัวอย่างใช้จากhttps://leetcode.com/problems/climbing-stairs/
แค่คิดสองวิธี
ในการบันทึกเราจะไปกับ (1) ที่เราบันทึกการเรียกใช้ฟังก์ชันแต่ละครั้งในแคชและโทรกลับจากที่นั่น มันค่อนข้างแพงเพราะมันเกี่ยวข้องกับการโทรซ้ำ
ในการเขียนโปรแกรมแบบไดนามิกเราไปด้วย (2. ) ที่เรารักษาตารางด้านล่างขึ้นมาโดยการแก้ปัญหาย่อยโดยใช้ข้อมูลที่บันทึกไว้ในตารางโดยทั่วไปเรียกว่าตาราง DP
บันทึก:
ทั้งสองนี้สามารถใช้กับปัญหาย่อยทับซ้อนของปัญหาได้
การบันทึกความจำมีประสิทธิภาพค่อนข้างต่ำถึง DP เนื่องจากค่าโสหุ้ยที่เกี่ยวข้องในระหว่างการเรียกฟังก์ชันแบบเรียกซ้ำ
ในแบบไดนามิกการเขียนโปรแกรม ,
ในท่องจำ ,