อัลกอริทึมของ Kadence: อาร์เรย์ย่อยที่ต่อเนื่องกันที่ใหญ่ที่สุด

อาร์เรย์ย่อยที่อยู่ติดกันผลรวมที่ใหญ่ที่สุดคืออะไร?

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

ตัวอย่างเช่น อาร์เรย์คือ {-10, 5, 1, 6, -9, 2, -7, 3, -5} อาร์เรย์ย่อยอาจเป็น: {-10,5,1,6} หรือ {5,1,6} หรือ {2,7,3, -5} เป็นต้น แต่ {5,1,6,3} ไม่สามารถเป็น อาร์เรย์ย่อยเนื่องจากไม่ได้รักษาลำดับไว้

อาร์เรย์ย่อยที่ต่อเนื่องกันที่ใหญ่ที่สุดผลรวมที่ใหญ่ที่สุด

ถ้าคุณสังเกต ในบรรดาซับอาร์เรย์ทั้งหมด ซับอาร์เรย์ที่เน้นข้อความไว้ดังต่อไปนี้ (5,1,6) มีค่าผลรวมสูงสุด:

อาร์เรย์ย่อยที่ต่อเนื่องกันที่ใหญ่ที่สุดผลรวมที่ใหญ่ที่สุด

ผลรวมของอาร์เรย์ย่อย {5,1,6} = 11 คือผลรวมสูงสุดในการรวมกันที่เป็นไปได้ทั้งหมดของอาร์เรย์ย่อยของอาร์เรย์ด้านบน ดังนั้น สำหรับอาร์เรย์ด้านบน อาร์เรย์ย่อยสูงสุดคือ {5,1,6}

อัลกอริทึมของ Kadence: อาร์เรย์ย่อยที่ต่อเนื่องกันที่ใหญ่ที่สุด

วิธีการง่ายๆ ในการแก้อาร์เรย์ย่อยที่ต่อเนื่องกันมากที่สุด

วิธีง่ายๆ ในการแก้ปัญหานี้คือการใช้สองลูปเพื่อค้นหาอาร์เรย์ย่อยทั้งหมด คำนวณผลรวม จากนั้นหาค่าสูงสุด

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

แนวทางง่ายๆ ในการแก้ผลรวมที่ใหญ่ที่สุด

นี่คือขั้นตอนง่าย ๆ ในการทำเช่นนี้

ขั้นตอน 1) เริ่มต้น max_sum ด้วยค่าจำนวนเต็มขั้นต่ำ และกำหนดตัวแปร “begin” และ “end” ด้วยศูนย์

ขั้นตอน 2) ให้ i และ j เป็นดัชนีของอาร์เรย์ โดยที่ "j" มากกว่าเท่ากับ "i" แสดงถึงดัชนีเริ่มต้นของอาร์เรย์ย่อย และ "j" แสดงถึงดัชนีสิ้นสุดของอาร์เรย์ย่อย

ขั้นตอน 3) “Current_sum” จะเก็บผลรวมของอาร์เรย์ย่อย หลังจากคำนวณผลรวมปัจจุบันแล้ว ให้ตรวจสอบว่า current_sum มากกว่า max_sum หรือไม่

ขั้นตอน 4) หาก current_sum มากกว่า ให้แทนที่ max_sum ด้วยผลรวมปัจจุบัน

ขั้นตอน 5) ตรวจสอบว่า "j" ไปถึงจุดสิ้นสุดของอาร์เรย์หรือไม่ หาก “j” ถึงจุดสิ้นสุดของอาร์เรย์ ให้เพิ่ม “i” และเปลี่ยนค่า current_sum เป็น 0

ขั้นตอน 6) ทำตามขั้นตอนเหล่านี้ทั้งหมด จนกระทั่ง “i” ถึงจุดสิ้นสุดของอาร์เรย์

ขั้นตอน 7) ที่จุดสิ้นสุดของสองลูปนี้ max_sum จะเก็บผลรวมอาร์เรย์ย่อยที่ใหญ่ที่สุด

รหัสหลอกสำหรับแนวทางง่ายๆ

  function maximumSubarraySum():
    input: array
  for all possible subArray from array:
    calculate sum of each sub array
    store the maximum subArray
  return the maximum sum

C++ การดำเนินการตามแนวทางง่ายๆ

