ผลรวมที่ใหญ่ที่สุดหารด้วย n


16

ฉันถามคำถามนี้กับ StackOverflowแต่ฉันคิดว่าที่นี่เป็นสถานที่ที่เหมาะสมกว่า

นี่เป็นปัญหาจากหลักสูตรIntroduction to Algorithm :

คุณมีอาร์เรย์aพร้อมnจำนวนเต็มบวก (อาร์เรย์ไม่จำเป็นต้องเรียงหรือองค์ประกอบที่ไม่ซ้ำกัน) แนะนำให้O(n)ขั้นตอนวิธีการที่จะหาผลรวมที่ใหญ่ที่สุดขององค์ประกอบที่หารด้วยnn

ตัวอย่าง: = [ 6 , 1 , 13 , 4 , 9 , 8 , 25 ] , n = 7 คำตอบคือ56 (มีองค์ประกอบ6 , 13 , 4 , 8 , 25 )a=[6,1,13,4,9,8,25],n=7566,13,4,8,25

มันค่อนข้างง่ายที่จะหาได้ในO(n2)โดยใช้โปรแกรมแบบไดนามิกและการจัดเก็บผลรวมที่ใหญ่ที่สุดกับส่วนที่เหลือ0,1,2,...,n1 1

นอกจากนี้หากเรา จำกัด ความสนใจขององค์ประกอบต่อเนื่องกันมันเป็นเรื่องง่ายที่จะหาลำดับที่ดีที่สุดในเวลาโดยการจัดเก็บผลรวมบางส่วนโมดูโลn : ให้S [ i ] = a [ 0 ] + a [ 1 ] + + a [ i ]สำหรับแต่ละส่วนที่เหลือrจำดัชนีที่ใหญ่ที่สุดjเช่นS [ j ] rO(n)nS[i]=a[0]+a[1]++a[i]rjแล้วสำหรับแต่ละฉันคุณพิจารณา S [ J ] - S [ ผม]ที่เจเป็นดัชนีที่สอดคล้องกับ R = S [ ผม] mod nS[j]r(modn)iS[j]S[i]jr=S[i]modn

แต่มีวิธี - เวลาสำหรับกรณีทั่วไปหรือไม่ ข้อเสนอแนะใด ๆ จะได้รับการชื่นชม! ฉันคิดว่ามันมีบางอย่างที่ต้องจัดการกับพีชคณิตเชิงเส้น แต่ฉันไม่แน่ใจจริงๆO(n)

หรือสามารถทำได้ในเวลา ?O(nlogn)


2
1. คุณได้โพสต์คำถามเดียวกันนี้ไว้ใน Stack Overflow กรุณาอย่าโพสต์คำถามเดียวกันบนเว็บไซต์ต่างๆ เราไม่ต้องการสำเนาหลายชุดที่ลอยอยู่ในเว็บไซต์ SE หลายแห่ง หากคุณไม่ได้รับคำตอบที่ยอมรับคุณสามารถตั้งค่าสถานะคำถามของคุณสำหรับการย้ายไปยังเว็บไซต์อื่น แต่โปรดอย่าโพสต์สิ่งเดียวกันที่อื่น 2. คุณสามารถให้การอ้างอิง / การอ้างอิง / ลิงก์ไปยังตำราหรือหลักสูตรที่ปรากฏได้หรือไม่? คุณแน่ใจได้อย่างไรว่ามีโซลูชัน - เวลาอยู่ O(n)
DW

5
ความท้าทายในมหาวิทยาลัยของคุณยังเปิดอยู่หรือไม่? มันจะมีประโยชน์มากหากเห็นลิงก์ไปยังหลักสูตรคำถามที่แน่นอนและหากเป็นจริงและผู้ที่เตรียมไว้จะอธิบาย / เผยแพร่คำตอบของพวกเขามันจะยอดเยี่ยม O(n)
Evil

มันค่อนข้างง่ายในการค้นหาใน O (n2) O (n2) โดยใช้การเขียนโปรแกรมแบบไดนามิกและเก็บผลรวมที่ใหญ่ที่สุดด้วยส่วนที่เหลือ 0,1,2, ... , n − 10,1,2, ... , n − 1 คุณช่วยอธิบายเรื่องนี้หน่อยได้ไหม? ฉันสามารถเข้าใจได้ว่านี่จะเป็นแบบ n สแควร์สได้หรือไม่ถ้าเราพิจารณาองค์ประกอบที่ต่อเนื่องกันเท่านั้น แต่ด้วยองค์ประกอบที่ไม่ต่อเนื่องเช่นกันมันจะไม่เป็นเลขชี้กำลังหรือไม่?
Nithish Inpursuit Ofhappiness

คำตอบ:


4

