Tại sao so sánh các chuỗi 0 (n), nhưng so sánh các số 0 (1)?


8

Tôi hiểu rằng để so sánh hai chuỗi cho đẳng thức, trình thông dịch phải lặp qua cả hai chuỗi và so sánh từng ký tự.

Điều đó sẽ làm cho độ phức tạp thời gian 0(n)trong đó nđộ dài của chuỗi ngắn nhất.

Tuy nhiên, so sánh hai số cho bình đẳng là 0(1).

Tại sao vậy? Người phiên dịch sẽ không lặp đi lặp lại qua mỗi số để kiểm tra sự bằng nhau chứ?


1
Có gì để lặp lại trên một số? Một số chỉ là giá trị: 2ví dụ, không 3. Đó là nó. Tương tự 123là không 124. Chuỗi là một tập hợp các ký tự "abc"khác nhau "abd"nhưng bạn phải kiểm tra từng ký tự.
VLAZ

2
Máy tính có các hoạt động nội tại so sánh toàn bộ giá trị số một cách nhanh chóng.
Mũi nhọn

5
Nếu bạn đang làm việc trong một ngôn ngữ như Erlang với số nguyên có độ chính xác vô hạn, thì phép so sánh số thực sự là O (n)
Pointy

1
Ngoài ra, thay vì "thông qua mọi số", bạn có thể có nghĩa là "thông qua mọi chữ số"
Pointy

1
@Pointy: Đó sẽ là O (log (n)), vì độ dài của số n tỷ lệ thuận với log (n).
Nyos

Câu trả lời:


10

Số trong máy tính thường được xử lý trong các đơn vị kích thước cố định. Một intcó thể là 32 hoặc 64 bit trong bất kỳ ngôn ngữ cụ thể và / hoặc kết hợp trình biên dịch / nền tảng nào, nhưng nó sẽ không bao giờ có độ dài thay đổi.

Do đó, bạn có một số bit cố định để so sánh khi so sánh số. Thật dễ dàng để xây dựng một mạch phần cứng so sánh nhiều bit cùng một lúc (nghĩa là "một hành động").

Mặt khác, các chuỗi có độ dài thay đổi, vì vậy bạn chỉ nói "chuỗi" không cho bạn biết bạn sẽ phải so sánh bao nhiêu bit.

những trường hợp ngoại lệ tuy nhiên, như có số chiều dài thay đổi, thường được gọi là một cái gì đó giống như BigIntegerhoặc BigDecimalsẽ cư xử rất giống với Stringso sánh vì nó có thể kết thúc là O (n) để so sánh hai BigDecimalgiá trị cho sự bình đẳng (trong đó n là chiều dài của BigDecimals , không phải một trong hai giá trị số của chúng).


Sự hiện diện của thẻ javascript có tạo ra sự khác biệt nào cho câu trả lời này không? Trong javascript họ có các toán tử =====toán tử, nơi ==toán tử cho phép thực hiện một cái gì 1 == '1'đó sẽ đánh giá là đúng, nhưng các tài liệu rất mơ hồ về việc mỗi toán hạng được chuyển đổi thành gì trước khi so sánh được thực hiện. Vì vậy, trong trường hợp này, nếu chúng được chuyển đổi thành chuỗi, việc so sánh có thể không thực hiện so sánh số nguyên mà là so sánh chuỗi
smac89

@ smac89: JavaScript sử dụng một loại số duy nhất là số dấu phẩy động có kích thước cố định, do đó, không có sự khác biệt nào để so sánh. Có, trước khi so sánh, bạn có thể cần thực hiện một số chuyển đổi có thể hoặc không thể thực hiện được trong O (n), nhưng IMO không thực sự là một phần của so sánh.
Joachim Sauer

3
@ smac89 " nhưng các tài liệu rất mơ hồ về việc mỗi toán hạng được chuyển đổi thành gì trước khi so sánh được thực hiện " các tài liệu RẤT rõ ràng về cách so sánh giữa các loại khác nhau.
VLAZ

@VLAZ cảm ơn vì đường link. Vì vậy, có vẻ như chuỗi được chuyển đổi thành số, vẫn còn O(n)và đó là quan điểm của tôi khi đưa ra điều này đặc biệt là khi nó có liên quan đến javascript.
smac89

@JoachimSauer JavaScript uses a single numberic typekhông đúng. BigInt hiện là loại tích hợp sẵn trong JavaScript
phuclv

4

Thông thường các chương trình biểu diễn các số dưới dạng cấu trúc dữ liệu có kích thước cố định (giá trị nhị phân, đó là lý do tại sao bạn có thể thấy kích thước của chúng được mô tả bằng bit). Có kích thước cố định, các phép so sánh sẽ mất một lượng thời gian không đổi và là O (1), đây là một trong những lợi ích của việc biểu diễn như vậy. Một nhược điểm sẽ là một giới hạn về phạm vi của các giá trị có thể được biểu diễn.

