Tại sao các vòng lặp lồng nhau được coi là thực hành xấu?


33

Hôm nay, giảng viên của tôi đã đề cập rằng có thể "gắn nhãn" các vòng lặp trong Java để bạn có thể tham khảo chúng khi xử lý các vòng lặp lồng nhau. Vì vậy, tôi đã tìm kiếm tính năng này khi tôi không biết về nó và nhiều nơi giải thích tính năng này được theo sau bởi một cảnh báo, không khuyến khích các vòng lặp lồng nhau.

Tôi thực sự không hiểu tại sao? Có phải vì nó ảnh hưởng đến khả năng đọc của mã? Hay là một cái gì đó "kỹ thuật" hơn?


4
Nếu tôi nhớ khóa học CS3 của mình một cách chính xác bởi vì nó thường dẫn đến thời gian theo cấp số nhân, điều đó có nghĩa là nếu bạn nhận được một tập dữ liệu lớn, ứng dụng của bạn sẽ trở nên không sử dụng được.
Travis Pessetto

21
Một điều bạn nên tìm hiểu về các giảng viên CS là không phải mọi thứ họ nói đều áp dụng 100% trong thế giới thực. Tôi không khuyến khích các vòng lặp lồng nhau sâu hơn một vài lần, nhưng nếu bạn phải xử lý các phần tử m x n để giải quyết vấn đề của mình, bạn sẽ thực hiện nhiều lần lặp đó.
Blrfl

8
@TravisPessetto Trên thực tế, nó vẫn là độ phức tạp đa thức - O (n ^ k), k là số lượng lồng nhau, không phải số mũ O (k ^ n), trong đó k là hằng số.
m3th0dman

1
@ m3th0dman Cảm ơn đã sửa lỗi cho tôi. Giáo viên của tôi không phải là người giỏi nhất trong chủ đề này. Anh ta đối xử với O (n ^ 2) và O (k ^ n) như nhau.
Travis Pessetto

2
Các vòng lặp lồng nhau làm tăng độ phức tạp chu kỳ (xem tại đây ), làm giảm khả năng duy trì của một chương trình, theo một số người.
Marco

Câu trả lời:


62

Các vòng lặp lồng nhau là tốt miễn là họ mô tả thuật toán chính xác.

Các vòng lặp lồng nhau có các cân nhắc về hiệu suất (xem câu trả lời của @ Travis-Pesetto), nhưng đôi khi nó chính xác là thuật toán chính xác, ví dụ như khi bạn cần truy cập vào mọi giá trị trong ma trận.

Các vòng lặp gắn nhãn trong Java cho phép thoát ra sớm một số vòng lặp lồng nhau khi các cách khác để làm điều này sẽ rất khó khăn. Ví dụ, một số trò chơi có thể có một đoạn mã như thế này:

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
      }
  }
}

Mặc dù mã như ví dụ trên đôi khi có thể là cách tối ưu để diễn đạt một thuật toán nhất định, nhưng tốt hơn hết là chia mã này thành các hàm nhỏ hơn và có thể sử dụng returnthay vì break. Vì vậy, breakvới một nhãn là một mùi mã mờ ; chú ý hơn khi bạn nhìn thấy nó


2
Giống như một đồ họa ghi chú bên sử dụng một thuật toán phải truy cập vào mọi phần của ma trận. Tuy nhiên, GPU là chuyên dụng để xử lý việc này theo cách hiệu quả về thời gian.
Travis Pessetto

Vâng, GPU thực hiện điều này theo cách song song; câu hỏi là về một chủ đề thực hiện, tôi cho rằng.
9000

2
Một trong những lý do nhãn có xu hướng bị nghi ngờ là vì thường có một sự thay thế. Trong trường hợp này bạn có thể trở lại thay thế.
jgmjgm

22

Các vòng lặp lồng nhau thường xuyên (nhưng không phải luôn luôn) thực hành xấu, bởi vì chúng thường xuyên (nhưng không phải luôn luôn) quá mức cho những gì bạn đang cố gắng làm. Trong nhiều trường hợp, có một cách nhanh hơn và ít lãng phí hơn để hoàn thành mục tiêu mà bạn đang cố gắng đạt được.

Ví dụ: nếu bạn có 100 mục trong danh sách A và 100 mục trong danh sách B và bạn biết rằng đối với mỗi mục trong danh sách A, có một mục trong danh sách B khớp với nó, (với định nghĩa "khớp" bị che khuất một cách có chủ ý ở đây) và bạn muốn tạo một danh sách các cặp, cách đơn giản để làm điều đó là như sau:

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