นี่คือความคิดสุ่มบางประการ:

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

    ราคาจะเป็นถ้าเราประมวลผลองค์ประกอบk มีไม่ต่ำผูกพันของΩ ( n log n )ขั้นตอนวิธีนี้เพราะเราไม่ได้มีการจัดเรียงองค์ประกอบทั้งหมด มันใช้เวลาเพียงO ( n log k )เวลาที่จะได้รับkองค์ประกอบที่เล็กที่สุดO(nk)kΩ(nlogn)O(nlogk)k

  • ถ้าเราใส่ใจเซตที่มีขนาดใหญ่กว่าเซตที่มีผลรวมมากที่สุดเราอาจจะสามารถใช้การคูณพหุนามแบบแปลงฟูริเยร์ที่เร็วขึ้นเพื่อแก้ปัญหาในเวลา คล้ายกับสิ่งที่ทำใน3SUMเมื่อช่วงของโดเมนถูก จำกัด (หมายเหตุ: ใช้ squaring ซ้ำ ๆ เพื่อทำการค้นหาแบบไบนารีมิฉะนั้นคุณจะได้O ( n k ( log n ) ( log log n ) )โดยที่kO(n(logn)2(loglogn))O(nk(logn)(loglogn))k คือจำนวนขององค์ประกอบที่ถูกตัดออก)

  • เมื่อเป็นคอมโพสิตและเกือบจะเหลือทั้งหมดเป็นหนึ่งหลายn 's ปัจจัยเวลาที่สำคัญอาจจะมีการบันทึกไว้โดยมุ่งเน้นไปที่ส่วนที่เหลือที่ไม่ได้มีหลายปัจจัยที่nn

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

  • คุณสามารถโกน log factorโดยการติดตามความสามารถในการเข้าถึงและการใช้ bit mask (ในอัลกอริทึมแบบไดนามิกที่พลิกแล้ว) จากนั้นย้อนรอยเมื่อคุณไปถึงเป้าหมายที่เหลือ

  • อัลกอริทึมการเขียนโปรแกรมแบบไดนามิกเป็นคล้อยตามมากที่จะทำงานแบบขนาน ด้วยหน่วยประมวลผลสำหรับแต่ละช่องบัฟเฟอร์ที่คุณสามารถได้รับลงไป ) หรืออีกวิธีหนึ่งโดยใช้O ( n 2 )ความกว้างและหารและการรวมพิชิตแทนของการรวมย้ำค่าใช้จ่ายลึกวงจรจะได้รับทุกทางลงไปที่O ( log 2 n )O(n)O(n2)O(log2n)

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


nO(n)

2
r1r2

-1

อัลกอริทึมที่ฉันนำเสนอมีดังนี้:

ผลรวมหารด้วย n หากคุณเพิ่มการเรียกซึ่งเป็นผลคูณของ n

ก่อนที่คุณจะเริ่มคุณจะสร้าง hashmap โดยมี int เป็นคีย์และรายการดัชนีเป็นค่า คุณยังสร้างรายการผลลัพธ์ที่มีดัชนี

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

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

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

คำแนะนำล่าสุด: ยังไม่ได้ทดสอบอัลกอริทึมเขียน testcase โดยใช้อัลกอริทึมกำลังดุร้าย


2
โลภเชิงเส้นไม่ทำงาน คุณพิจารณาเฉพาะองค์ประกอบที่หารด้วย n และคู่หารด้วย n ได้แล้ว triples และอีกมากมายเป็นอย่างไร ไม่รับประกันผลรวมย่อยสูงสุดในกรณีเล็ก ๆ น้อย ๆ [2, 1, 8] -> ผลรวมสูงสุดคือ 9 แต่อัลกอริทึมของคุณส่งคืน 3
Evil

@EvilJS เกิดอะไรขึ้นกับ sub- ของคุณn2อัลกอริทึม?
delta-terminator

ขอบคุณที่บอกความผิดพลาดนี้ให้ฉัน ความคิดของฉันเกี่ยวกับการปรับปรุงคือการทำ hashmap ของรายการที่เรียงลำดับโดยการเพิ่มมูลค่าและเริ่มสะสมหลังจากเสร็จสิ้นการส่งผ่านอาร์เรย์
Tobias Würfl

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

Yeah was quite a quick idea with the stacks. In fact you only need lists in the hashmap which you sort. I was not sure wether it is polite to edit my first answer. After all I made a mistake in my first attempt.
Tobias Würfl

-2

use this DP method from (/programming/4487438/maximum-sum-of-non-consecutive-elements?rq=1):

Given an array A[0..n], let M(i) be the optimal solution using the elements with indices 0..i. Then M(-1) = 0 (used in the recurrence), M(0) = A[0], and M(i) = max(M(i - 1), M(i - 2) + A[i]) for i = 1, ..., n. M(n) is the solution we want. This is O(n). You can use another array to store which choice is made for each subproblem, and so recover the actual elements chosen.

Change recursion to M(i) = max(M(i - 1), M(i - 2) + A[i] ) such that is stored only if its divisible by N


2
This doesn't work – I'll let you figure out why. (Hint: Try to run it on the constant 1 array.) Also, in this problem we do allow consecutive elements.
Yuval Filmus

1
This is very good solution, just to totally different (and much easier) problem.
Evil
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.