2.11 Tìm kiếm nhị phân (Binary Search)

  • Cách viết kinh điển của tìm kiếm nhị phân. Cần chú ý 3 điểm:
    1. Điều kiện thoát vòng lặp: chú ý là low <= high, không phải low < high.
    2. Cách tính mid: mid := low + (high-low)>>1
    3. Cách cập nhật lowhigh: low = mid + 1, high = mid - 1.
func binarySearchMatrix(nums []int, target int) int { low, high := 0, len(nums)-1 for low <= high { mid := low + (high-low)>>1 if nums[mid] == target { return mid } else if nums[mid] > target { high = mid - 1 } else { low = mid + 1 } } return -1 }
  • Biến thể của tìm kiếm nhị phân. Có 4 biến thể cơ bản:
    1. Tìm phần tử đầu tiên bằng target, độ phức tạp O(logn)O(log n)
    2. Tìm phần tử cuối cùng bằng target, độ phức tạp O(logn)O(log n)
    3. Tìm phần tử đầu tiên lớn hơn hoặc bằng target, độ phức tạp O(logn)O(log n)
    4. Tìm phần tử cuối cùng nhỏ hơn hoặc bằng target, độ phức tạp O(logn)O(log n)
// Tìm kiếm nhị phân phần tử đầu tiên bằng target, độ phức tạp O(logn) func searchFirstEqualElement(nums []int, target int) int { low, high := 0, len(nums)-1 for low <= high { mid := low + ((high - low) >> 1) if nums[mid] > target { high = mid - 1 } else if nums[mid] < target { low = mid + 1 } else { if (mid == 0) || (nums[mid-1] != target) { // Tìm phần tử đầu tiên bằng target return mid } high = mid - 1 } } return -1 } // Tìm kiếm nhị phân phần tử cuối cùng bằng target, độ phức tạp O(logn) func searchLastEqualElement(nums []int, target int) int { low, high := 0, len(nums)-1 for low <= high { mid := low + ((high - low) >> 1) if nums[mid] > target { high = mid - 1 } else if nums[mid] < target { low = mid + 1 } else { if (mid == len(nums)-1) || (nums[mid+1] != target) { // Tìm phần tử cuối cùng bằng target return mid } low = mid + 1 } } return -1 } // Tìm kiếm nhị phân phần tử đầu tiên >= target, độ phức tạp O(logn) func searchFirstGreaterElement(nums []int, target int) int { low, high := 0, len(nums)-1 for low <= high { mid := low + ((high - low) >> 1) if nums[mid] >= target { if (mid == 0) || (nums[mid-1] < target) { // Tìm phần tử đầu tiên >= target return mid } high = mid - 1 } else { low = mid + 1 } } return -1 } // Tìm kiếm nhị phân phần tử cuối cùng <= target, độ phức tạp O(logn) func searchLastLessElement(nums []int, target int) int { low, high := 0, len(nums)-1 for low <= high { mid := low + ((high - low) >> 1) if nums[mid] <= target { if (mid == len(nums)-1) || (nums[mid+1] > target) { // Tìm phần tử cuối cùng <= target return mid } low = mid + 1 } else { high = mid - 1 } } return -1 }
  • Dùng tìm kiếm nhị phân trong mảng “gần như có thứ tự”. Có thể giải bằng cách kinh điển hoặc các biến thể. Dạng bài hay gặp: tìm đỉnh trong mảng núi, tìm điểm phân chia trong mảng đã sắp xếp bị xoay. Bài 33, 81, 153, 154, 162, 852.
