ความแตกต่างระหว่างการบันทึกและการเขียนโปรแกรมแบบไดนามิกคืออะไร?


247

ความแตกต่างระหว่างการบันทึกและการเขียนโปรแกรมแบบไดนามิกคืออะไร? ฉันคิดว่าการเขียนโปรแกรมแบบไดนามิกเป็นส่วนหนึ่งของการบันทึกความจำ ถูกต้องหรือไม่


8
นี่คือบทความที่อธิบายนี้ค่อนข้างกัน: แบบไดนามิกโปรแกรม VS memoization เทียบกับการจัดระเบียบ
aioobe

คำตอบ:


366

บทความที่เกี่ยวข้องกับ Programming.Guide: Dynamic programming vs memoization vs tabulation


ความแตกต่างระหว่างการบันทึกและการเขียนโปรแกรมแบบไดนามิกคืออะไร?

การบันทึกเป็นคำศัพท์ที่อธิบายถึงเทคนิคการปรับให้เหมาะสมซึ่งคุณแคชผลลัพธ์ที่คำนวณไว้ก่อนหน้านี้และส่งกลับผลลัพธ์ที่แคชเมื่อต้องการคำนวณแบบเดียวกันอีกครั้ง

การเขียนโปรแกรมแบบไดนามิกเป็นเทคนิคสำหรับการแก้ปัญหาซ้ำธรรมชาติซ้ำแล้วซ้ำอีกและสามารถใช้งานได้เมื่อการคำนวณของปัญหาย่อยทับซ้อนกัน

โดยทั่วไปแล้วการเขียนโปรแกรมแบบไดนามิกถูกนำไปใช้โดยใช้ตาราง แต่ยังสามารถนำมาใช้โดยใช้การบันทึก อย่างที่คุณเห็นไม่มีใครเป็น "ส่วนย่อย" ของอีกคนหนึ่ง


คำถามติดตามผลที่สมเหตุสมผลคือ: ความแตกต่างระหว่างการจัดระเบียบ (เทคนิคการเขียนโปรแกรมแบบไดนามิกทั่วไป) และการบันทึกช่วยจำคืออะไร?

เมื่อคุณแก้ปัญหาการเขียนโปรแกรมแบบไดนามิกโดยใช้ตารางคุณแก้ปัญหา " bottom up " คือโดยการแก้ปัญหาย่อยที่เกี่ยวข้องทั้งหมดก่อนโดยทั่วไปเติมตารางn -dimensional จากการคำนวณผลลัพธ์ในตารางจะคำนวณวิธีแก้ปัญหา "top" / ต้นฉบับ

หากคุณใช้การบันทึกช่วยจำเพื่อแก้ปัญหาที่คุณทำโดยรักษาแผนที่ของปัญหาย่อยที่แก้ไขแล้ว คุณทำมัน " บนลงล่าง " ในแง่ที่ว่าคุณแก้ปัญหา "บนสุด" ก่อน (ซึ่งมักจะเกิดขึ้นอีกครั้งเพื่อแก้ปัญหาย่อย)

สไลด์ที่ดีจากที่นี่ (ลิงค์ตอนนี้ตายไปแล้วสไลด์ยังดีอยู่):

  • หากปัญหาย่อยทั้งหมดต้องได้รับการแก้ไขอย่างน้อยหนึ่งครั้งอัลกอริธึมการเขียนโปรแกรมแบบไดนามิกจากล่างขึ้นบนมักจะมีประสิทธิภาพสูงกว่าอัลกอริทึมที่จดบันทึกจากบนลงล่างโดยปัจจัยคงที่
    • ไม่มีค่าใช้จ่ายสำหรับการเรียกซ้ำและค่าใช้จ่ายน้อยลงสำหรับการบำรุงรักษาตาราง
    • มีปัญหาบางประการที่รูปแบบปกติของการเข้าถึงตารางในอัลกอริทึมการเขียนโปรแกรมแบบไดนามิกสามารถใช้ประโยชน์เพื่อลดเวลาหรือความต้องการพื้นที่ได้มากขึ้น
  • หากปัญหาย่อยบางอย่างในพื้นที่ย่อยไม่จำเป็นต้องแก้ไขเลยโซลูชันที่บันทึกช่วยจำจะมีข้อได้เปรียบในการแก้ปัญหาเฉพาะปัญหาย่อยที่จำเป็นต้องใช้อย่างแน่นอน

