Bài này mình đọc và dịch từ GeeksForGeeks
Đề bài
Cho 1 mảng kích thước n (n > 0), chứa các số từ 1 đến n-1. Trong mảng có duy nhất 1 phần tử bị lặp lại. Tìm phần tử đó
Hướng xử lý
Có 5 cách
- Cách 1: Dùng 2 vòng for lồng nhau, check nếu thấy phần tử bị lặp lại thì return
- Cách 2: Dùng hashmap để đếm số lần xuất hiện. Thằng nào xuất hiện 2 lần thì in ra.
- Cách 3: Dùng tính chất của tổng: tổng từ 1 đến n là n*(n+1)/2 => tổng từ 1 đến n-1 là (n-1)*n/2. Phần tử bị lặp lại sẽ làm cho tổng của dãy dư ra 1 lượng đúng bằng phần tử đấy => lấy tổng dãy – (tổng từ 1 đến n – 1) là ra
- Cách 4: Dùng tính chất phép XOR: Vì dãy số liên tục từ 1 đến n-1 => (1^2^…^n-1) ^ (arr[0]^arr[1]^…arr[n-1]) sẽ ra đúng phần tử bị dư này.
- Cách 5: Dùng giá trị âm để đánh dấu lại.
Cách 1
Game khá dễ, không có gì để nói. Tuy nhiên độ phức tạp khá cao. Cách dành cho người mới học lập trình thôi.
Cách 2
Cũng dễ. Tạo 1 map đếm số lần xuất hiện. Sau đó for trong map, gặp phần tử nào có số lần xuất hiện > 1 => trả về luôn.
Cách này cũng chưa được tối ưu lắm. Độ phức tạp cũng vẫn cao.
Cách 3
Dùng tính chất phép công. Cách này khá tối ưu
Tổng dãy từ 1 đến n = n * (n+1)/2.
Dãy là các số từ 1 đến n – 1 => tổng = (n-1) * n / 2 (gọi tổng này là tổng 1)
Lại có 1 phần tử xuất hiện 2 lần => tổng mới = tổng 1 + phần tử xuất hiện 2 lần
=> phần tử xuất hiện 2 lần = tổng mới – tổng 1
Cách 4
Cách 4 thú vị nhất. Áp dụng tính chất XOR: a^a = 0
Giả sử dãy là a0, a1,…, an
=> (a0 ^ a1 ^… ^an) ^ (1 ^2^…^n-1) = phần tử bị dư.
Lí do là dãy có tính chất các số từ 1 đến n -1 chỉ xuất hiện 1 lần => khi XOR với gía trị index tương ứng sẽ ra 0 => kết quả lòi ra cuối cùng chính là phần tử xuất hiện 2 lần
Cách 5
Cũng khá hay, chỉ cần dùng 1 vòng lặp và 1 mảng đánh dấu.
Vì tính chất của mảng là các số nguyên không âm và có giá trị từ 1 -> n -1, ta tạo 1 mảng đánh dấu các giá trị gặp
- Tạo mảng arr2 có kích thước n
- Lặp trong arr ban đầu (arr1). Mỗi lần lặp check xem phần tử của arr2 có index = value của arr1 có giá trị âm không.
- Nếu âm => đã xuất hiện rồi
- Nếu không âm => chưa xuất hiện => đánh dấu arr2[item] = -2
Cảm ơn bạn đã đọc bài.
Chúc bạn một ngày làm việc hiệu quả ^^