704 이진 검색

704. 이진 검색

링크

n 요소와 대상 값 대상이 있는 정렬된(오름차순) 정수 배열 nums가 주어지면 nums에서 대상을 검색하는 함수를 작성하고 대상 값이 존재하면 아래 첨자를 반환하고 그렇지 않으면 -1을 반환합니다.

예 1:

输入: nums = [-1,0,3,5,9,12], target = 9     
输出: 4       
解释: 9 出现在 nums 中并且下标为 4     

예 2:

输入: nums = [-1,0,3,5,9,12], target = 2     
输出: -1        
解释: 2 不存在 nums 中因此返回 -1        

힌트:

  • nums의 모든 요소는 고유하다고 가정할 수 있습니다.
  • n은 [1, 10000] 사이입니다.
  • nums의 각 요소는 [-9999, 9999] 범위에 있습니다.

생각의 기차

정렬된 비반복 배열 에서 목표 값을 찾는 문제 로 이진 검색을 고려할 수 있다.

제목에서 언급한 바와 같이 nums의 모든 요소는 반복되지 않고 nums는 오름차순으로 정렬되므로 이진 검색 방법을 고려할 수 있습니다.

이진 탐색의 논리는 비교적 단순하지만 경계 조건 처리에서 실수하기 쉽습니다. 예를 들어 우리가 쓰는 while(left < right)것과 while(left <= right)그에 상응하는 처리 방식이 완전히 다릅니다.

간단한 예를 들어 배열에 5라는 요소가 하나만 있고 대상 값 target도 . while(left < right)쓰기 방식을 사용하는 경우 right1로 초기화하고 left0으로 초기화해야 합니다. 그리고 while(left <= right)표기법을 , left및 를 0으로 초기화 right해야 합니다 . 따라서 두 쓰기 방법의 차이점은 경계 조건 처리 에 있습니다 .

따라서 경계조건의 처리방법에 따라 이진탐색은 다음과 같은 두 가지 작성방법이 있다.

첫 번째 글쓰기 방법

배열 요소가 [1,2,3,4,5,6,7], 라고 가정하고 표기법을target = 3 사용하여 이진 정렬을 구현합니다.while(left < right)

이런 식으로 , left = 0,right = 7동작 과정을 그림으로 나타내면

코드의 핵심 nums[mid] < nums[right]은 , right = mid. 주기에는 열린 간격이 right있으며 여기에서도 열린 간격이어야 합니다. 일관성을 유지하십시오 .

해당 코드는 다음과 같습니다. ( Kotlin )

class Solution {
    fun search(nums: IntArray, target: Int): Int {
        var left = 0
        var right = nums.size // [left,right) 右侧为开区间,right 设置为 nums.size
        while (left < right) {
            val mid = (left + right) / 2
            if (nums[mid] < target) left = mid + 1
            else if (nums[mid] > target) right = mid // 代码的核心,循环中 right 是开区间,这里也应是开区间
            else return mid
        }
        return -1 // 没有找到 target ,返回 -1
    }
}

두 번째 글쓰기 방법

배열 요소가 [1,2,3,4,5,6,7], 라고 가정하고 표기법을target = 3 사용하여 이진 정렬을 구현합니다.while(left <= right)

이렇게 'left = 0, right = 76'으로 쓰면 연산과정을 그림으로 나타내었다.

코드의 핵심 nums[mid] < nums[right]은 , right = mid - 1. 루프 right에는 닫힌 간격이 있으며 여기에서도 닫힌 간격이어야 하며 일관성을 유지해야 합니다 .

해당 코드는 다음과 같습니다. ( Kotlin )

class Solution {
    
    
    fun search(nums: IntArray, target: Int): Int {
    
    
        var left = 0
        var right = nums.size - 1 // [left,right] 右侧为闭区间,right 设置为 nums.size - 1
        while (left <= right) {
    
    
            val mid = (left + right) / 2
            if (nums[mid] < target) left = mid + 1
            else if (nums[mid] > target) right = mid - 1 // 代码的核心,循环中 right 是闭区间,这里也应是闭区间
            else return mid
        }
        return -1 // 没有找到 target ,返回 -1
    }
}

추천

출처blog.csdn.net/jiaweilovemingming/article/details/125063997