Tìm kiếm trên mảng đã sắp xếp và xoay - LeetCode 81 - game nhà cái tặng tiền cược miễn phí

| Jan 9, 2025 min read

2019 năm 07 tháng Loc88 Club Game Bài Tặng Code 29 ngày Máy tính

1. Mô tả bài toán

Giả sử rằng một mảng được sắp xếp theo thứ tự tăng dần đã bị xoay tại một điểm chuyển nào đó mà bạn không biết trước (ví dụ: mảng [0, 0, 1, 2, 2, 5, 6] có thể trở thành [2, 5, 6, 0, 0, 1, 2]).

Bạn cần tìm kiếm giá trị target trong mảng này. Nếu tìm thấy, hãy trả về true; nếu không tìm thấy, hãy trả về false.

Ví dụ 1:

  • Đầu vào: nums = [2, 5, 6, 0, 0, 1, 2], target = 0
  • Đầu ra: true

Ví dụ 2:

  • Đầu vào: nums = [2, 5, 6, 0, 0, 1, 2], target = 3
  • Đầu ra: false

Lưu ý: a) Đây là phiên bản biến thể của bài toán “Tìm kiếm trên mảng đã xoay và sắp xếp”, trong đó mảng nums có thể chứa các phần tử trùng lặp. b) Liệu sự hiện diện của các phần tử trùng lặp có ảnh hưởng đến độ phức tạp thời gian chạy hay không? Tại sao?

Nguồn gốc bài toán: LeetCode

2. Cách tiếp cận giải quyết

Chúng ta sẽ áp dụng thuật toán tìm kiếm nhị phân để tối ưu hóa quá trình tìm kiếm. Các bước cụ 22win casino thể như sau:

  • Ban đầu, biến begin và end lần lượt chỉ đến phần tử đầu tiên và cuối cùng của mảng.
  • Khi begin <= end, thực hiện vòng lặp với các thao tác sau:

a) Trước mỗi lần lặp, kiểm tra xem phần tử đầu tiên và phần tử cuối cùng có giống nhau không. Nếu có, loại bỏ các phần tử trùng lặp từ phần đầu của mảng để tránh trường hợp các phần tử này gây nhiễu cho việc xác định vị trí của mid.

b) Tính toán giá trị mid giữa begin và end. Nếu phần tử tại vị trí mid bằng với target, trả về true ngay lập tức.

c) Nếu toàn bộ mảng vẫn đang ở trạng thái tăng dần, áp dụng tìm kiếm nhị phân thông thường.

d) Trong trường hợp mảng đã bị xoay, mảng sẽ bao gồm hai đoạn con: đoạn trước lớn hơn (tăng dần) và đoạn sau nhỏ hơn (cũng tăng dần). Cần so sánh target với phần tử tại vị trí mid và xác định nó thuộc đoạn trước hay đoạn sau để f8bet72 quyết định cách chia nửa mảng phù hợp.

3. Mã nguồn Golang

func search(nums []int, target int) bool {
    begin, end := 0, len(nums)-1
    
    for begin <= end {
        // Xử lý khi phần tử đầu tiên và cuối cùng bằng nhau
        if nums[begin] == nums[end] {
            if target == nums[begin] {
                return true
            }
            // Loại bỏ các phần tử trùng lặp từ đầu
            for begin < end && nums[begin] == nums[end] {
                begin++
                continue
            }
        }
        
        mid := (begin + end) / 2
        
        if target == nums[mid] {
            return true
        }
        
        // Trường hợp mảng hoàn toàn tăng dần
        if nums[begin] < nums[end] {
            if target > nums[mid] {
                begin = mid + 1
            } else {
                end = mid - 1
            }
            continue
        }
        
        // Trường hợp mảng đã bị xoay
        if target > nums[mid] {
            if nums[mid] >= nums[begin] {
                begin = mid + 1
            } else {
                if target >= nums[begin] {
                    end = mid - 1
                } else {
                    begin = mid + 1
                }
            }
        } else {
            if nums[mid] >= nums[begin] {
                if target >= nums[begin] {
                    end = mid - 1
                } else {
                    begin = mid + 1
                }
            } else {
                end = mid - 1
            }
        }
    }
    
    return false
}

#Golang #ThuậtToán