1.1.1 배열 - 검색 삽입 위치(Leetcode 35)

1. 주제

Leetcode 링크
정렬된 배열과 대상 값이 주어지면 배열에서 대상 값을 찾고 해당 인덱스를 반환합니다. 대상 값이 배열에 없으면 순서대로 삽입할 위치를 반환합니다.

시간 복잡도가 O(log n)인 알고리즘을 사용하십시오.

예 1:

입력: 숫자 = [1,3,5,6], 대상 = 5
출력: 2

예 2:

입력: 숫자 = [1,3,5,6], 대상 = 2
출력: 1

예 3:

입력: 숫자 = [1,3,5,6], 대상 = 7
출력: 4

예 4:

입력: 숫자 = [1,3,5,6], 대상 = 0
출력: 0

예 5:

입력: 숫자 = [1], 대상 = 0
출력: 0

힌트:

  • 1 <= 숫자.길이 <= 104
  • -104 <= 숫자[i] <= 104
  • nums는 반복되는 요소가 없는 오름차순 배열입니다.
  • -104 <= 대상 <= 104

2. 아이디어

제목은 이분법을 사용하라는 메시지를 표시합니다.

  • nums는 반복되는 요소가 없는 오름차순 배열입니다.
  • 시간 복잡도가 O(log n)인 알고리즘을 사용해야 합니다.

네 가지 상황:

  • 대상 값은 배열의 모든 요소 앞에 있습니다.
  • 대상 값이 배열의 요소와 같습니다.
  • 대상 값이 삽입되는 배열의 위치
  • 대상 값은 배열의 모든 요소 뒤에 있습니다.

핵심:

  • 순회를 종료하기 위해 바이너리 방법을 사용하는 경우 왼쪽과 오른쪽이 가리키는 위치

3. 코드 구현

3.1 해결책 1: 폭력적인 해결책

  • 시간 복잡도 O(log n) 조건을 만족하지 않음
class Solution {
    
    
public:
    int searchInsert(vector<int>& nums, int target) {
    
    
        for(int i = 0; i < nums.size(); i++){
    
    
            // 对应于前三种情况
            if(nums[i] >= target){
    
    
                return i;
            }

        }
        // 对应于目标值在数组所有元素之后的情况
        return nums.size();

    }
};

3.2 솔루션 2: 이분법(왼쪽 폐쇄 및 오른쪽 폐쇄)

class Solution {
    
    
public:
    int searchInsert(vector<int>& nums, int target) {
    
    
       // 定义左闭右闭区间
       
       int left = 0;
       int right = nums.size() - 1;

        while(left <= right){
    
    
            int middle = left + (right - left) / 2;
            if(nums[middle] < target){
    
    
                left = middle + 1; // target 在右区间,所以[middle + 1, right]
            }else if(nums[middle] > target){
    
    
                right = middle - 1; // target 在左区间,所以[left, middle - 1]
            }else{
    
    // nums[middle] == target
                return middle;
            }
        }

        // 数组中不存在target
        // 1. 插入到所有元素之前,所有的元素都比target大:right = -1(left = 0)
        // 2. 插入到数组中,nums[left] < target < nums[right]
        // 下一次循环,执行left = middle + 1;
        // 下一次循环,执行right = middle - 1, 结束循环;
        // 3. 插入到所有元素之后,所有的元素都比target大:right = nums.size() - 1(left = nums.size())
        return right + 1;

    }
};

3.3 솔루션 3: 이분법(왼쪽 폐쇄 및 오른쪽 개방)

class Solution {
    
    
public:
    int searchInsert(vector<int>& nums, int target) {
    
    
       // 定义左闭右开区间
       
       int left = 0;
       int right = nums.size();

        while(left < right){
    
    
            int middle = left + (right - left) / 2;
            if(nums[middle] < target){
    
    
                left = middle + 1; // target 在右区间,所以[middle + 1, right)
            }else if(nums[middle] > target){
    
    
                right = middle; // target 在左区间,所以[left, middle)
            }else{
    
    // nums[middle] == target
                return middle;
            }
        }

        // 数组中不存在target
        // 1. 插入到所有元素之前,所有的元素都比target大:right = 0(left = 0)
        // 2. 插入到数组中,nums[left] < target < nums[right]
        // 下一次循环,执行left = middle + 1;
        // 下一次循环,执行right = middle, 结束循环;
        // 3. 插入到所有元素之后,所有的元素都比target大:right = nums.size()(left = nums.size())
        return right;

    }
};

4. 요약

  • 이분법 과정에 대한 이해를 깊게 할 필요가 있으며, 특히 루프가 끝날 때 왼쪽과 오른쪽의 포인팅 위치

추천

출처blog.csdn.net/weixin_46297585/article/details/123195584