แหล่งข้อมูลเพิ่มเติม:


1
คุณสลับการเขียนโปรแกรมแบบไดนามิกและการบันทึก พื้นฐานการบันทึกเป็นโปรแกรมแบบไดนามิกซ้ำ
user1603602

6
Naah ฉันคิดว่าคุณเข้าใจผิด ตัวอย่างเช่นไม่มีอะไรในบทความเกี่ยวกับการบันทึกความจำที่บอกว่าการเรียกซ้ำจำเป็นต้องมีส่วนร่วมเมื่อใช้การบันทึกความจำ
aioobe

หลังจากอ่านคำตอบแล้วหากคุณต้องการรู้สึกถึงผลของNZT-48เกี่ยวกับเรื่องนี้คุณสามารถดูบทความและตัวอย่างได้ที่นี่
snr

45

การเขียนโปรแกรมแบบไดนามิกเป็นกระบวนทัศน์ของอัลกอริทึมที่แก้ปัญหาที่ซับซ้อนโดยการแบ่งมันเป็นปัญหาย่อยและเก็บผลลัพธ์ของปัญหาย่อยเพื่อหลีกเลี่ยงการคำนวณผลลัพธ์เดียวกันอีกครั้ง

http://www.geeksforgeeks.org/dynamic-programming-set-1/

การบันทึกเป็นวิธีที่ง่ายในการติดตามโซลูชันที่แก้ไขก่อนหน้านี้ (มักใช้เป็นคู่ค่าคีย์แฮชซึ่งตรงข้ามกับการจัดเรียงซึ่งมักขึ้นอยู่กับอาร์เรย์) เพื่อไม่ให้คำนวณใหม่เมื่อพบอีกครั้ง มันสามารถใช้ในวิธีการจากล่างขึ้นบนหรือบนลงล่าง

ดูการสนทนานี้เกี่ยวกับบันทึกช่วยจำ vs ตาราง

ดังนั้นการเขียนโปรแกรมแบบไดนามิกเป็นวิธีการแก้ปัญหาบางระดับของปัญหาโดยการแก้ปัญหาความสัมพันธ์ / การเรียกซ้ำและการจัดเก็บการแก้ปัญหาที่พบก่อนหน้านี้ผ่านทางตารางหรือบันทึก การบันทึกเป็นวิธีการติดตามการแก้ไขปัญหาที่แก้ไขก่อนหน้านี้และสามารถใช้กับฟังก์ชั่นใด ๆ ที่มีวิธีการแก้ไขที่ไม่ซ้ำกันสำหรับชุดอินพุตที่กำหนด


14

การเขียนโปรแกรมแบบไดนามิกมักจะเรียกว่าการบันทึก!

  1. การบันทึกเป็นเทคนิคจากบนลงล่าง (เริ่มแก้ไขปัญหาที่กำหนดโดยการแยกมันออก) และการเขียนโปรแกรมแบบไดนามิกเป็นเทคนิคจากล่างขึ้นบน (เริ่มแก้ไขจากปัญหาย่อยย่อย ๆ ไปจนถึงปัญหาที่กำหนด)

  2. DP ค้นหาวิธีแก้ปัญหาโดยเริ่มจากตัวพิมพ์ใหญ่และทำงานจนสุดทาง DP ช่วยแก้ปัญหาย่อยทั้งหมดได้เพราะจะทำจากล่างขึ้นบน

    แตกต่างจากการบันทึกซึ่งแก้ปัญหาย่อยที่จำเป็นเท่านั้น

  3. DP มีศักยภาพในการแปลงการแก้ปัญหากำลังดุร้ายแบบเอ็กซ์โพเนนเชียลไทม์เป็นโพรซีเดอร์เวลาแบบพหุนาม

  4. DP อาจมีประสิทธิภาพมากกว่านี้มากเพราะเป็นการทำซ้ำ

    ในทางตรงกันข้ามการบันทึกจะต้องชำระค่าโสหุ้ย (มักสำคัญ) เนื่องจากการเรียกซ้ำ