Với 100 mục trong mỗi danh sách, việc này sẽ mất trung bình 100 * 100/2 (5.000) matchesthao tác. Với nhiều mặt hàng hơn, hoặc nếu không đảm bảo tương quan 1: 1, nó sẽ trở nên đắt hơn.

Mặt khác, có một cách nhanh hơn nhiều để thực hiện một thao tác như thế này:

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

Nếu bạn làm theo cách này, thay vì số lượng matcheshoạt động dựa trên length(A) * length(B), giờ đây nó dựa trên length(A) + length(B), điều đó có nghĩa là mã của bạn sẽ chạy nhanh hơn nhiều.


10
Với lời cảnh báo rằng thiết lập sắp xếp mất một lượng thời gian không hề nhỏ, O(n log n)hai lần, nếu Quicksort được sử dụng.
Robert Harvey

@RobertHarvey: Tất nhiên rồi. Nhưng điều đó vẫn còn ít hơn nhiều so O(n^2)với các giá trị không nhỏ của N.
Mason Wheeler

10
Phiên bản thứ hai của thuật toán nói chung là không chính xác. Đầu tiên, nó giả định rằng X và Y có thể so sánh được thông qua <toán tử, thường không thể được lấy từ matchestoán tử. Thứ hai, ngay cả khi cả X và Y là số, thuật toán 2nd vẫn có thể tạo ra kết quả sai, ví dụ như khi X matches YX + Y == 100.
Pasha

9
@ user958624: Rõ ràng đây là một tổng quan rất cao về thuật toán chung. Giống như toán tử "khớp", "<" phải được xác định theo cách chính xác trong bối cảnh dữ liệu được so sánh. Nếu điều này được thực hiện chính xác, kết quả sẽ chính xác.
Mason Wheeler

Tôi đã làm một cái gì đó giống như cái cuối cùng với mảng duy nhất của họ, tôi nghĩ và / hoặc ngược lại với nó. Mọi người thay vào đó chỉ sử dụng các mảng của PHP dựa trên hàm băm và nó sẽ nhanh hơn nhiều.
jgmjgm

11

Một lý do để tránh các vòng lặp lồng nhau là bởi vì đó là một ý tưởng tồi để lồng các cấu trúc khối quá sâu, bất kể chúng có vòng lặp hay không.

Mỗi chức năng hoặc phương pháp phải dễ hiểu, cả mục đích của nó (tên nên thể hiện những gì nó làm) và cho người bảo trì (cần phải dễ hiểu nội bộ). Nếu một hàm quá phức tạp để dễ hiểu, điều đó thường có nghĩa là một số phần bên trong nên được đưa vào các hàm riêng biệt để chúng có thể được gọi trong hàm chính (bây giờ nhỏ hơn) theo tên.

Các vòng lặp lồng nhau có thể khó hiểu tương đối nhanh chóng, mặc dù một số vòng lặp lồng nhau là tốt - như những người khác chỉ ra, điều đó không có nghĩa là bạn đang tạo ra một vấn đề hiệu suất bằng cách sử dụng thuật toán chậm cực kỳ (và không cần thiết).

Trên thực tế, bạn không cần các vòng lặp lồng nhau để có được các giới hạn hiệu suất chậm một cách vô lý. Ví dụ, hãy xem xét một vòng lặp duy nhất trong mỗi lần lặp lấy một mục từ hàng đợi, sau đó có thể đặt lại một vài mục - ví dụ: tìm kiếm đầu tiên theo chiều rộng của một mê cung. Hiệu suất không được quyết định bởi độ sâu của vòng lặp (chỉ có 1) mà là số lượng vật phẩm được đưa vào hàng đợi đó trước khi nó cạn kiệt ( nếu nó cạn kiệt) - phần lớn có thể tiếp cận của mê cung là.


1
Bạn có thể rất thường xuyên làm phẳng một vòng lặp lồng nhau và nó vẫn mất cùng thời gian. lấy từ 0 đến chiều rộng, từ 0 đến chiều cao; Thay vào đó, bạn chỉ có thể đặt chiều cao từ 0 đến chiều rộng.
jgmjgm