func peakIndexInMountainArray(A []int) int { low, high := 0, len(A)-1 for low < high { mid := low + (high-low)>>1 // Nếu A[mid] > A[mid+1] thì đỉnh nằm bên trái (kể cả mid) => high = mid // Ngược lại đỉnh nằm bên phải => low = mid + 1 if A[mid] > A[mid+1] { high = mid } else { low = mid + 1 } } return low }
  • Dạng bài “tối thiểu hóa giá trị lớn nhất” (max-min). Tìm giá trị lớn nhất nhỏ nhất sao cho thỏa điều kiện. Bài 410, 875, 1011, 1283.
STTTiêu đềLời giảiĐộ khóĐộ phức tạp thời gianĐộ phức tạp bộ nhớYêu thíchTỷ lệ AC (Acceptance)
0004Trung vị của hai mảng đã sắp xếp (Median of Two Sorted Arrays)GoHard36.2%
0033Tìm kiếm trong mảng đã sắp xếp bị xoay (Search in Rotated Sorted Array)GoMedium39.0%
0034Tìm vị trí đầu và cuối của phần tử trong mảng đã sắp xếp (Find First and Last Position of Element in Sorted Array)GoMedium41.9%
0035Vị trí chèn (Search Insert Position)GoEasy43.4%
0069Căn bậc hai (Sqrt(x))GoEasyO(logn)O(log n)O(1)O(1)37.4%
0074Tìm kiếm trong ma trận 2D (Search a 2D Matrix)GoMedium47.7%
0081Tìm kiếm trong mảng đã sắp xếp bị xoay II (Search in Rotated Sorted Array II)GoMedium35.7%
0153Tìm giá trị nhỏ nhất trong mảng đã sắp xếp bị xoay (Find Minimum in Rotated Sorted Array)GoMedium48.9%
0154Tìm giá trị nhỏ nhất trong mảng đã sắp xếp bị xoay II (Find Minimum in Rotated Sorted Array II)GoHard43.5%
0162Tìm phần tử đỉnh (Find Peak Element)GoMedium46.0%
0167Hai tổng II - Mảng đầu vào đã sắp xếp (Two Sum II - Input Array Is Sorted)GoMediumO(n)O(n)O(1)O(1)60.0%
0209Tổng mảng con tối thiểu đạt ngưỡng (Minimum Size Subarray Sum)GoMediumO(n)O(n)O(1)O(1)45.0%
0222Đếm số nút của cây hoàn chỉnh (Count Complete Tree Nodes)GoMediumO(n)O(n)O(1)O(1)60.6%
0240Tìm kiếm trong ma trận 2D II (Search a 2D Matrix II)GoMedium51.0%
0268Số bị thiếu (Missing Number)GoEasy62.6%
0275Chỉ số H II (H-Index II)GoMedium37.5%
0278Phiên bản xấu đầu tiên (First Bad Version)GoEasy43.3%
0287Tìm số bị lặp (Find the Duplicate Number)GoMediumO(n)O(n)O(1)O(1)❤️59.1%
0300Dãy con tăng dần dài nhất (Longest Increasing Subsequence)GoMediumO(nlogn)O(n log n)O(n)O(n)52.2%
0315Đếm số nhỏ hơn ở phía sau (Count of Smaller Numbers After Self)GoHard42.6%
0327Đếm tổng đoạn (Count of Range Sum)GoHard35.8%
0349Giao của hai mảng (Intersection of Two Arrays)GoEasyO(n)O(n)O(n)O(n)70.9%
0350Giao của hai mảng II (Intersection of Two Arrays II)GoEasyO(n)O(n)O(n)O(n)56.0%
0352Luồng dữ liệu như các đoạn rời nhau (Data Stream as Disjoint Intervals)GoHard59.7%
0354Phong bì búp bê Nga (Russian Doll Envelopes)GoHard37.9%
0367Số chính phương hoàn hảo hợp lệ (Valid Perfect Square)GoEasy43.3%
0374Đoán số cao hơn hay thấp hơn (Guess Number Higher or Lower)GoEasy51.9%
0378Phần tử nhỏ thứ K trong ma trận đã sắp xếp (Kth Smallest Element in a Sorted Matrix)GoMedium61.8%
0400Chữ số thứ N (Nth Digit)GoMedium34.1%
0410Chia mảng để tổng lớn nhất nhỏ nhất (Split Array Largest Sum)GoHard53.5%
0436Tìm đoạn bên phải (Find Right Interval)GoMedium50.8%
0441Sắp xếp tiền xu (Arranging Coins)GoEasy46.2%
0456Mẫu 132 (132 Pattern)GoMedium32.4%
0475Máy sưởi (Heaters)GoMedium36.5%
0483Cơ số tốt nhỏ nhất (Smallest Good Base)GoHard38.8%
0493Cặp đảo ngược (Reverse Pairs)GoHard30.9%
0497Điểm ngẫu nhiên trong các hình chữ nhật không chồng lấp (Random Point in Non-overlapping Rectangles)GoMedium39.4%
0528Chọn ngẫu nhiên theo trọng số (Random Pick with Weight)GoMedium46.1%
0532Các cặp K-diff trong mảng (K-diff Pairs in an Array)GoMedium41.2%
0540Phần tử duy nhất trong mảng đã sắp xếp (Single Element in a Sorted Array)GoMedium59.1%
0611Số tam giác hợp lệ (Valid Triangle Number)GoMedium50.6%
0633Tổng của các số chính phương (Sum of Square Numbers)GoMedium34.4%
0658Tìm K phần tử gần nhất (Find K Closest Elements)GoMedium46.8%
0668Số nhỏ thứ K trong bảng nhân (Kth Smallest Number in Multiplication Table)GoHard51.4%
0704Tìm kiếm nhị phân (Binary Search)GoEasy56.1%
0710Chọn ngẫu nhiên với danh sách đen (Random Pick with Blacklist)GoHardO(n)O(n)O(n)O(n)33.5%
0718Độ dài tối đa của mảng con lặp lại (Maximum Length of Repeated Subarray)GoMedium51.3%
0719Tìm khoảng cách cặp nhỏ nhất thứ K (Find K-th Smallest Pair Distance)GoHard36.7%
0729Lịch của tôi I (My Calendar I)GoMedium56.8%
0732Lịch của tôi III (My Calendar III)GoHard71.5%
0744Tìm chữ cái nhỏ nhất lớn hơn mục tiêu (Find Smallest Letter Greater Than Target)GoEasy45.8%
0778Bơi trong nước dâng (Swim in Rising Water)GoHard59.8%
0786Phân số nguyên tố nhỏ thứ K (K-th Smallest Prime Fraction)GoMedium51.7%
0793Kích thước tiền ảnh của hàm số lượng số 0 của giai thừa (Preimage Size of Factorial Zeroes Function)GoHard43.2%
0825Bạn bè có độ tuổi phù hợp (Friends Of Appropriate Ages)GoMedium46.3%
0826Phân công công việc có lợi nhuận cao nhất (Most Profit Assigning Work)GoMedium44.9%
0852Chỉ số đỉnh trong mảng núi (Peak Index in a Mountain Array)GoMedium69.0%
0862Mảng con ngắn nhất có tổng ít nhất K (Shortest Subarray with Sum at Least K)GoHard26.0%
0875Koko ăn chuối (Koko Eating Bananas)GoMedium52.1%
0878Số ma thuật thứ N (Nth Magical Number)GoHard35.4%
0887Siêu thả trứng (Super Egg Drop)GoHard27.1%
0888Đổi kẹo công bằng (Fair Candy Swap)GoEasy60.7%
0911Bầu cử trực tuyến (Online Election)GoMedium52.2%
0981Kho lưu trữ key-value theo thời gian (Time Based Key-Value Store)GoMedium52.2%
1004Số 1 liên tiếp tối đa III (Max Consecutive Ones III)GoMedium63.2%
1011Sức chứa để chuyển hàng trong D ngày (Capacity To Ship Packages Within D Days)GoMedium67.7%
1157Phần tử chiếm đa số trực tuyến trong mảng con (Online Majority Element In Subarray)GoHard41.8%
1170So sánh chuỗi theo tần suất của ký tự nhỏ nhất (Compare Strings by Frequency of the Smallest Character)GoMedium61.5%
1201Số xấu III (Ugly Number III)GoMedium28.9%
1208Lấy các chuỗi con bằng nhau trong ngân sách (Get Equal Substrings Within Budget)GoMedium48.6%
1235Lợi nhuận tối đa khi xếp lịch công việc (Maximum Profit in Job Scheduling)GoHard53.4%
1283Tìm ước số nhỏ nhất với ngưỡng cho trước (Find the Smallest Divisor Given a Threshold)GoMedium56.2%
1300Tổng mảng đã biến đổi gần mục tiêu nhất (Sum of Mutated Array Closest to Target)GoMedium43.6%
1337K hàng yếu nhất trong ma trận (The K Weakest Rows in a Matrix)GoEasy72.1%
1385Tìm giá trị khoảng cách giữa hai mảng (Find the Distance Value Between Two Arrays)GoEasy66.6%
1439Tìm tổng nhỏ thứ K của ma trận có các hàng đã sắp xếp (Find the Kth Smallest Sum of a Matrix With Sorted Rows)GoHard61.4%
1482Số ngày tối thiểu để làm m bó hoa (Minimum Number of Days to Make m Bouquets)GoMedium54.0%
1539Số dương bị thiếu thứ K (Kth Missing Positive Number)GoEasy58.6%
1608Mảng đặc biệt với X phần tử >= X (Special Array With X Elements Greater Than or Equal X)GoEasy60.5%
1631Đường đi với nỗ lực tối thiểu (Path With Minimum Effort)GoMedium55.7%
1648Bán bóng màu giảm giá trị (Sell Diminishing-Valued Colored Balls)GoMedium30.4%
1649Tạo mảng đã sắp xếp qua hướng dẫn (Create Sorted Array through Instructions)GoHard37.5%
1658Số thao tác tối thiểu để giảm X về 0 (Minimum Operations to Reduce X to Zero)GoMedium37.6%
1818Hiệu tổng tuyệt đối nhỏ nhất (Minimum Absolute Sum Difference)GoMedium30.4%
------------------------------------------------------------------------------------------------------------------------------------------------