Cùng giải leetcode! Bài 219. Contains Duplicate II

18 tháng 04, 2023 - 683 lượt xem

Tác giả: Lê Trung Kiên lớp java 08
Email: lekien.2803.cg@gmail.com
SĐT: 0942096947
Link bài toán: https://leetcode.com/problems/contains-duplicate-ii/

1. Mở đầu

Xin chào các bạn, mình viết ra bài viết này để chia sẻ phương pháp giải cũng như tư duy của mình về bài toán này của leetcode. Phương pháp của mình có thể không phải là tối ưu nhất, tuy nhiên mình sẽ phân tích, chia nhỏ bài toán ra thành các module nhỏ hơn để dễ giải quyết cũng như giúp các bạn hiểu được các yêu cầu mà bài toán đưa ra.

2. Đề bài

Cho mảng số nguyên nums và số nguyên k. Trả về kết quả là true nếu có hai con trỏ khác nhau ij thỏa mãn nums[i] == nums[j]abs(i - j) <= k.
Điều kiện:

  • 1 <= nums.length <= 10^5.
  • -10^9 <= nums[i] <= 10^9.
  • 0 <= k <= 105.

Bài toán minh họa 1:

Input: nums = [1,2,3,1], k = 3
Output: true

Bài toán minh họa 2:

Input: nums = [1,0,1,1], k = 1
Output: true

Bài toán minh họa 3:

Input: nums = [1,2,3,1,2,3], k = 2
Output: false

3. Phân tích

Lại là một bài tìm số trùng lặp trong mảng, nhưng phiên bản này khó hơn một chút. Còn phiên bản dễ hơn thì tôi đã có bài viết tại đây.
Bài này chúng ta vẫn có thể sử dụng thuật toán Brute Force (thuật toán vét cạn) để xử lý, tuy nhiên như tôi đã nói ở bài trên, độ phức tạp sẽ lên đến O(n^2) và điều này không tốt một chút nào, nên chúng ta sẽ không giải bằng kỹ thuật này.
Ố kề. Bài này nếu như chỉ tìm ra cặp số giống nhau như bài 217 thì không khó. Vấn đề ở đây là nó phải thỏa mãn điều kiện nữa là khoảng cách giữa hai con trỏ ij phải nhỏ hơn hoặc bằng số nguyên k.
Như ở ví dụ 1, chúng ta có hai số giống nhau là 1 và chúng ở vị trí 03, mà |0 - 3| = 3 cũng chính bằng k, nên kết quả trả về true:
leetcode-219-1

Tuy nhiên ở ví dụ 3, mặc dù cũng có cặp số giống nhau, nhưng lại không thỏa mãn điều kiện, nên kết quả trả về false:
leetcode-219-2

Vậy nên, ở bài này chúng ta sẽ sử dụng cấu trúc dữ liệu HashMap để giải quyết bài toán. Với key chính là phần tử trong nums, còn value là vị trí hiện tại của phần tử đó trong mảng. Tại sao lại là vị trí hiện tại? Nếu như phần tử đó chưa có trong map, ta sẽ thêm nó vào; còn nếu như phần tử đó có rồi, ta sẽ phải đồng thời kiểm tra xem hiệu giữa index hiện tại và index đã được lưu trong value có nhỏ hơn hoặc bằng k hay không? Nếu có thì trả về true còn không thì false.

4. Code bằng cơm

Đầu tiên chúng ta cần tạo mới một HashMap.
leetcode-219-3

Tiếp theo chúng ta sẽ một vòng lặp for để duyệt qua mảng nums. Khi này chúng ta sẽ làm hai công việc một lúc, ấy là kiểm tra xem nếu phần tử đó có trong map hay chưa? Nếu chưa có thì ta thêm vào map, còn chưa có thì ta sẽ phải kiểm tra tiếp. Ta kiểm tra xem, với cái phần tử này đã có trong map rồi, thì cái index đã lưu trong value ấy với cái index hiện tại trừ đi nhau liệu có nhỏ hơn hoặc bằng k hay không?
leetcode-219-4

Done! Chúng ta tới bước tiếp theo thôi!

5. Code bằng máy

Code của chúng ta sẽ như sau:

 public boolean containsNearbyDuplicate(int[] nums, int k) {

     Map<Integer, Integer> map = new HashMap<>();
     for (int i = 0; i < nums.length; i++) {
         if (map.containsKey(nums[i]) && Math.abs(map.get(nums[i]) - i) <= k) {
             return true;
         }
         map.put(nums[i], i);
     }

     return false;
 }

6. Kết thúc

Qua bài viết này, mình đã chia sẻ cho các bạn cách mình tư duy khi giải bài tập trên leetcode. Hi vọng bài viết giúp ích cho các bạn trong cách tư duy để giải các bài tập khác. Xin cám ơn các bạn đã dành thời gian đọc và theo dõi. Peace!!!

Bình luận

avatar
Vi Văn Trung 2023-04-19 08:55:34.007697 +0000 UTC

gfjhfuyg

Avatar
* Vui lòng trước khi bình luận.
Ảnh đại diện
  0 Thích
0