Gần đây tôi đã tham gia một cuộc phỏng vấn nơi họ hỏi tôi những câu hỏi kỹ thuật. Một là cách bạn sẽ tính số nào trong danh sách độ dài n-1 bị thiếu. Danh sách chứa tất cả các số từ 1 đến n, ngoại trừ i trong đó 1 < = i < = n. Các con số không theo thứ tự. Giải pháp của tôi là cộng tất cả chúng lên, sau đó trừ đi từ việc tính toán các số từ 1 đến n, bằng cách thêm 1 đến n và nhân với n/2 hoặc (n-1)/2 khi thích hợp. Nhưng tôi có cảm giác rằng có một cách tốt hơn để làm điều đó. Giải pháp tối ưu là gì?Cách tối ưu để tính số nguyên nào trong danh sách bị thiếu?
Trả lời
Câu trả lời của bạn là đủ tốt, theo ý kiến của tôi.
Nhưng một số người - có lẽ người phỏng vấn của bạn là một trong số họ - đang lo lắng về tình trạng tràn và như vậy. Trong trường hợp đó, hãy sử dụng XOR thay vì bổ sung.
Để lấy XOR của các số nguyên từ 0 đến n, chỉ cần XOR cùng với các chỉ mục mảng khi bạn lặp lại. Với XOR của các số nguyên từ 0 đến n và XOR của các phần tử mảng, bạn chỉ XOR hai số nguyên tố đó lại với nhau để lấy phần tử còn thiếu.
P.S. Tổng các số nguyên từ 1 đến n luôn là (n + 1) * n/2
Tôi thích lừa XOR của bạn! Tuy nhiên, điều thú vị là bạn không cần phải lo lắng về tràn để giải quyết vấn đề, miễn là bạn biết rằng hệ thống của bạn giữ các bit thấp hơn chính xác của kết quả. trừ tổng số được tính toán (tràn) của các số từ tổng (cũng bị tràn) được tính bằng phương pháp Gaussian, và đáng ngạc nhiên, bạn sẽ nhận được số! Bí quyết sẽ không hoạt động nếu hệ thống luôn kiểm tra tràn số nguyên (ví dụ: Ada). Nó cũng sẽ không hoạt động trên phao nổi, nhưng cũng không phải là thủ thuật XOR. XOR lừa đòi hỏi một vượt qua mảng, trừ khi có một công thức khép kín như một cho tổng hợp. – kkm
@kkm: Phương pháp Gaussian chỉ tránh được vấn đề tràn nếu bạn tính toán (n/2) hoặc (n + 1)/2 trước (tùy theo số nào là số nguyên). Nếu bạn nhân n bằng n + 1, bạn bị mất bit cao và không thể lấy lại nó khi bạn chia cho 2. Nhưng có, khác hơn thế, làm tổng modulo 2^k hoạt động tốt. – Nemo
trong khi lặp qua mảng để tính tổng, bạn có thể kiểm tra xem liệu một số có lặp lại hay không.
Bạn có thể mở rộng trên đó, tôi không thể nhìn thấy những gì bạn có ý nghĩa. – CSturgess
trong câu trả lời của bạn, bạn đã đề cập rằng giải pháp có thể được tính toán thông qua tính tổng và sau đó trừ nó khỏi tổng số. để tính tổng, bạn phải lặp lại suy nghĩ mảng. – KItis
Có, nhưng ý bạn là lặp lại điều gì? Các con số không lặp lại. – CSturgess
Phương pháp của bạn hoàn toàn ổn. Nó là tối ưu cả về không gian và thời gian. Tràn có thể là vấn đề duy nhất với nó.
Một phương pháp khác có thể là sử dụng hàm băm. Tạo một hashSet ban đầu có các giá trị 1-> N. Bây giờ cho mỗi số bạn gặp phải trong danh sách - xóa giá trị đó khỏi hashSet. Cuối cùng, giá trị còn lại trong hashSet là giá trị bị thiếu.
Phương pháp này là O (N) về thời gian và không gian phức tạp. Phương pháp của bạn (chặn tràn) là O (N) trong thời gian và O (1) phức tạp. Yếu tố 'n' được thêm vào cho không gian là chi phí để loại bỏ tràn.
giải pháp của bạn là khá nhiều tối ưu với một thay đổi, như @Nemo chỉ ra tổng của các số nguyên từ 1 đến n luôn là (n+1) * n/2
Nó cũng có giá trị chỉ ra rằng cách tiếp cận của bạn là multi-thread có khả năng (và might phù hợp với các giá trị rất lớn của N), chia mảng thành từng phần, sau đó lấy tổng của mỗi phần mảng trong một chuỗi, sau đó thêm các phần tiền đó. Nó phụ thuộc vào chi phí của luồng được so sánh với việc thêm số vào một mảng.
Nếu bạn lo lắng về việc tràn và giá trị luôn luôn là int32 (như hầu hết các giá trị .Length
bao gồm mảng) thì chỉ lưu trữ tổng dưới dạng int64, tổng của tất cả các giá trị nguyên dương (((long)int.MaxValue) +1L) * (int.MaxValue/2) = 2305843007066210304
. trong một int64 với .MaxValue = 9223372036854775807
.
Câu trả lời khác như được đề cập bởi những người khác là XOR từng mục và giữ một XOR đang chạy, nhưng sau đó bạn cần phải tính toán công thức để đạt được tổng XOR dự kiến trong thời gian O(1)
.
Rất có thể người phỏng vấn đang tìm cách xem bạn có nhận được giải pháp O(N)
với bộ nhớ O(1)
(câu trả lời của bạn) thay vì sắp xếp mảng và chậm hơn nhiều cho các giá trị rất lớn là N
.
Để cải thiện hơn nữa giải pháp của bạn trong mã, sẽ sử dụng con trỏ để truy cập mảng thay vì giá trị chỉ mục (nếu mã của bạn là C# sẽ là một cải tiến hợp lý).
- 1. Tối ưu hóa danh sách đệ quy Haskell
- 2. Làm cách nào để tính chiều rộng titleView tối ưu?
- 3. Python: cách tối ưu để thêm vào từ điển có giá trị danh sách
- 4. Tối ưu hóa nhân modulo số nguyên tố nhỏ
- 5. Tối ưu hóa danh sách lọc bằng Python 2.7
- 6. chuyển đổi danh sách chuỗi thành danh sách số nguyên
- 7. Danh sách thành số nguyên hoặc gấp đôi trong R
- 8. Chèn ngày bị thiếu trong khi giữ thứ tự ngày trong danh sách python
- 9. Cách tối ưu hóa chỉ số solr
- 10. Làm cách nào để chuyển đổi chuỗi thành danh sách các số nguyên trong Haskell
- 11. Truyền danh sách số nguyên vào python
- 12. Chuyển đổi danh sách các danh sách thành danh sách các số nguyên
- 13. Tìm số nguyên 32 bit bị thiếu trong một mảng chưa phân loại chứa tối đa 4 tỷ ints
- 14. Làm thế nào để chuyển đổi chuỗi số thành số nguyên trong một danh sách?
- 15. Giải pháp cho một số tính năng WPF bị thiếu trong Silverlight
- 16. biến SQL để giữ danh sách các số nguyên
- 17. Tối ưu hóa JaxRS/Jackson để loại trừ null, trống Danh sách, mảng
- 18. Tối ưu hóa tính toán một phần trong Haskell
- 19. Danh sách các lựa chọn thay thế cho các chức năng bị thiếu trong OpenGLES
- 20. Tối ưu hóa Mã số
- 21. tệp svn-base nguyên sơ bị thiếu
- 22. Tìm chỉ số của nguyên tố tối đa từ danh sách Python
- 23. Chuyển đổi số thành danh sách số nguyên
- 24. Làm cách nào để thực hiện giao điểm danh sách số nguyên trong khi vẫn giữ nguyên bản sao?
- 25. chuyển đổi số nguyên thành danh sách trong python
- 26. Sắp xếp danh sách con trong danh sách số nguyên Python
- 27. C++ 11 thông số tối ưu qua
- 28. Làm cách nào để chuyển danh sách các số nguyên đến một hành động MVC?
- 29. Lọc tối đa 20 giá trị từ danh sách các số nguyên
- 30. Làm cách nào để chuyển danh sách dưới dạng danh sách các đối số trong vợt?
Hãy xem xét phạm vi sẽ trông như thế nào nếu bạn sắp xếp nó. Nếu bạn có thể nghĩ ra một từ bắt đầu bằng chữ "P" bạn đang đi đúng hướng. –
Nhưng sẽ không phân loại nó đòi hỏi nhiều công việc hơn so với phương pháp của tôi? (Và tôi xin lỗi, tôi không thể nghĩ ra từ) – CSturgess
Tôi không nói rằng phân loại là câu trả lời, chỉ cần bạn nên suy nghĩ về những gì nó sẽ như thế nào. Chữ thứ hai là "e". –