เหตุใดลูปที่ซ้อนกันจึงถือว่าไม่เหมาะสม


33

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

ฉันไม่เข้าใจว่าทำไม เป็นเพราะมันมีผลต่อความสามารถในการอ่านของรหัสหรือไม่ หรือเป็น "เทคนิค" มากกว่านี้หรือไม่


4
ถ้าฉันจำหลักสูตร CS3 ของฉันได้อย่างถูกต้องนั่นเป็นเพราะมันมักจะนำไปสู่เวลาเอ็กซ์โปเนนเชียลซึ่งหมายความว่าถ้าคุณได้รับชุดข้อมูลขนาดใหญ่แอปพลิเคชันของคุณจะไม่สามารถใช้งานได้
Travis Pessetto

21
สิ่งหนึ่งที่คุณควรเรียนรู้เกี่ยวกับผู้สอน CS คือไม่ใช่ทุกสิ่งที่พวกเขาพูดจะนำไปใช้ 100% ในโลกแห่งความจริง ฉันไม่สนับสนุนลูปซ้อนกันมากกว่าสองสามลึก แต่ถ้าคุณต้องประมวลผลองค์ประกอบm x nเพื่อแก้ปัญหาของคุณคุณจะต้องทำซ้ำหลายครั้ง
Blrfl

8
@ TravisPessetto จริงๆแล้วมันยังคงมีความซับซ้อนของพหุนาม - O (n ^ k), k เป็นจำนวนซ้อนกัน, ไม่ใช่เลขชี้กำลัง O (k ^ n) โดยที่ k เป็นค่าคงที่
m3th0dman

1
@ m3th0dman ขอบคุณที่แก้ไขฉัน ครูของฉันไม่ได้ยอดเยี่ยมที่สุดในวิชานี้ เขาปฏิบัติต่อ O (n ^ 2) และ O (k ^ n) เหมือนกัน
เทรวิส Pessetto

2
ลูปแบบซ้อนเพิ่มความซับซ้อนของวงจร (ดูที่นี่ ) ซึ่งจะลดการบำรุงรักษาของโปรแกรมตามบางคน
Marco

คำตอบ:


62

การวนซ้ำซ้อนกันนั้นใช้ได้ตราบใดที่พวกเขาอธิบายอัลกอริทึมที่ถูกต้อง

ลูปซ้อนมีข้อควรพิจารณาเกี่ยวกับประสิทธิภาพ (ดูคำตอบของ @ Travis-Pesetto) แต่บางครั้งก็เป็นอัลกอริทึมที่ถูกต้องเช่นเมื่อคุณต้องการเข้าถึงทุกค่าในเมทริกซ์

การติดฉลากลูปใน Java ช่วยให้สามารถแยกลูปซ้อนได้หลายแบบก่อนกำหนดเมื่อวิธีอื่น ๆ ในการทำเช่นนี้จะยุ่งยาก เช่นบางเกมอาจมีโค้ดบางส่วนดังนี้:

Player chosen_one = null;
...
outer: // this is a label
for (Player player : party.getPlayers()) {
  for (Cell cell : player.getVisibleMapCells()) {
    for (Item artefact : cell.getItemsOnTheFloor())
      if (artefact == HOLY_GRAIL) {
        chosen_one = player;
        break outer; // everyone stop looking, we found it
      }
  }
}

ในขณะที่รหัสเช่นตัวอย่างข้างต้นบางครั้งอาจจะเป็นวิธีที่ดีที่สุดในการแสดงขั้นตอนวิธีการบางอย่างก็มักจะดีกว่าที่จะทำลายรหัสนี้ในฟังก์ชั่นที่มีขนาดเล็กและอาจจะใช้แทนreturn breakดังนั้นbreakที่มีป้ายเป็นลมกลิ่นรหัส ; ให้ความสนใจเป็นพิเศษเมื่อคุณเห็นมัน


2
เช่นเดียวกับกราฟิกบันทึกด้านใช้อัลกอริทึมที่ต้องเข้าถึงเมทริกซ์ทุกส่วน อย่างไรก็ตาม GPU นั้นมีความเชี่ยวชาญในการจัดการสิ่งนี้ในวิธีที่ประหยัดเวลา
Travis Pessetto

ใช่ GPU ทำสิ่งนี้ในลักษณะที่ขนานกันอย่างหนาแน่น คำถามนั้นเกี่ยวกับการประมวลผลเธรดเดียวฉันคิดว่า
9000

