Contents

คำแนะนำเกี่ยวกับอัลกอริธึมหน้าต่างบานเลื่อนและวิธีการใช้งานในระหว่างเดินทาง

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

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

อัลกอริธึมหน้าต่างบานเลื่อนทำงานในลักษณะใด และเราจะดำเนินการอย่างไรโดยใช้ภาษาโปรแกรม Go

ทำความเข้าใจอัลกอริธึมหน้าต่างบานเลื่อน

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

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

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

ภาพประกอบที่ให้มาจะแสดงภาพกราฟิกของการดำเนินการ:

/th/images/sliding_window_algorithm_visual.jpg

พารามิเตอร์ของหน้าต่างสามารถปรับแต่งได้ตามความต้องการเฉพาะที่เกิดจากปัญหาที่เกิดขึ้น

การใช้อัลกอริธึมหน้าต่างบานเลื่อนใน Go

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

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

พิจารณาอาร์เรย์ตัวเลขที่กำหนดให้เป็น"nums"ดังที่ปรากฎในข้อมูลโค้ดที่ตามมา เรามีการจัดเรียงค่าต่างๆ ดังต่อไปนี้:

 nums := []int{1, 5, 4, 8, 7, 1, 9}

พิจารณาอาร์เรย์ปฐมภูมิที่มีขนาด n x m โดยที่ n แทนจำนวนแถว และ m แทนจำนวนคอลัมน์ ให้เราพิจารณาเซตย่อยของอาร์เรย์นี้เพิ่มเติม ซึ่งเรียกว่าอาร์เรย์ย่อย ซึ่งขยายข้าม k แถว และมีค่าเป็น 3 สำหรับมิติคอลัมน์ (นั่นคือ k คอลัมน์)

 k := 3

อาจนิยามฟังก์ชันที่ต้องการหาผลรวมที่เป็นไปได้มากที่สุดเท่าที่จะเป็นไปได้จากการรวมอาร์เรย์ย่อย โดยที่แต่ละอาร์เรย์ย่อยมีความยาว k:

 func maximumSubarraySum(nums []int, k int) int {
    // body
}

แม้ว่าการจัดเก็บสำเนาขององค์ประกอบเป้าหมายในหน้าต่างเป็นทางเลือกอื่นเป็นไปได้ แต่วิธีนี้กลับแสดงประสิทธิภาพที่ต่ำกว่ามาตรฐาน

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

เพื่อแก้ไขปัญหานี้ จำเป็นต้องคำนวณผลรวมของส่วนเริ่มต้นที่มีความยาว’k’ด้วยเหตุนี้ คุณควรรวมบรรทัดต่อไปนี้ไว้ในฟังก์ชันของคุณ:

 var windowStart, windowEnd, maxSum, windowSum int
windowStart = 0

for i := 0; i < k; i\+\+ {
    windowSum \+= nums[i]
}

maxSum = windowSum

รหัสดังกล่าวสร้างตัวแปรที่จำเป็นสำหรับอัลกอริทึม คำนวณผลรวมของหน้าต่างเริ่มต้นภายในอาร์เรย์ และตั้งค่าผลรวมสูงสุดเป็นผลรวมที่ได้รับจากหน้าต่างหลัก ต่อจากนั้น จะเริ่มต้นตัวแปร maxSum ด้วยค่าที่กำหนดสำหรับการสะสมของหน้าต่างที่เปิด

ระยะต่อมาเกี่ยวข้องกับการสำรวจอาร์เรย์ nums โดยเริ่มต้นที่ดัชนี k และค่อยๆ เลื่อน"หน้าต่าง"ไปข้างหน้าตามลำดับขั้นตอน ในแต่ละขั้นตอนของกระบวนการนี้ “หน้าต่าง” จะถูกเลื่อนทีละน้อยจนกระทั่งถึงจุดสิ้นสุดของอาร์เรย์

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

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

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

 for windowEnd = k; windowEnd < len(nums); windowEnd\+\+ {
    windowSum = windowSum \+ nums[windowEnd] - nums[windowStart]

    if windowSum > maxSum {
        maxSum = windowSum
    }

    // slide window forward
    windowStart\+\+
}

เมื่อสิ้นสุดการวนซ้ำ ค่ารวมสูงสุดจะถูกจัดเก็บไว้ภายใน maxSum ซึ่งอาจส่งคืนเป็นเอาต์พุตของฟังก์ชัน

 return maxSum

ฟังก์ชั่นที่สมบูรณ์ของคุณควรมีลักษณะดังนี้:

 func maximumSubarraySum(nums []int, k int) int {
    var windowStart, windowEnd, maxSum, windowSum int
    windowStart = 0

    for i := 0; i < k; i\+\+ {
        windowSum \+= nums[i]
    }

    maxSum = windowSum

    for windowEnd = k; windowEnd < len(nums); windowEnd\+\+ {
        windowSum = windowSum \+ nums[windowEnd] - nums[windowStart]

        if windowSum > maxSum {
            maxSum = windowSum
        }

        // slide window forward
        windowStart\+\+
     }

    return maxSum
}

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

 func main() {
    nums := []int{1, 5, 4, 8, 7, 1, 9}
    k := 3
    fmt.Println(maximumSubarraySum(nums, k))
}

ในกรณีนี้ ผลลัพธ์จะเท่ากับ 19 ซึ่งสอดคล้องกับผลรวมของอาร์เรย์ย่อยที่ประกอบด้วยองค์ประกอบ 4, 8 และ 7 ซึ่งก็คือค่าสูงสุดในบรรดาลำดับย่อยทั้งหมดภายในอาร์เรย์ที่กำหนด

อาจใช้แนวทางที่เปรียบเทียบได้เพื่อจัดการกับรูปแบบที่เกิดซ้ำในบริบทและขอบเขตทางภาษาต่างๆ เช่น การจัดการองค์ประกอบที่ทำซ้ำภายในช่วงที่กำหนดโดยใช้

ผลลัพธ์อัลกอริธึมที่เหมาะสมที่สุดในการใช้งานที่มีประสิทธิภาพ

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

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