@jgmjgm - vâng, có nguy cơ làm phức tạp mã bên trong vòng lặp. Làm phẳng có thể đơn giản hóa điều đó đôi khi, nhưng thường thì ít nhất bạn sẽ thêm sự phức tạp của việc khôi phục các chỉ số mà bạn thực sự muốn. Một mẹo nhỏ đó là sử dụng loại chỉ mục tạo ra tất cả các vòng lặp lồng vào logic để tăng chỉ số ghép đặc biệt - bạn không thể làm điều đó chỉ với một vòng lặp, nhưng có thể bạn có nhiều vòng lặp với cấu trúc tương tự hoặc có thể bạn có thể viết một phiên bản chung linh hoạt hơn. Chi phí sử dụng loại đó (nếu có) có thể đáng giá cho sự rõ ràng.
Steve314

Tôi không cho rằng đây là một việc nên làm nhưng đơn giản đến mức có thể đơn giản đến mức biến hai vòng thành một nhưng vẫn không ảnh hưởng đến độ phức tạp của thời gian.
jgmjgm

7

Với trường hợp nhiều vòng lặp lồng nhau, bạn kết thúc với thời gian đa thức. Ví dụ cho mã giả này:

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

Đây sẽ được coi là thời gian O (n ^ 2) sẽ là một biểu đồ tương tự như: nhập mô tả hình ảnh ở đây

Trong đó trục y là lượng thời gian mà chương trình của bạn mất để kết thúc và trục x là lượng dữ liệu.

Nếu bạn nhận được quá nhiều dữ liệu, chương trình của bạn sẽ rất chậm, không ai sẽ đợi nó. và không quá 1.000 mục nhập dữ liệu mà tôi tin rằng sẽ mất quá nhiều thời gian.


10
bạn có thể muốn chọn lại biểu đồ của mình: đó là một đường cong hàm mũ không phải là một bậc hai, cũng là đệ quy không tạo ra thứ O (n log n) từ O (n ^ 2)
ratchet freak

5
Để đệ quy tôi có hai từ "stack" và "overflow"
Mateusz

10
Tuyên bố của bạn rằng đệ quy có thể giảm hoạt động O (n ^ 2) xuống O (n log n) phần lớn là không chính xác. Thuật toán tương tự được triển khai đệ quy so với lặp lại nên có độ phức tạp chính xác theo thời gian lớn. Hơn nữa, đệ quy thường có thể chậm hơn (tùy thuộc vào việc thực hiện ngôn ngữ), vì mỗi lệnh gọi đệ quy yêu cầu tạo khung ngăn xếp mới, trong khi việc lặp lại chỉ yêu cầu một nhánh / so sánh. Các cuộc gọi chức năng thường rẻ, nhưng chúng không miễn phí.
dckrooney

2
@TravisPessetto Tôi đã thấy 3 ngăn xếp tràn trong 6 tháng qua trong khi phát triển các ứng dụng C # do các tham chiếu đối tượng đệ quy hoặc theo chu kỳ. Điều buồn cười là nó sẽ sụp đổ và bạn không biết điều gì đã đánh bạn. Khi bạn nhìn thấy các vòng lặp lồng nhau, bạn biết rằng điều gì đó xấu có thể xảy ra và ngoại lệ về chỉ số sai cho một cái gì đó có thể dễ dàng nhìn thấy.
Mateusz

2
@Mateusz cũng vậy, các ngôn ngữ như Java cho phép bạn bắt gặp lỗi tràn ngăn xếp. Điều này với một dấu vết ngăn xếp sẽ cho phép bạn xem những gì đã xảy ra. Tôi không có nhiều kinh nghiệm, nhưng lần duy nhất tôi thấy lỗi tràn ngăn xếp là trong một PHP có lỗi gây ra đệ quy vô hạn và PHP đã hết bộ nhớ 512MB được gán cho nó. Đệ quy cần phải có giá trị kết thúc cuối cùng, nó không tốt cho các vòng lặp vô hạn. Giống như mọi thứ trong CS, có một thời gian và một nơi dành cho tất cả mọi thứ.
Travis Pessetto

0

Lái một chiếc xe tải ba mươi tấn thay vì một chiếc xe chở khách nhỏ là một thực tế tồi. Ngoại trừ khi bạn cần vận chuyển 20 hoặc 30 tấn công cụ.

Khi bạn sử dụng một vòng lặp lồng nhau, nó không phải là thực hành xấu. Nó hoàn toàn ngu ngốc, hoặc đó chính xác là những gì cần thiết. Bạn quyết định.