เพื่อให้ง่ายยิ่งขึ้นการใช้การบันทึกจะใช้วิธีการจากบนลงล่างเพื่อแก้ไขปัญหาเช่นเริ่มจากปัญหาหลัก (หลัก) จากนั้นแบ่งให้เป็นปัญหาย่อยและแก้ปัญหาย่อยเหล่านี้ในทำนองเดียวกัน ในวิธีการนี้ปัญหาย่อยเดียวกันสามารถเกิดขึ้นได้หลายครั้งและใช้รอบ CPU มากขึ้นซึ่งจะเป็นการเพิ่มความซับซ้อนของเวลา ในขณะที่การเขียนโปรแกรมแบบไดนามิกปัญหาย่อยเดียวกันจะไม่ได้รับการแก้ไขหลายครั้ง แต่ผลลัพธ์ก่อนหน้านี้จะถูกใช้เพื่อเพิ่มประสิทธิภาพการแก้ปัญหา


10

(1) การบันทึกและ DP ในแนวความคิดเป็นสิ่งเดียวกัน เนื่องจาก: พิจารณาคำจำกัดความของ DP: "ปัญหาย่อยที่ทับซ้อนกัน" "และโครงสร้างย่อยที่ดีที่สุด" การบันทึกมีคุณสมบัติครบถ้วน 2 สิ่งเหล่านี้

(2) การบันทึกคือ DP ที่มีความเสี่ยงของการโอเวอร์โฟลว์ของสแต็กคือการเรียกซ้ำลึก DP bottom up ไม่มีความเสี่ยงนี้

(3) การบันทึกต้องการตารางแฮช พื้นที่เพิ่มเติมดังนั้นและเวลาค้นหา

ดังนั้นเพื่อตอบคำถาม:

- แนวคิด (1) หมายความว่าพวกเขาเป็นสิ่งเดียวกัน

- การพิจารณา (2) หากคุณต้องการจริงๆการบันทึกเป็นส่วนย่อยของ DP ในแง่ที่ว่าปัญหาที่แก้ไขได้โดยการบันทึกจะถูกแก้ไขโดย DP แต่ปัญหาที่แก้ได้โดย DP อาจไม่สามารถแก้ไขได้ด้วยการบันทึก อาจสแต็กล้น)

- เมื่อพิจารณา (3) พวกเขามีความแตกต่างเล็กน้อยในประสิทธิภาพ


6

จากวิกิพีเดีย:

memoization

ในการคำนวณการบันทึกเป็นเทคนิคการปรับให้เหมาะสมที่ใช้เพื่อเร่งความเร็วโปรแกรมคอมพิวเตอร์โดยให้การเรียกใช้ฟังก์ชันหลีกเลี่ยงการคำนวณผลลัพธ์ซ้ำสำหรับอินพุตที่ประมวลผลก่อนหน้านี้

การเขียนโปรแกรมแบบไดนามิก

ในวิชาคณิตศาสตร์และวิทยาศาสตร์คอมพิวเตอร์การเขียนโปรแกรมเชิงพลวัตเป็นวิธีการแก้ปัญหาที่ซับซ้อนโดยแบ่งย่อยเป็นปัญหาย่อยที่ง่ายกว่า

เมื่อแบ่งปัญหาออกเป็นปัญหาย่อยที่เล็กกว่า / ง่ายกว่าเรามักจะพบปัญหาย่อยเดียวกันมากกว่าหนึ่งครั้งดังนั้นเราจึงใช้การบันทึกเพื่อบันทึกผลลัพธ์ของการคำนวณก่อนหน้านี้ดังนั้นเราจึงไม่จำเป็นต้องทำซ้ำอีก