2
หนึ่งในเหตุผลที่ฉลากน่าจะเป็นเพราะมักจะมีทางเลือกอื่น ในกรณีนี้คุณสามารถกลับมาแทน
jgmjgm

22

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

ตัวอย่างเช่นหากคุณมี 100 รายการในรายการ A และ 100 รายการในรายการ B และคุณรู้ว่าสำหรับแต่ละรายการในรายการ A มีหนึ่งรายการในรายการ B ที่ตรงกับมัน (ด้วยคำจำกัดความของ "การจับคู่" ทิ้งไว้โดยเจตนาไม่ชัดเจน ที่นี่) และคุณต้องการสร้างรายการคู่วิธีง่ายๆในการทำเช่นนี้:

for each item X in list A:
  for each item Y in list B:
    if X matches Y then
      add (X, Y) to results
      break

100 รายการในแต่ละรายการนี้จะใช้เวลาเฉลี่ยของ 100 * 100/2 (5,000 บาท) matchesการดำเนินงาน ด้วยรายการเพิ่มเติมหรือหากไม่มั่นใจว่าค่าสหสัมพันธ์ 1: 1 จะมีราคาแพงกว่า

ในทางตรงกันข้ามมีวิธีที่เร็วกว่ามากในการดำเนินการเช่นนี้:

sort list A
sort list B (according to the same sort order)
I = 0
J = 0
repeat
  X = A[I]
  Y = B[J]
  if X matches Y then
    add (X, Y) to results
    increment I
    increment J
  else if X < Y then
    increment I
  else increment J
until either index reaches the end of its list

หากคุณทำเช่นนี้แทนที่จะเป็นการmatchesดำเนินการตามจำนวนlength(A) * length(B)ตอนนี้ขึ้นอยู่กับlength(A) + length(B)ซึ่งหมายความว่ารหัสของคุณจะทำงานได้เร็วขึ้นมาก


10
ด้วยข้อแม้ที่การตั้งค่าการเรียงลำดับใช้เวลาที่ไม่สำคัญO(n log n)สองครั้งหากใช้ Quicksort
Robert Harvey

@ RobertHarvey: แน่นอน แต่นั่นก็ยังน้อยกว่าO(n^2)ค่าที่ไม่ใช่เล็ก ๆ ของ N.
Mason Wheeler

10
อัลกอริทึมรุ่นที่สองไม่ถูกต้องโดยทั่วไป ก่อนอื่นสมมติว่า X และ Y นั้นสามารถเทียบเคียงได้ผ่าน<โอเปอเรเตอร์ซึ่งโดยทั่วไปไม่สามารถหาได้จากmatchesโอเปอเรเตอร์ ประการที่สองแม้ว่าทั้ง X และ Y มีตัวเลขอัลกอริทึมที่ 2 อาจจะยังคงก่อให้เกิดผลที่ไม่ถูกต้องเช่นเมื่อเป็นX matches Y X + Y == 100
มหาอำมาตย์

9
@ user958624: เห็นได้ชัดว่านี่เป็นภาพรวมระดับสูงของอัลกอริทึมทั่วไป เช่นเดียวกับตัวดำเนินการ "จับคู่" ต้องกำหนด "<" ในลักษณะที่ถูกต้องในบริบทของข้อมูลที่กำลังเปรียบเทียบ หากทำอย่างถูกต้องผลลัพธ์จะถูกต้อง
Mason Wheeler

PHP ทำสิ่งที่คล้ายกันครั้งสุดท้ายกับอาร์เรย์ที่เป็นเอกลักษณ์ฉันคิดและ / หรือตรงข้ามกับมัน ผู้คนจะเพียงแค่ใช้อาร์เรย์ของ PHP ซึ่งใช้แฮชและมันเร็วกว่ามาก
jgmjgm

11

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

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

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

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


1
คุณสามารถแผ่ลูปซ้อนกันบ่อยครั้งและยังคงใช้เวลาเดียวกัน ใช้สำหรับความกว้าง 0 ถึงสำหรับความสูง 0; คุณสามารถใส่ความสูงได้ 0 ถึงความกว้าง
jgmjgm

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

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

7

ในกรณีของลูปซ้อนกันหลายคุณจบลงด้วยเวลาพหุนาม ตัวอย่างเช่นให้รหัสหลอกนี้:

