01/10/2018, 16:32
Tìm số nguyên dương nhỏ nhất không chứa trong mảng đã cho
Tìm số nguyên dương nhỏ nhất > 0 không chứa trong mảng đã cho
ví dụ cho mảng int[] A = { 1, 3, 6, 4, 1, 2 }; thì phải ouput ra số 5
Mình không thông minh nên chỉ nghĩ được là sẽ chạy số n từ 1 đến số lớn nhất của mảng, lặp vòng for xem con số n đó có bằng với phần tử trong mảng hay không, nếu mà bằng thì break, còn không thì in ra số đó.
Như vậy có đúng ko ạ, ai có thể chia sẻ cho mình thuật toán khác với được không ạ.
Xin cảm ơn.
Bài liên quan
Mình nghĩ là đầu tiên thì nên sắp xếp cái mảng đó theo thứ tự từ nhỏ đến lớn.
Sau đó cho một vòng lặp chạy từ đầu đến cuối mảng đã sắp xếp, kiểm tra xem nếu phần tử trước cộng với 1 mà khác phần tử sau
if (arr[i]+1)!=arr[i+1]
thì sẽ trả vềarr[i]+1
và break ra khỏi vòng lặp.Cảm ơn thuật toán của bạn. hihi
Vậy trường hơp mình cho dãy int[] A = { -1,-2 }; thì output ra 0 hay mấy vậy bạn?
nếu vậy thì ta sẽ thêm điều kiện lớn hơn 0 cho arr[i+1].
if ((arr[i]+1)!=arr[i+1]) &&(arr[i]+1>0)
và thêm return 1 ở sau vòng lặp.khi nó chạy hết mảng mà không có giá trị nào được trả về thì sẽ trả về 1
Phải ra 1 chứ
Đúng ra là chạy thêm hai cái (while <= 0) nữa thì có khi được o(n) thu hẹp từ hai đầu.
Ra 1 vì đề yêu cầu >0 nhưng mà mình nghĩ bạn ấy nói vậy chỉnh xíu là được rồi
Mảng có phải sẽ gặp vấn đề khi int[] A = { 1, 3, 6, 4, 1, 2 }; không nhỉ? có 2 giá trị 1 thì lập tức return về 2 mất rồi hihi
Mình viết vầy thi test 3 trường hợp cho kết quả đúng, chưa biết t/h ngoại lệ nào để tes cho nó sai
Ban đầu mình cũng nghĩ là rà min nhưng nó là O(n^2) nên mình bỏ.
Cách của bạn là O(max*n), không hay đâu.
Đầu tiên, vẫn phải sort lại mảng.
Để ý tính chất sau:
Nếu số bé nhất mảng > 1 -> đáp số là 1.
Nếu số lớn nhất mảng < 1 -> đáp số là 1.
Nếu 2 trường hợp trên không xảy ra, đến đây có 2 cách giải quyết:
for từ 1 đến số lớn nhất + 1 xem có số nào không thuộc mảng hay không. Kiểm tra 1 số có thuộc mảng hay không bằng cách tìm kiếm nhị phân. Độ phức tạp tổng là
O(n log n + max(a[]) log n)
Dùng cách này, độ phức tạp tổng là
O(n log n)
:Tuỳ bạn chọn.
Không cần thiết cứ bổ sung
if(a[i] == a[i-1]) continue;
thôi. Và câu lệnh này thể hiện rất rõ ý đồ của người viết.Điều kiện > 0 của câu if có thể bỏ, vì ai giới hạn số for đâu
Ghi chú: @thớt
break;
là thoát vòng lặp ngay vàcontinue;
là chuyển qua lần lặp tiếp theo.Theo mình nghĩ là như thế này:
B1: Tạo 1 ArrayList rồi add tất cả phần tử trong list vào (Lọc luôn số âm)
B2: Chạy 1 hàm for từ đầu đến cuối ArrayList đó, xong dùng luôn hàm .contains() của ArrayList luôn
B3: Nếu là Failse thì sẽ là số cần tìm.
B4; Với thuật toán này sẽ có 2 số hợp lệ, thì lấy số bé hơn
Mảng có n phần tử thì tối đa cũng chỉ chứa được n số nguyên dương liên tiếp -> như vậy kết quả thuộc [1,n+1]
Dùng 1 mảng đánh dấu kiểm tra những số nào có trong khoảng đó, sau đó tìm số nhỏ nhất chưa được đánh dấu.
Thì đáp số là số 1 .
Oh :(( Mình nhầm là trong khoảng các số ở mảng xin lỗi bạn
Thật ra bài này làm đc trong O(N) với N ~ 1e6 bằng cách dùng mảng đánh dấu những phần tử dương <= N xuất hiện trong bảng, dễ chứng minh chắc chắn sẽ có số nguyên dương trong [1,N+1] chưa xuất hiện trong mảng.
À anh gió chứng minh rồi :v
Tạo mảng boolean n phần tử, n là số phần tử lớn nhất. Rồi for hết mảng nta cho. Mỗi vong for gặp số nào >0 thì A[i]= true. Rồi for mảng A . Tìm giá trị false đầu tiên .in nó ra là đc. 2 vòng lặp đơn là xong.
Cách của bạn chính là cách của bạn
@Gio
rồi.Đây là cách mà mình làm :)) thấy vẫn chưa tối ưu lắm :))
Bài cũng hay :D, lâu lâu code thử tí, không biết đúng yêu cầu chưa.
O(CONSTANT*n) về tổng thể sẽ thấp hơn O(n^2)