#include <stdio.h>
#include <iostream>
using namespace std;
void maximumSubarraySum(int array[], int n) {
  int max_sum = -1e9;
  int begin = 0;
  int end = 0;
  for (int i = 0; i < n; i++) {
    int current_sum = 0;
    for (int j = i; j < n; j++) {
      current_sum += array[j];
      if (max_sum < current_sum) {
        max_sum = current_sum;
        begin = i;
        end = j;
      }
    }
  }
  cout << "largest sum is " << max_sum << endl;
  cout << "largest sum contiguous subarray: ";
  for (int i = begin; i <= end; i++) {
    cout << array[i] << "\t";
  }
}
int main() {
  int array[] = {-10, 5, 1, 6, -9, 2, -7, 3, -5};
  maximumSubarraySum(array, sizeof(array) / sizeof(array[0]));
}

Output:

largest sum is 12
largest sum contiguous subarray: 5      1       6

Python การนำแนวทางง่ายๆ ไปใช้

def maximumSubarraySum(numbers):
max_sum,begin,end = -1e9, 0 , 0
  for i in range(len(numbers)):
    current_sum=0
  for j in range(i,len(numbers)):
    current_sum+=numbers[j]
  if max_sum<current_sum:
    max_sum=current_sum
  begin,end=i,j
    print("largest sum is ",max_sum)
    print("largest sum contiguous subarray: ",end="")
  for i in range(begin,end+1):
    print(numbers[i],end='\t')
    numbers = [-10,5,1,6,-9,2,-7,3,-5]
    maximumSubarraySum(numbers)

Output:

largest sum is 12
largest sum contiguous subarray: 5      1       6

อัลกอริทึมของ Kadane เพื่อค้นหาอาร์เรย์ย่อยที่ต่อเนื่องกันมากที่สุด

อัลกอริทึมของ Kadane เป็นวิธี "การเขียนโปรแกรมแบบไดนามิก" ประเภทหนึ่ง ที่นี่เราจะใช้หนึ่งวงแทนสองวง การใช้งานอัลกอริทึมของ Kadane โดยทั่วไปใช้ได้กับอาร์เรย์จำนวนบวกเท่านั้น

เราต้องการเพียงตัวแปรสองตัวเพื่อค้นหาอาร์เรย์ย่อยที่ต่อเนื่องกันมากที่สุด นี่คือผังงานสำหรับอัลกอริทึมของ Kadane:

อัลกอริทึมของคาดาเนะเพื่อค้นหาผลรวมที่ใหญ่ที่สุด

ต่อไปนี้เป็นขั้นตอนสำหรับอัลกอริทึมของ Kadane:

ขั้นตอน 1) สร้างตัวแปรสองตัว ได้แก่ current_sum และ max_sum

“Current_sum” จะเก็บค่าของผลรวมสูงสุดที่ลงท้ายด้วยดัชนีอาร์เรย์เฉพาะ ในขณะที่ “max_sum” จะเก็บค่าผลรวมสูงสุดจนถึงตอนนี้

ขั้นตอน 2) เราจะเพิ่มค่าด้วย current_sum สำหรับแต่ละองค์ประกอบอาร์เรย์ จากนั้นเราจะตรวจสอบเงื่อนไขสองประการด้านล่าง:

  • หาก current_sum น้อยกว่าองค์ประกอบปัจจุบัน ค่า current_sum จะเป็นองค์ประกอบปัจจุบัน
  • หาก max_sum น้อยกว่า current_sum ดังนั้น max_sum จะเป็น current_sum

ขั้นตอน 3) ดำเนินการขั้นตอนก่อนหน้าสำหรับอาร์เรย์ทั้งหมด เราจะมีอาร์เรย์ย่อยที่ต่อเนื่องกันมากที่สุดในตัวแปร "max_sum"

ตัวอย่างอัลกอริทึมของ Kadane

เราจะสาธิตอัลกอริทึมของ Kadanes ด้วยอาร์เรย์ขนาดเล็ก และอภิปรายทุกขั้นตอนในการค้นหาอาร์เรย์ย่อยที่ต่อเนื่องกันที่ใหญ่ที่สุด

สมมติว่าอาร์เรย์ที่กำหนดเป็นดังต่อไปนี้:

ตัวอย่างอัลกอริทึมของ Kadane

ต่อไปนี้เป็นขั้นตอนของอัลกอริทึมของ Kadane:

ขั้นตอน 1) สร้างตัวแปรสองตัวคือ current_sum และ max_sum กำหนด INT_MIN ให้กับ max_sum และ 0 ให้กับ current_sum (ในที่นี้ INT_MIN หมายถึงจำนวนเต็มขั้นต่ำ)

ขั้นตอน 2) ที่ดัชนี 0 ค่าคือ 4 ดังนั้น current_sum = 0 + 4 หรือ 4 ที่นี่ current_sum มีขนาดใหญ่กว่า max_sum โดย max_sum จะเป็น 4

ตัวอย่างอัลกอริทึมของ Kadane

