2012-02-12 67 views
19

Tôi luôn nghĩ sự phức tạp của:Big O, độ phức tạp của việc tổng hợp một chuỗi số n là bao nhiêu?

1 + 2 + 3 + ... + n là O (n) và tổng hai ma trận n bằng n sẽ là O (n^2).

Nhưng hôm nay tôi đọc từ sách giáo khoa, "theo công thức tính tổng n số nguyên đầu tiên, đây là n (n + 1)/2" và sau đó: (1/2) n^2 + (1/2) n, và do đó O (n^2).

Tôi thiếu gì ở đây?

+4

Nó sẽ giúp biết "cái này" là gì. Bạn nói đúng rằng việc bổ sung những thứ n (làm một cái gì đó n lần, mỗi chi phí O (1)) là O (n). Nhưng nếu thay vì thêm 1 + 2 + 3 + v.v, bạn phải * làm * một cái gì đó một lần, và sau đó * làm * một cái gì đó hai lần, và sau đó ba lần, vv, sau đó sau 1 + 2 + 3 .. + n đã được thực hiện bạn đã thực hiện n * (n + 1)/2 điều, là O (n^2). – DSM

+0

Thiếu? Vâng, bạn tìm thấy công thức cho một tổng kết giải thích nó. Bạn cần trợ giúp gì khác? – simchona

+0

@DSM xin lỗi vì sự mơ hồ, "this" đang đề cập đến '1 + 2 + 3 + ... + n' – user1032613

Trả lời

15

Có thể sử dụng big O notation để xác định tốc độ tăng trưởng mọi chức năng.

Trong trường hợp này, có vẻ như cuốn sách không nói về độ phức tạp của thời gian tính toán giá trị, mà còn về bản thân giá trị. Và n(n+1)/2O(n^2).

0

Bạn có công thức không phụ thuộc vào số lượng được thêm vào, vì vậy đây là một thuật toán hằng số không đổi hoặc O (1).

Nếu bạn thêm từng số một tại một thời điểm, thì đó thực sự là O (n). Công thức là một phím tắt; đó là một thuật toán khác, hiệu quả hơn. Phím tắt hoạt động khi các số được thêm vào là tất cả 1 .. n. Nếu bạn có một dãy số không tiếp giáp, thì công thức phím tắt sẽ không hoạt động và bạn sẽ phải quay lại thuật toán từng người một.

Không có điều nào trong số này áp dụng cho ma trận số. Để thêm hai ma trận, nó vẫn là O (n^2) bởi vì bạn đang thêm n^2 cặp riêng biệt của các số để có được một ma trận của n^2 kết quả.

6

n (n + 1)/2 là cách nhanh chóng để tổng hợp chuỗi liên tiếp của số nguyên N (bắt đầu từ 1). Tôi nghĩ rằng bạn đang bối rối một thuật toán với ký hiệu lớn-oh!

Nếu bạn nghĩ về nó như một chức năng thì lớn-oh phức tạp của chức năng này là O (1):

 
public int sum_of_first_n_integers(int n) { 
    return (n * (n+1))/2; 
} 

Việc thực hiện ngây thơ sẽ phải lớn-oh phức tạp của O (n).

public int sum_of_first_n_integers(int n) { 
    int sum = 0; 
    for (int i = 1; i <= n; i++) { 
    sum += n; 
    } 
    return sum; 
} 

Ngay cả khi chỉ xem từng ô của một ma trận n-by-n là O (n^2), vì ma trận có n^2 ô.

+1

Tôi nghĩ điều này không giải thích được thực sự là gì hỏi: "Làm thế nào đến tổng của n số nguyên đầu tiên là O (n^2)"? – svick

0

Có sự khác biệt giữa tổng N số nguyên tùy ý và tổng N là tất cả trong một hàng. Đối với 1 + 2 + 3 + 4 + ... + N, bạn có thể tận dụng thực tế là chúng có thể được chia thành các cặp với một số tiền chung, ví dụ: 1 + N = 2+ (N-1) = 3+ (N-2) = ... = N + 1. Vì vậy, đó là N + 1, N/2 lần. (Nếu có một số lẻ, một trong số đó sẽ được bỏ ghép, nhưng với một chút nỗ lực bạn có thể thấy rằng cùng một công thức giữ trong trường hợp đó.)

Đó không phải là O (N^2). Nó chỉ là một công thức mà sử dụng N^2, thực sự là O (1). O (N^2) có nghĩa là (gần) rằng số bước để tính toán nó phát triển như N^2, đối với N. lớn. Trong trường hợp này, số lượng các bước là như nhau bất kể N.

1

Có thực sự không phải là một vấn đề phức tạp, mà là sự phức tạp của một thuật toán.

Trong trường hợp của bạn, nếu bạn chọn lặp qua tất cả các số, độ phức tạp thực tế là O(n).

Nhưng đó không phải là thuật toán hiệu quả nhất. Một cách hiệu quả hơn là áp dụng công thức - n*(n+1)/2, là hằng số và do đó độ phức tạp là O(1).

7

Bạn khó hiểu về độ phức tạp của thời gian chạy và kích thước (độ phức tạp) của kết quả .

Các thời gian chạy của tổng hợp, một sau khi khác, n số liên tiếp đầu tiên thực sự O ( n) là.

Nhưng sự phức tạp của kết quả, đó là kích thước của “tổng 1-n” = n ( n-1)/2 là O ( n^2).