Một đại diện thay thế nâng cao giới hạn này, cho phép phạm vi số lớn tùy ý, do đó sẽ không còn được cố định về kích thước và không còn là O (1) để so sánh.


0

Chuỗi

So sánh chuỗi thường là quét tuyến tính các ký tự, trả về false ở chỉ mục đầu tiên nơi các ký tự không khớp.

Độ phức tạp thời gian là O (N) và thời gian thực tế phụ thuộc vào số lượng ký tự cần được quét trước khi sự khác biệt xuất hiện theo thống kê. Không có câu trả lời đơn giản, nhưng câu trả lời vẫn rõ ràng ;-)

Số

nếu hai số nguyên bằng nhau, không thể biết nếu không so sánh tất cả các bit của chúng. Vì vậy, trong trường hợp đẳng thức, thời gian cần thiết tỷ lệ thuận với số bit (tỷ lệ với log (abs (N)) nếu N là một trong các phép so sánh).

Nếu thực tế chúng không bằng nhau, có nhiều trường hợp, tất cả đều liên quan đến nội bộ thực hiện. Số nguyên dài được lưu trữ dưới dạng vectơ "chữ số" trong cơ sở lũy thừa 2. Nếu các vectơ không có cùng độ dài, thì số nguyên không bằng nhau và điều đó sẽ mất thời gian không đổi.

Nhưng nếu chúng có cùng độ dài, thì "các chữ số" phải được so sánh cho đến khi tìm thấy cặp không khớp đầu tiên (nếu có). Điều đó cần thời gian tỷ lệ thuận với số chữ số cần được so sánh.


Chữ số không được so sánh. Các bit được so sánh. Và các bit được so sánh như một nhóm nguyên tử. Không có máy tính nào so sánh bit 1, rồi bit 2, rồi bit 3, rồi bit 4. Tùy thuộc vào hướng dẫn cụ thể được sử dụng và khả năng của bộ xử lý, họ so sánh 8 bit, hoặc 16 bit, hoặc 32 bit, hoặc 64 bit, v.v. , như một hoạt động duy nhất. Không so sánh cấp độ chữ số hoặc tương đương, nó nằm trên ranh giới byte / từ.
Ghedipunk

0

Nói chung, chúng tôi chỉ sử dụng ký hiệu big-O khi n có thể tăng lên các giá trị lớn một cách khó hiểu, bởi vì ký hiệu big-O mô tả cách thời gian thực hiện tăng lên khi đầu vào tăng. Chẳng hạn, khi sắp xếp một danh sách, hầu hết các thuật toán tốt nhất đều sắp xếp O(n log n)- có nghĩa là và chỉ có nghĩa là khi danh sách đủ dài, thời gian cần thiết để sắp xếp nó tỷ lệ thuận với nó n log n. Khi danh sách không đủ dài, các yếu tố khác (ví dụ, bất kỳ lúc nào thuật toán của bạn có thể mất để phân bổ thêm dung lượng), trở nên quan trọng và thậm chí có thể chiếm thời gian chạy.

Với các chuỗi JavaScript, nthực sự có thể có kích thước lớn tùy ý *, vì vậy chúng tôi nói việc so sánh cần có O(n)thời gian. Nhưng với các số JavaScript (là các số dấu phẩy động có độ chính xác kép của IEEE 754 ), ncó giới hạn tối đa là 64 - 1 cho một bit dấu, 11 cho số mũ và 53 cho các chữ số có nghĩa **. Do đó, chúng tôi biết chính xác sẽ mất bao lâu để so sánh số xảy ra và các hệ thống tốt nhất chúng tôi có để so sánh các số có kích thước chính xác đó ít nhiều chạy giống nhau bất kể có bao nhiêu trong số 64 chữ số đó mỗi số thực sự đã - do đó, so sánh các số này trong JavaScript được xem xét O(1).


* Về mặt kỹ thuật, có giới hạn trên vì RAM có thể hết. Tuy nhiên, ngôn ngữ không chỉ định kích thước tối đa cho chuỗi và O(n)phần so sánh chuỗi chi phối tốt thời gian thực hiện trước khi điều đó xảy ra.

** Nhân tiện, điều này không có nghĩa là số trong JavaScript không thể tăng vô hạn. Qua một điểm nhất định, họ bắt đầu ném đi các chữ số nhỏ hơn (ví dụ: các số trên 2 ^ 53 chỉ có thể là số chẵn và các số trên 2 ^ 54 chỉ có thể chia hết cho 4) và khi số đó đủ lớn, nó sẽ làm tròn đến vô cùng. Ngược lại, nếu bạn chia một số nhiều lần để làm cho nó cực kỳ nhỏ, cuối cùng nó sẽ làm tròn xuống không.

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.