set i equal to 1
while i is not equal to 100
  increment i
  set j equal to 1
  while j is not equal to i
    increment j
  end
 end

นี่จะถือว่าเป็นเวลา O (n ^ 2) ซึ่งจะเป็นกราฟที่คล้ายกับ: ป้อนคำอธิบายรูปภาพที่นี่

โดยที่แกน y คือระยะเวลาที่โปรแกรมของคุณใช้ในการยกเลิกและแกน x คือปริมาณข้อมูล

หากคุณได้รับข้อมูลมากเกินไปโปรแกรมของคุณจะช้าจนไม่มีใครรอ และมันก็ไม่มากนักประมาณ 1,000 รายการข้อมูลที่ฉันเชื่อว่าจะใช้เวลานานเกินไป


10
คุณอาจต้องการเลือกกราฟของคุณอีกครั้ง: นั่นคือเส้นโค้งเลขชี้กำลังไม่ใช่เส้นกำลังสอง, การเรียกซ้ำไม่ได้ทำสิ่ง O (n log n) จาก O (n ^ 2)
ratchet freak

5
สำหรับการเรียกซ้ำฉันมีสองคำว่า "สแต็ค" และ "ล้น"
Mateusz

10
คำสั่งของคุณที่การเรียกซ้ำสามารถลดการดำเนินการ O (n ^ 2) เป็น O (n log n) ส่วนใหญ่ไม่ถูกต้อง อัลกอริทึมเดียวกันที่ใช้ซ้ำแบบซ้ำ ๆ ซ้ำ ๆ กันควรมีความซับซ้อนของเวลาแบบโอเพ่นซอร์ส นอกจากนี้การเรียกซ้ำมักจะช้ากว่า (ขึ้นอยู่กับการใช้ภาษา) เนื่องจากการเรียกซ้ำแต่ละครั้งต้องใช้การสร้างเฟรมสแต็กใหม่ในขณะที่การวนซ้ำนั้นต้องการเพียงสาขา / การเปรียบเทียบ ฟังก์ชั่นการโทรมักจะถูก แต่ก็ไม่ได้ฟรี
dckrooney

2
@TravisPessetto ฉันเห็น 3 สแต็คโอเวอร์โฟลว์ใน 6 เดือนที่ผ่านมาในขณะที่พัฒนาแอปพลิเคชัน C # เนื่องจากการอ้างอิงซ้ำหรือการอ้างอิงวัตถุแบบวนรอบ อะไรตลกเกี่ยวกับมันที่มันจะผิดพลาดและคุณไม่รู้ว่าอะไรจะกระทบคุณ เมื่อคุณเห็นลูปซ้อนกันคุณจะรู้ว่ามีบางอย่างไม่ดีเกิดขึ้นและมีข้อยกเว้นเกี่ยวกับดัชนีผิดสำหรับบางสิ่งที่มองเห็นได้ง่าย
Mateusz

2
@Mateusz ด้วยเช่นภาษา Java ช่วยให้คุณสามารถจับข้อผิดพลาดล้นสแต็ค การติดตามแบบสแต็กควรให้คุณเห็นสิ่งที่เกิดขึ้น ฉันไม่ได้มีประสบการณ์มากนัก แต่ครั้งเดียวที่ฉันเห็นข้อผิดพลาดสแต็กล้นคือใน PHP ที่มีข้อผิดพลาดทำให้เกิดการเรียกซ้ำไม่สิ้นสุดและ PHP มีหน่วยความจำไม่เพียงพอที่ 512MB ที่กำหนดให้ การเรียกซ้ำจำเป็นต้องมีค่าการยุติสุดท้ายซึ่งไม่ดีสำหรับลูปที่ไม่มีที่สิ้นสุด เช่นเดียวกับทุกสิ่งใน CS มีเวลาและสถานที่สำหรับทุกสิ่ง
เทรวิส Pessetto

0

การขับรถบรรทุกขนาดสามสิบตันแทนที่จะเป็นรถโดยสารขนาดเล็กถือเป็นการปฏิบัติที่ไม่ดี ยกเว้นเมื่อคุณต้องการขนส่งสิ่งของ 20 หรือ 30 ตัน

เมื่อคุณใช้การวนซ้ำซ้อนกันมันไม่ใช่วิธีปฏิบัติที่ไม่ดี มันโง่อย่างเต็มที่หรือเป็นสิ่งที่ต้องการ คุณตัดสินใจ.

