给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

你可以假设数组中无重复元素。

示例 1:

  1. 输入: [1,3,5,6], 5
  2. 输出: 2

示例 2:

  1. 输入: [1,3,5,6], 2
  2. 输出: 1

示例 3:

  1. 输入: [1,3,5,6], 7
  2. 输出: 4

示例 4:

  1. 输入: [1,3,5,6], 0
  2. 输出: 0

暴力解法:遍历数组依次检查

public int searchInsert(int[] nums, int target) {
    int length = nums.length;
    // 若数组第一个元素就大于目标值,则直接返回 0 
    if (nums[0] > target) {
        return 0;
    }
    // 若数组最后一个元素小于目标值,则直接返回数组长度(作为结果索引值)
    if (nums[length-1] < target) {
        return length;
    }
    int left = 0;
    for(int i = 0; i < length; i++) {
        // 若某个值等于目标值,则返回当前索引
        if (nums[i] == target) {
            return i;
        }
        // 若某个值等小目标值,则将当前索引记录下来
        if (nums[i] < target) {
            left = i;
        }
    }
    return left + 1;
}

复杂度分析
时间复杂度:O(n),其中 n 为数组的长度。
空间复杂度:O(1)。我们只需要常数空间存放若干变量。

二分查找

因为数组是有序的,可以使用二分查找

public int searchInsert(int[] nums, int target) {
    int length = nums.length;
    if (nums[0] > target) {
        return 0;
    }
    if (nums[length-1] < target) {
        return length;
    }
    int left = 0;
    int right = length - 1;
    while (left <= right) {
        int mid = (left + right) / 2; 
        if(nums[mid] == target) {
            return mid;
        } else if(nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return left;
}

为了防止整数范围溢出,将 int mid = (left + right) / 2; 修改为 int mid = left + (right - left) / 2;

public int searchInsert(int[] nums, int target) {
    int length = nums.length;
    if (nums[0] > target) {
        return 0;
    }
    if (nums[length-1] < target) {
        return length;
    }
    int left = 0;
    int right = length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2; 
        if(nums[mid] == target) {
            return mid;
        } else if(nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return left;
}

利用位运算可以将 int mid = left + (right - left) / 2; 修改为 int mid = left + ( (right - left) >> 1 );

public int searchInsert(int[] nums, int target) {
    int length = nums.length;
    if (nums[0] > target) {
        return 0;
    }
    if (nums[length-1] < target) {
        return length;
    }
    int left = 0;
    int right = length - 1;
    while (left <= right) {
        int mid = left + ((right - left) >> 1); 
        if(nums[mid] == target) {
            return mid;
        } else if(nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return left;
}

复杂度分析
时间复杂度:O(logn),其中 n 为数组的长度。
空间复杂度:O(1)。我们只需要常数空间存放若干变量。