Tuy nhiên, có người phàn nàn về các vòng lặp dán nhãn . Câu trả lời cho điều đó: nếu bạn phải đặt câu hỏi, thì đừng sử dụng nhãn. Nếu bạn biết đủ để tự quyết định, thì bạn tự quyết định.


Nếu bạn biết đủ để tự quyết định, bạn biết đủ để không sử dụng các vòng lặp có nhãn. :-)
user949300

Không. Khi bạn đã được dạy đủ, bạn đã được dạy không sử dụng nhãn. Khi bạn biết đủ, bạn vượt ra ngoài giáo điều và làm những gì đúng.
gnasher729

1
Vấn đề với nhãn là nó hiếm khi cần thiết và nhiều người sử dụng nó sớm để khắc phục các lỗi kiểm soát dòng chảy. Giống như cách mọi người đặt lối ra khắp nơi khi họ điều khiển luồng sai. Chức năng cũng làm cho nó phần lớn dư thừa.
jgmjgm

-1

Không có gì sai hoặc nhất thiết là xấu về các vòng lặp lồng nhau. Tuy nhiên, họ có những cân nhắc và cạm bẫy nhất định.

Các bài báo bạn đã được dẫn đến, có thể nhân danh sự ngắn gọn hoặc do một quá trình tâm lý được gọi là bị cháy, bỏ qua các chi tiết cụ thể.

Bị cháy là khi bạn có trải nghiệm tiêu cực về một cái gì đó với ngụ ý là bạn sau đó tránh nó. Ví dụ, tôi có thể cắt rau bằng một con dao sắc và tự cắt. Sau đó tôi có thể nói rằng những con dao sắc nhọn là xấu, đừng sử dụng chúng để cắt rau để cố gắng làm cho trải nghiệm tồi tệ đó không thể xảy ra nữa. Điều đó rõ ràng rất không thực tế. Trong thực tế bạn chỉ cần cẩn thận. Nếu bạn đang bảo người khác cắt rau thì bạn còn có cảm giác mạnh mẽ hơn về điều này. Nếu tôi hướng dẫn trẻ em cắt rau, tôi sẽ cảm thấy rất mạnh mẽ khi bảo chúng không sử dụng một con dao sắc nhọn đặc biệt là nếu tôi không thể giám sát chúng chặt chẽ.

Vấn đề là trong lập trình là bạn sẽ không đạt được hiệu quả cao nhất nếu bạn luôn thích sự an toàn trước tiên. Trong trường hợp này, những đứa trẻ chỉ có thể cắt rau mềm. Đối mặt với bất cứ điều gì khác và họ sẽ chỉ tạo ra một mớ hỗn độn bằng cách sử dụng một con dao cùn. Điều quan trọng là học cách sử dụng đúng các vòng lặp bao gồm các vòng lặp lồng nhau và bạn không thể làm điều đó nếu chúng bị coi là xấu và bạn không bao giờ thử sử dụng chúng.

Như nhiều câu trả lời ở đây chỉ ra một vòng lặp lồng nhau là một dấu hiệu cho thấy các đặc tính hiệu suất của chương trình của bạn, điều này có thể trở nên tồi tệ hơn theo cấp số nhân mỗi lần lồng. Đó là, O (n), O (n ^ 2), O (n ^ 3) và trên đó bao gồm O (n ^ độ sâu) trong đó độ sâu biểu thị số lượng vòng lặp bạn đã lồng. Khi làm tổ của bạn phát triển, thời gian cần thiết tăng theo cấp số nhân. Vấn đề là ở chỗ, đó không phải là một điều chắc chắn rằng sự phức tạp về thời gian và không gian của bạn sẽ là như vậy (thường là một * b * c nhưng không phải tất cả các vòng lặp có thể chạy mọi lúc) cũng không phải là một điều chắc chắn rằng bạn sẽ có một vấn đề hiệu suất ngay cả khi đó là.

Đối với nhiều người, đặc biệt là sinh viên, nhà văn và giảng viên thẳng thắn, hiếm khi lập trình để kiếm sống hoặc hàng ngày cho các vòng lặp cũng có thể là điều họ không quen và gây ra quá nhiều nhận thức về những cuộc gặp gỡ sớm. Đây là một khía cạnh có vấn đề bởi vì luôn có một đường cong học tập và tránh nó sẽ không hiệu quả trong việc chuyển đổi sinh viên thành lập trình viên.