อย่างไรก็ตามมีคนบ่นเรื่องลูปการติดฉลาก คำตอบคือ: ถ้าคุณต้องถามคำถามอย่าใช้การติดฉลาก หากคุณรู้พอที่จะตัดสินใจด้วยตัวเองคุณต้องตัดสินใจเอง


ถ้าคุณรู้พอที่จะตัดสินใจด้วยตัวเองคุณก็รู้ว่าจะไม่ใช้ลูปที่มีป้ายกำกับ :-)
user949300

ไม่เมื่อคุณได้รับการสอนเพียงพอคุณได้รับการสอนให้ไม่ใช้การใช้ฉลาก เมื่อคุณรู้พอคุณอยู่เหนือความเชื่อและทำในสิ่งที่ถูกต้อง
gnasher729

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

-1

ไม่มีอะไรผิดปกติอย่างแน่นอนหรือจำเป็นต้องเลวเกี่ยวกับลูปซ้อนกัน อย่างไรก็ตามมีข้อควรพิจารณาและข้อผิดพลาดบางประการ

บทความที่คุณนำไปสู่น่าจะเป็นชื่อของความกะทัดรัดหรือเนื่องจากกระบวนการทางจิตวิทยาที่รู้จักกันว่าถูกเผาไหม้ข้ามไปเฉพาะ

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

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

เนื่องจากคำตอบมากมายที่นี่ชี้ให้เห็นการซ้อนกันวนรอบเพื่อเป็นการบ่งบอกถึงลักษณะการทำงานของโปรแกรมของคุณซึ่งอาจทำให้การซ้อนแต่ละครั้งแย่ลงอย่างมาก นั่นคือ O (n), O (n ^ 2), O (n ^ 3) และอื่น ๆ ซึ่งประกอบด้วย O (n ^ depth) โดยที่ความลึกแสดงถึงจำนวนลูปที่คุณซ้อนกัน เมื่อการทำรังของคุณเติบโตขึ้นเวลาที่ต้องใช้จะเพิ่มขึ้นแบบทวีคูณ ปัญหาก็คือว่ามันไม่แน่นอนว่าเวลาหรือพื้นที่ของคุณจะซับซ้อน (บ่อยครั้งที่ * b * c แต่ไม่ใช่ว่าทุกวนรังอาจทำงานตลอดเวลาอย่างใดอย่างหนึ่ง) และไม่แน่ใจว่าคุณจะ มีปัญหาด้านประสิทธิภาพแม้ว่าจะเป็นเช่นนั้นก็ตาม

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

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

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

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

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

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

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

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

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

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

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

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

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


คม <-> ตัวอย่างเช่นมีดทื่อไม่ดีเช่นมีดทื่อมักจะมีมากขึ้นเป็นอันตรายสำหรับการตัด และ O (n) -> O (n ^ 2) -> O (n ^ 3) ไม่ได้ชี้แจงในnก็เรขาคณิตหรือพหุนาม
Caleth

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

@jgmjgm: n ^ depth คือพหุนามความลึก ^ n เป็นเลขชี้กำลัง มันไม่ใช่เรื่องของการตีความ
Roel Schroeven

x ^ y แตกต่างจาก y ^ x หรือไม่ ความผิดพลาดที่คุณทำคือคุณไม่เคยอ่านคำตอบ คุณโลภแบบเอกซ์โปเนนเชียลแล้วจึงโลภสมการด้วยตัวเองไม่ใช่แบบเอ็กซ์โปเนนเชียล ถ้าคุณอ่านคุณจะเห็นว่ามันบอกว่ามันเพิ่มทวีคูณสำหรับแต่ละเลเยอร์ของการซ้อนและถ้าคุณทดสอบมันด้วยตัวเองเวลาสำหรับ (a = 0; a <n; a ++); (b = 0; b <n ข ++) สำหรับ (c = 0; ค <n ค ++); เมื่อเพิ่มหรือลบลูปคุณจะเห็นว่ามันเป็นเลขชี้กำลัง คุณจะพบการวนซ้ำหนึ่งครั้งที่ n ^ 1, สองการแสดงที่ n ^ 2 และสามการแสดงที่ n ^ 3 คุณล้มเหลวในการเข้าใจซ้อน: D เลขชี้กำลังของ Gemoetric
jgmjgm

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