Nhưng đối với số tùy tiện lớn này là đơn giản từ cách thêm một số lượng lớn mất nhiều thời gian hơn so với cách thêm số lượng nhỏ. Đối với một phân tích thời gian chạy chính xác, bạn thực sự phải xem xét kích thước của kết quả. Tuy nhiên, điều này thường không liên quan đến lập trình, thậm chí không hoàn toàn trong khoa học máy tính lý thuyết. Trong cả hai tên miền, số tổng hợp thường được coi là hoạt động O (1) trừ khi được miền yêu cầu một cách rõ ràng (ví dụ: khi triển khai hoạt động cho thư viện bignum).

+0

"Thời gian chạy của tổng số n liên tiếp đầu tiên thực sự là O (n)" - Không, đây là thời gian chạy của việc thêm các số tùy ý 'n'. Thời gian chạy của tổng số n liên tiếp đầu tiên là thời gian chạy của việc áp dụng công thức 'n * (n + 1)/2', tức là O (1). :) –

+1

@Serge No. "tổng hợp các số liên tiếp * n * đầu tiên" là mô tả * thuật toán *. Tương phản với “tổng số * n * số đầu tiên liên tiếp”. Sau này là có liên quan với kết quả. Trước đây là quan tâm đến phương pháp, tức là tổng hợp các số nguyên một. Tuy nhiên, tôi có thể đã làm rõ hơn ... –

+0

Tất nhiên đó là vấn đề của thuật ngữ. Và vì nó không phải là một mô tả chính thức nhưng chỉ là một cuộc trò chuyện, nó có thể phụ thuộc vào ngữ cảnh. Nhưng trong hầu hết các bối cảnh trong một cuộc hội thoại "tổng hợp các số liên tiếp n đầu tiên" hoặc tương tự không phải là một _algorithm_ - nó là một _task_ (một vấn đề để giải quyết). Không phải bất kỳ việc thực hiện cụ thể nào (thuật toán) để giải quyết nhiệm vụ này mà chính là nhiệm vụ. Và nói về thời gian phức tạp của nhiệm vụ là nói về độ phức tạp thời gian của thuật toán tốt nhất có thể giải quyết nó (trong cuộc hội thoại vì thuật toán chỉ nói đúng có thể có thời gian chạy). –

0

câu trả lời của tổng số chuỗi n tự nhiên có thể được tìm thấy bằng hai cách. cách đầu tiên là bằng cách thêm tất cả các số trong vòng lặp. trong thuật toán trường hợp này là tuyến tính và mã sẽ như thế này

int sum = 0; 
    for (int i = 1; i <= n; i++) { 
    sum += n; 
    } 
return sum; 

tương tự như 1 + 2 + 3 + 4 + ...... + n. trong trường hợp này, độ phức tạp của thuật toán được tính bằng số lần hoạt động bổ sung được thực hiện là O (n).

cách thứ hai để tìm câu trả lời tổng của chuỗi số tự nhiên n là công thức direst n * (n + 1)/2. công thức này sử dụng phép nhân thay vì lặp lại lặp đi lặp lại. phép toán nhân không có độ phức tạp về thời gian tuyến tính. có các thuật toán khác nhau có sẵn cho phép nhân có độ phức tạp thời gian khác nhau, từ O (N^1,45) đến O (N^2). do đó trong trường hợp phức tạp thời gian phép nhân phụ thuộc vào kiến ​​trúc của bộ vi xử lý. nhưng với mục đích phân tích thời gian phức tạp của phép nhân được coi là O (N^2). do đó khi sử dụng cách thứ hai để tìm tổng thì độ phức tạp của thời gian sẽ là O (N^2).

tại đây hoạt động nhân giống không giống như thao tác bổ sung. nếu ai có kiến ​​thức về chủ thể tổ chức máy tính thì anh ta có thể dễ dàng hiểu được hoạt động nội bộ của phép nhân và phép cộng. mạch nhân là phức tạp hơn so với mạch cộng và đòi hỏi thời gian cao hơn nhiều so với mạch cộng để tính toán kết quả. do đó, thời gian phức tạp của tổng của chuỗi không thể không đổi.

+0

Tôi nghĩ rằng bạn đang nhầm lẫn số hoạt động với số chữ số trong một số.Nếu bạn đặt n là số lượng hoạt động, trong trường hợp đầu tiên bạn phải thực hiện n số tiền, thì có nghĩa là complexitiy là O (n). Trong trường hợp thứ hai, chi phí sẽ là O (1) vì bạn đang thực sự thực hiện một số hoạt động đã biết và cố định (3 trong công thức này). –

2

Vì vậy, tôi đoán là điều này thực sự là một tài liệu tham khảo để Cracking the Coding Interview, trong đó có đoạn này trên thực hiện StringBuffer:

Trên mỗi nối, một bản sao mới của chuỗi được tạo ra, và hai chuỗi được sao chép, ký tự theo ký tự. Lần lặp đầu tiên yêu cầu chúng tôi sao chép x ký tự. Lặp lại thứ hai yêu cầu sao chép 2x ký tự. Lần lặp thứ ba yêu cầu 3x và , v.v. Do đó tổng thời gian là O(x + 2x + ... + nx). Điều này làm giảm thành O(xn²). (Tại sao không phải là nó O(xnⁿ)? Bởi vì 1 + 2 + ... n bằng n(n+1)/2 hay, O(n²).)

Đối với bất cứ lý do Tôi thấy điều này một chút bối rối trên đầu tiên của tôi đọc qua, quá. Điều quan trọng cần xem là n nhân với số n hoặc nói cách khác là đang diễn ra và điều đó thống trị. Đây là lý do tại sao cuối cùng là O(xn²) chỉ là O(n²) - số x là loại cá trích màu đỏ.

Các vấn đề liên quan