Các vòng lặp lồng nhau có thể đi hoang dã, đó là chúng có thể kết thúc rất sâu. Nếu tôi đi qua từng châu lục, rồi qua từng quốc gia, rồi qua từng thành phố, rồi qua từng cửa hàng, rồi qua từng kệ, rồi qua từng sản phẩm nếu đó là một lon đậu qua từng hạt đậu và đo kích thước của nó để lấy trung bình thì bạn có thể thấy rằng sẽ làm tổ rất sâu. Bạn sẽ có một kim tự tháp và rất nhiều không gian lãng phí từ lề trái. Bạn thậm chí có thể cuối cùng đi ra khỏi trang.

Đây là một vấn đề sẽ có ý nghĩa hơn trong lịch sử khi màn hình nhỏ và độ phân giải thấp. Trong những trường hợp đó, thậm chí một vài cấp độ làm tổ thực sự có thể chiếm rất nhiều không gian. Đây là một mối quan tâm ít hơn hiện nay khi ngưỡng cao hơn mặc dù nó vẫn có thể gây ra vấn đề nếu có đủ lồng.

Liên quan là lập luận thẩm mỹ. Nhiều người không tìm thấy lồng nhau cho các vòng lặp thẩm mỹ trái ngược với bố cục với sự liên kết phù hợp hơn, điều này có thể hoặc không thể liên kết với những gì mọi người đã quen, theo dõi bằng mắt và các mối quan tâm khác. Tuy nhiên, có vấn đề ở chỗ nó có xu hướng tự củng cố và cuối cùng có thể khiến mã khó đọc hơn khi phá vỡ một khối mã và gói các vòng lặp đằng sau trừu tượng như các hàm cũng có nguy cơ phá vỡ ánh xạ mã theo luồng thực thi.

Có một xu hướng tự nhiên đối với những gì mọi người đã quen. Nếu bạn đang lập trình một cái gì đó theo cách đơn giản nhất thì xác suất không cần lồng là cao nhất, xác suất cần một cấp giảm xuống theo một độ lớn, xác suất cho cấp khác lại giảm xuống. Tần số giảm và về cơ bản có nghĩa là càng làm tổ sâu, các giác quan của con người càng ít được huấn luyện để dự đoán nó.

Liên quan đến điều đó là trong bất kỳ cấu trúc phức tạp nào, có thể xem xét một vòng lặp lồng nhau, thì bạn nên luôn luôn hỏi đó là giải pháp đơn giản nhất có thể vì có tiềm năng cho một giải pháp bị bỏ lỡ cần ít vòng lặp hơn. Điều trớ trêu là một giải pháp lồng nhau thường là cách đơn giản nhất để tạo ra thứ gì đó hoạt động với lượng nỗ lực, độ phức tạp và tải nhận thức tối thiểu. Nó thường tự nhiên để làm tổ cho các vòng lặp. Nếu bạn xem xét ví dụ một trong những câu trả lời ở trên, cách nhanh hơn nhiều so với vòng lặp lồng nhau cũng phức tạp hơn nhiều và bao gồm nhiều mã hơn đáng kể.

Cần phải hết sức cẩn thận vì thường có thể loại bỏ các vòng lặp trừu tượng hoặc làm phẳng chúng với kết quả cuối cùng là một phương pháp chữa trị tồi tệ hơn căn bệnh này, đặc biệt nếu bạn không nhận được sự cải thiện hiệu suất đáng kể và có thể đo được từ nỗ lực.

Mọi người thường gặp phải các vấn đề về hiệu năng liên quan đến các vòng lặp đang bảo máy tính lặp lại một hành động nhiều lần và thường sẽ liên quan đến các tắc nghẽn về hiệu suất. Thật không may, phản ứng với điều này có thể rất hời hợt. Mọi người thường thấy một vòng lặp và thấy một vấn đề về hiệu suất khi không có vòng lặp và sau đó ẩn vòng lặp khỏi tầm nhìn để không có hiệu quả thực sự. Mã "trông" nhanh nhưng đặt nó trên đường, đánh lửa, đặt chân ga và nhìn vào đồng hồ tốc độ và bạn có thể thấy nó vẫn nhanh như một bà già đang đi trên khung hình zimmer của mình.