ขั้นตอน 3) ที่ดัชนี 1 ค่าคือ -2 ดังนั้น current_sum = 4 + (-2) หรือ 2

คราวนี้ current_sum น้อยกว่า max_sum ด้วยเหตุนี้ ค่าของ max_sum จะไม่ถูกอัปเดต

ตัวอย่างอัลกอริทึมของ Kadane

ขั้นตอน 4) ค่าถัดไปคือ 1 หากเราเพิ่มสิ่งนี้ด้วย current_sum แล้ว current_sum จะเป็น 3 แต่ max_sum นั้นมากกว่า current_sum ดังนั้น max_sum จะไม่ได้รับการอัปเดต

ตัวอย่างอัลกอริทึมของ Kadane

ขั้นตอน 5) ที่ดัชนี 3 ค่าคือสาม เราจะอัปเดตค่าโดยการเพิ่ม current_sum ขึ้น 3 ดังนั้น current_sum จะเป็น 6

ตัวอย่างอัลกอริทึมของ Kadane

ในกรณีนี้ max_sum จะน้อยกว่า current_sum ดังนั้น max_sum จะได้รับการอัปเดตด้วยค่า current_sum

ขั้นตอน 6) สำหรับองค์ประกอบสุดท้ายของอาร์เรย์ เราได้ -1 หากเราเพิ่มสิ่งนี้ด้วย current_sum แล้ว current_sum จะเป็น 5 ซึ่งน้อยกว่า max_sum ดังนั้น max_sum จะยังคงเป็น 6

ตัวอย่างอัลกอริทึมของ Kadane

เมื่อเรามาถึงจุดสิ้นสุดของอาร์เรย์ อัลกอริธึมจะสิ้นสุดที่นี่ ตอนนี้ “max_sum” มีอาร์เรย์ย่อยผลรวมสูงสุด ซึ่งก็คือ 5 อาร์เรย์ย่อยคือ {4,-2,1,3}

รหัสหลอกสำหรับอัลกอริทึมของ Kadane

function KadaneAlgorithm():
    input: array
    maximum_sum, current_sum = 0
    for each elements in array:
        add the element with current_sum
        if current_sum is greater than the maximum_sum
            then maximum_sum = current_sum
        if current_sum is less than the element
            then current_sum = element
    return the value of maximum_sum

C++การใช้อัลกอริทึมของ Kadane

#include < iostream >
using namespace std;
void kadane(int array[], int n) {
  int current_sum = 0;
  int max_sum = -1e9;
  // -1e9 means -10000000
  for (int i = 0; i < n; i++) {
    current_sum += array[i];
    if (max_sum < current_sum) {
      max_sum = current_sum;
    }
    if (current_sum < array[i]) {
      current_sum = array[i];
    }
  }
  cout << "largest sum is " << max_sum << endl;
}
int main() {
  int array[] = {-10, 5, 1, 6, -9, 2, -7, 3, -5};
  kadane(array, sizeof(array) / sizeof(array[0]));
}

Output:

largest sum is 12

Python การใช้อัลกอริทึมของ Kadane

def kadane(numbers):
  current_sum = 0
  max_sum = -1e9
for i in range(len(numbers)):
  current_sum += numbers[i]
if max_sum < current_sum:
  max_sum = current_sum
if current_sum<numbers[i]:
  current_sum = numbers[i]
  print("largest sum is ",max_sum)
  kadane([-10,5,1,6,-9,2,-7,3,-5])

Output:

largest sum is 12

การวิเคราะห์ความซับซ้อนสำหรับซับอาร์เรย์ต่อเนื่องที่มีผลรวมมากที่สุด

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

หากอาร์เรย์มีผลรวมเป็น N องค์ประกอบต่างๆ จากนั้นใช้สองลูป เราจะผ่าน N2 องค์ประกอบ ดังนั้น ความซับซ้อนของเวลาสำหรับวิธีการง่ายๆ ในการค้นหาผลรวมที่ใหญ่ที่สุดของซับอาร์เรย์ที่อยู่ติดกันจะเป็นดังนี้ O(N2). ที่นี่ “O” หมายถึงฟังก์ชันความซับซ้อน

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

ดังนั้นหากอาร์เรย์อินพุตมีขนาดเท่ากับ Nดังนั้นความซับซ้อนของเวลาของอัลกอริทึมของ Kadane จะเป็น O(N) ซึ่งเร็วกว่าวิธีการแบบง่าย ๆ เช่น อาร์เรย์ที่มีองค์ประกอบ 100 องค์ประกอบ วิธีการแบบง่าย ๆ จะใช้เวลา CPU 100*100 หรือ 10,000 แต่อัลกอริทึมของ Kadane จะใช้เวลา CPU เพียง 100 เท่านั้น