การเขียนโปรแกรมแบบไดนามิกมักจะพบกับสถานการณ์ที่เหมาะสมที่จะใช้การบันทึกความจำ แต่คุณสามารถใช้เทคนิคใดก็ได้โดยไม่จำเป็นต้องใช้วิธีอื่น


OP แก้ไขคำถามหลังจากที่ฉันโพสต์คำตอบ คำถามเดิมถามว่าอะไรคือความแตกต่างระหว่างทั้งสอง
yurib

4

ทั้งการบันทึกและการเขียนโปรแกรมแบบไดนามิกแก้ปัญหาย่อยแต่ละรายการเพียงครั้งเดียว

การบันทึกใช้การเรียกซ้ำและทำงานจากบนลงล่างในขณะที่การเขียนโปรแกรมแบบไดนามิกจะย้ายไปในทิศทางตรงกันข้ามเพื่อแก้ปัญหาจากล่างขึ้นบน

ด้านล่างคือการเปรียบเทียบที่น่าสนใจ -

จากบนลงล่าง - ก่อนอื่นคุณต้องบอกว่าฉันจะยึดครองโลก คุณจะทำอย่างไร คุณบอกว่าฉันจะยึดครองเอเชียก่อน คุณจะทำอย่างไร ฉันจะไปอินเดียก่อน ฉันจะเป็นหัวหน้ารัฐมนตรีของนิวเดลี ฯลฯ ฯลฯ

จากล่างขึ้นบน - คุณบอกว่าฉันจะกลายเป็น CM ของนิวเดลี จากนั้นจะเข้ายึดครองอินเดียจากนั้นประเทศอื่น ๆ ทั้งหมดในเอเชียและในที่สุดฉันก็จะเข้ายึดครองโลก


3

ฉันต้องการไปด้วยตัวอย่าง ;

ปัญหา:

คุณกำลังปีนบันไดกรณี ใช้เวลาไม่เกิน 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/


2

แค่คิดสองวิธี

  1. เราแยกปัญหาที่ใหญ่กว่าออกเป็นปัญหาย่อยที่เล็กกว่า - วิธีการจากบนลงล่าง
  2. เราเริ่มต้นจากปัญหาย่อยที่เล็กที่สุดและเข้าถึงปัญหาที่ใหญ่กว่า - วิธีการจากล่างขึ้นบน

ในการบันทึกเราจะไปกับ (1) ที่เราบันทึกการเรียกใช้ฟังก์ชันแต่ละครั้งในแคชและโทรกลับจากที่นั่น มันค่อนข้างแพงเพราะมันเกี่ยวข้องกับการโทรซ้ำ

ในการเขียนโปรแกรมแบบไดนามิกเราไปด้วย (2. ) ที่เรารักษาตารางด้านล่างขึ้นมาโดยการแก้ปัญหาย่อยโดยใช้ข้อมูลที่บันทึกไว้ในตารางโดยทั่วไปเรียกว่าตาราง DP

บันทึก:

  • ทั้งสองนี้สามารถใช้กับปัญหาย่อยทับซ้อนของปัญหาได้

  • การบันทึกความจำมีประสิทธิภาพค่อนข้างต่ำถึง DP เนื่องจากค่าโสหุ้ยที่เกี่ยวข้องในระหว่างการเรียกฟังก์ชันแบบเรียกซ้ำ

  • ความซับซ้อนของเวลาแบบอะซิมโทติกยังคงเหมือนเดิม

0

ในแบบไดนามิกการเขียนโปรแกรม ,

  • ไม่มีค่าใช้จ่ายสำหรับการเรียกซ้ำค่าใช้จ่ายน้อยลงสำหรับการบำรุงรักษาตาราง
  • รูปแบบปกติของการเข้าถึงตารางอาจถูกใช้เพื่อลดความต้องการเวลาหรือพื้นที่

ในท่องจำ ,

  • ปัญหาย่อยบางอย่างไม่จำเป็นต้องได้รับการแก้ไข
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.