Kiểu ẩn này tương tự như nếu bạn có mười kẻ lừa đảo trên tuyến đường của bạn. Nếu thay vì có một con đường thẳng đến nơi bạn muốn đi, bạn hãy sắp xếp nó để có một kẻ buôn lậu đằng sau mỗi góc, nó sẽ tạo ảo giác khi bạn bắt đầu hành trình của mình rằng không có kẻ lừa đảo. Xa mặt cách lòng. bạn vẫn sẽ bị lừa mười lần nhưng bây giờ bạn sẽ không thấy nó đến.

Câu trả lời cho câu hỏi của bạn là cả hai, nhưng không có mối quan tâm nào là tuyệt đối. Họ hoàn toàn chủ quan hoặc chỉ khách quan theo ngữ cảnh. Thật không may, đôi khi ý kiến ​​hoàn toàn chủ quan hay đúng hơn chiếm ưu thế và chiếm ưu thế.

Theo nguyên tắc thông thường, nếu nó cần một vòng lặp lồng nhau hoặc có vẻ như là bước rõ ràng tiếp theo, tốt nhất không nên cố tình và chỉ cần làm điều đó. Tuy nhiên nếu có bất kỳ nghi ngờ nào kéo dài thì nên xem lại sau.

Một nguyên tắc nhỏ khác là bạn phải luôn kiểm tra cardinality và tự hỏi mình rằng vòng lặp này sẽ là một vấn đề. Trong ví dụ trước tôi đã đi qua các thành phố. Để thử nghiệm tôi chỉ có thể đi qua mười thành phố nhưng số lượng thành phố tối đa hợp lý để mong đợi sử dụng trong thế giới thực là bao nhiêu? Sau đó tôi có thể nhân số đó với cùng một lục địa. Đó là một quy tắc để luôn luôn cân nhắc với các vòng lặp, đặc biệt là lặp đi lặp lại một lượng động (biến) số lần có thể chuyển thành dòng xuống.

Bất kể luôn luôn làm những gì làm việc đầu tiên. Cách mà bạn thấy một cơ hội để tối ưu hóa, bạn có thể so sánh giải pháp tối ưu hóa của mình với cách dễ nhất để làm việc và xác nhận rằng nó mang lại lợi ích như mong đợi. Bạn cũng có thể mất quá nhiều thời gian để tối ưu hóa quá sớm trước khi các phép đo được thực hiện và điều đó dẫn đến YAGNI hoặc rất nhiều thời gian lãng phí và thời hạn bị bỏ lỡ.


Ví dụ về dao cùn <-> sắc nét không phải là tuyệt vời, vì dao cùn thường nguy hiểm hơn khi cắt. Và O (n) -> O (n ^ 2) -> O (n ^ 3) không trong n, đó là hình học hoặc đa thức .
Caleth

Những con dao buồn tẻ tệ hơn là một chút của một huyền thoại đô thị. Trong thực tế, nó khác nhau và thường đặc trưng cho trường hợp dao cùn đặc biệt không phù hợp thường đòi hỏi nhiều lực và liên quan đến rất nhiều trượt. Mặc dù bạn đúng, có một hạn chế ẩn nhưng cố hữu ở đó, bạn chỉ có thể cắt rau mềm. Tôi sẽ xem xét n ^ độ sâu theo cấp số nhân nhưng bạn không đúng với những ví dụ đó.
jgmjgm

@jgmjgm: n ^ độ sâu là đa thức, độ sâu ^ n là hàm mũ. Nó không thực sự là một vấn đề giải thích.
Roel Schroeven

x ^ y khác với y ^ x? Sai lầm bạn đã làm là bạn không bao giờ không đọc câu trả lời. Bạn đã tham gia theo cấp số nhân và sau đó tham gia các phương trình mà theo cách riêng của họ không theo cấp số nhân. Nếu bạn đọc bạn sẽ thấy tôi đã nói nó tăng theo cấp số nhân cho từng lớp lồng và nếu bạn tự kiểm tra nó, thì thời gian cho (a = 0; a <n; a ++); for (b = 0; b <n ; b ++); for (c = 0; c <n; c ++); khi thêm hoặc xóa các vòng lặp thì bạn sẽ thấy rằng nó thực sự theo cấp số nhân. Bạn sẽ tìm thấy một vòng lặp thực hiện tại n ^ 1, hai vòng thực hiện tại n ^ 2 và ba vòng thực hiện tại n ^ 3. Bạn không hiểu lồng nhau: D. Tập con đá quý theo cấp số nhân.
jgmjgm

Tôi đoán điều này không chứng minh một điểm mà mọi người thực sự đấu tranh với các cấu trúc lồng nhau.
jgmjgm
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.