LeetCode 刷题记录 34. Find First and Last Position of Element in Sorted Array

题目:
Given an array of integers nums sorted in ascending order, find the starting and ending position of a given target value.

Your algorithm’s runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

Example 1:

Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]
Example 2:

Input: nums = [5,7,7,8,8,10], target = 6
Output: [-1,-1]
解法1:
与正常的二分查找不同,由于此题要求的是最开始的元素和最后的元素,所以我们在二分查找时如果找到目标元素,我们首先记录下他的下标,如果是找第一个,我们就往左移,如果是找最后一个,我们就往右移
例如:5 7 7 8 9 10
先求first:mid = 7, 7 < 8, 舍弃左半边, lo = 3,hi = 5,lo <= hi 成立,继续迭代,mid = 8,记录此时的下标为4,由于是找第一个元素,所以我们要舍弃右半边,lo = 3,hi = 3,lo <= hi 成立,继续迭代,mid = 8,记录此时的下标为3,由于是找第一个元素,所以我们要舍弃右半边,lo = 3,hi = 2,,lo <= hi 不成立,结束循环,此时我们得到第一个元素的下标3
求last的情况和first一样,只不过我们在找到目标元素后向右移,舍弃左半边
我们还要考虑找不到的情况 所以我们预设idx为-1,结束后如果下标没有更新则返回-1
c++:

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        vector<int> res;
        int first = findFirst(nums,target);
        int last =  findLast(nums,target);
        res.push_back(first);
        res.push_back(last);
        return res;
    }
    int findFirst(vector<int>& nums, int target){
        int n = nums.size();
        int lo = 0;
        int hi = n - 1;
        int idx = -1;
        while(lo <= hi){
            int mid = lo + (hi - lo) / 2;
            if(nums[mid] == target){
                hi = mid - 1;
                idx = mid;
            } else if(nums[mid] > target){
                hi = mid - 1;
            } else {
                lo = mid + 1;
            }
            
        }
        return idx;
    }
    int findLast(vector<int>& nums, int target){
        int n = nums.size();
        int lo = 0;
        int hi = n - 1;
        int idx = -1;
        while(lo <= hi){
            int mid = lo + (hi - lo) / 2;
            if(nums[mid] == target){
                lo = mid + 1;
                idx = mid;
            } else if(nums[mid] > target){
                hi = mid - 1;
            } else {
                lo = mid + 1;
            }
            
        }
        return idx;
    }
};

java:

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int[] res = new int[2];
        int first = findFirst(nums,target);
        int last =  findLast(nums,target);
        res[0] = first;
        res[1] = last;
        return res;
    }
    public int findFirst(int[] nums, int target){
        int n = nums.length;
        int lo = 0;
        int hi = n - 1;
        int idx = -1;
        while(lo <= hi){
            int mid = lo + (hi - lo) / 2;
            if(nums[mid] == target){
                hi = mid - 1;
                idx = mid;
            } else if(nums[mid] > target){
                hi = mid - 1;
            } else {
                lo = mid + 1;
            }
            
        }
        return idx;
    }
    public int findLast(int[] nums, int target){
        int n = nums.length;
        int lo = 0;
        int hi = n - 1;
        int idx = -1;
        while(lo <= hi){
            int mid = lo + (hi - lo) / 2;
            if(nums[mid] == target){
                lo = mid + 1;
                idx = mid;
            } else if(nums[mid] > target){
                hi = mid - 1;
            } else {
                lo = mid + 1;
            }
            
        }
        return idx;
    }
    
}

python:
python list不能赋值,只能append

class Solution(object):
    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        res = []
        first = self.findFirst(nums,target)
        last =  self.findLast(nums,target)
        res.append(first)
        res.append(last)
        return res
    def findFirst(self, nums, target):
        n = len(nums)
        lo = 0
        hi = n - 1
        idx = -1
        while lo <= hi:
            mid = lo + (hi - lo) / 2
            if nums[mid] == target:
                hi = mid - 1
                idx = mid
            elif nums[mid] > target:
                hi = mid - 1
            else:
                lo = mid + 1
            
            
        
        return idx
    
    def findLast(self, nums, target):
        n = len(nums)
        lo = 0
        hi = n - 1
        idx = -1
        while lo <= hi:
            mid = lo + (hi - lo) / 2
            if nums[mid] == target:
                lo = mid + 1
                idx = mid
            elif nums[mid] > target:
                hi = mid - 1
            else:
                lo = mid + 1
            
            
        
        return idx
    

解法2:
lower_bound() 找第一个大于等于val的位置
upper_bound() 找第一个大于val的位置
在本题中我们可以用lower_bound()找第一个位置,用upper_bound() - 1来找最后一个位置
此外我们还要考虑没找到的情况,由于lower_bound() 找第一个大于等于val的位置,所以它必定大于0,如果target大于数组的最大值,它将返回n(数组的长度)
所以我们可以用

if(first < n && nums[first] == target)

来判断是否找到了target
重点是lower_bound()和upper_bound()的实现
lower_bound():

int lower_bound(vector<int>& nums, int target){
        int n = nums.size();
        int lo = 0;
        int hi = n;
        while(lo < hi){
            int mid = lo + (hi - lo) / 2;
            if(nums[mid] >= target){
                hi = mid;
            } else {
                lo = mid + 1;
            }
            
        }
        return lo;

    }

该方案lo < hi 且初始空间为[0,n]
[5,7,7,8,8,10], target = 8
在这里插入图片描述
mid = 8 >=8,满足条件,说明第一个满足条件的元素一定在mid或者mid的做出,hi = mid
在这里插入图片描述
在这里插入图片描述
mid = 7,7 < 8,说明第一个大于等于8的一定在mid的右侧, lo = mid + 1
在这里插入图片描述
mid = 7,7 < 8,说明第一个大于等于8的一定在mid的右侧, lo = mid + 1
在这里插入图片描述
lo = hi结束循环,lo的位置即为第一个大于等于8的位置
[5,7,7,8,8,10], target = 11
在这里插入图片描述
mid = 8,8 < 11,说明第一个大于等于11的一定在mid的右侧, lo = mid + 1
在这里插入图片描述
mid 为10,·10< 11,说明第一个大于等于11的一定在mid的右侧, lo = mid + 1
在这里插入图片描述
lo = hi结束循环,lo的位置即为说明第一个大于等于8的位置
lower_bound()的第二种写法:
循环条件:lo <= hi 初始[0,n-1]

int lower_bound(vector<int>& nums, int target){
        int n = nums.size();
        int lo = 0;
        int hi = n - 1;
        while(lo <= hi){
            int mid = lo + (hi - lo) / 2;
            if(nums[mid] >= target){
                hi = mid - 1;
            } else {
                lo = mid + 1;
            }
            
        }
        return lo;
    }

[5,7,7,8,8,10], target = 8
在这里插入图片描述
mid = 7 7 < 8, lo = mid + 1
在这里插入图片描述
mid = 8 8 >= 8, hi = mid - 1不是维持mid
在这里插入图片描述
mid = 8 8 >= 8, hi = mid - 1不是维持mid
在这里插入图片描述
hi < lo 结束循环返回lo
[5,7,7,8,8,10], target = 11
在这里插入图片描述
mid = 7 7 < 11, lo = mid + 1
在这里插入图片描述
mid = 8 8 < 11, lo = mid + 1
在这里插入图片描述
mid = 10 8 < 11, lo = mid + 1
在这里插入图片描述
lo > hi 结束循环,返回lo
upper_bound()函数和lower_bound()函数一样只不过判断条件为>,而不是>=
C++:
C++ vector重载了= 所以可以用res[0] = first;

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        vector<int> res(2,-1);
        int n = nums.size();
        int first = lower_bound(nums,target);
        int last =  upper_bound(nums,target) - 1;
        cout << first << " " << last <<endl;
        if(first < n && nums[first] == target){
            res[0] = first;
            res[1] = last;
            return res;
        } else {
            return res;
        }
        
    }
    int lower_bound(vector<int>& nums, int target){
//         int n = nums.size();
//         int lo = 0;
//         int hi = n;
//         while(lo < hi){
//             int mid = lo + (hi - lo) / 2;
//             if(nums[mid] >= target){
//                 hi = mid;
//             } else {
//                 lo = mid + 1;
//             }
            
//         }
//         return lo;
        int n = nums.size();
        int lo = 0;
        int hi = n - 1;
        while(lo <= hi){
            int mid = lo + (hi - lo) / 2;
            if(nums[mid] >= target){
                hi = mid - 1;
            } else {
                lo = mid + 1;
            }
            
        }
        return lo;
    }
    int upper_bound(vector<int>& nums, int target){
        int n = nums.size();
        int lo = 0;
        int hi = n;
        while(lo < hi){
            int mid = lo + (hi - lo) / 2;
            if(nums[mid] > target){
                hi = mid;
            } else {
                lo = mid + 1;
            }
            
        }
        return lo;
//         int n = nums.size();
//         int lo = 0;
//         int hi = n - 1;
//         while(lo <= hi){
//             int mid = lo + (hi - lo) / 2;
//             if(nums[mid] > target){
//                 hi = mid - 1;
//             } else {
//                 lo = mid + 1;
//             }
            
//         }
//         return lo;
    }
};

java:

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int[] res = new int[2];
        res[0] = -1;
        res[1] = -1;
        int n = nums.length;
        int first = lower_bound(nums,target);
        int last =  upper_bound(nums,target) - 1;
        if(first < n && nums[first] == target){
            res[0] = first;
            res[1] = last;
            return res;
        } else {
            return res;
        }
    }
    public int lower_bound(int[] nums, int target){
        int n = nums.length;
        int lo = 0;
        int hi = n - 1;
        while(lo <= hi){
            int mid = lo + (hi - lo) / 2;
            if(nums[mid] >= target){
                hi = mid - 1;
            } else {
                lo = mid + 1;
            }
            
        }
        return lo;
    }
    public int upper_bound(int[] nums, int target){
        int n = nums.length;
        int lo = 0;
        int hi = n - 1;
        while(lo <= hi){
            int mid = lo + (hi - lo) / 2;
            if(nums[mid] > target){
                hi = mid - 1;
            } else {
                lo = mid + 1;
            }
            
        }
        return lo;
    }
    
}

python:
python list不能用赋值=

class Solution(object):
    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        res = []
        n = len(nums)
        first = self.lower_bound(nums,target)
        last =  self.upper_bound(nums,target) - 1
        if first < n and nums[first] == target:
            res.append(first)
            res.append(last)
            return res
        else:
            res.append(-1)
            res.append(-1)
            return res
        
    def lower_bound(self, nums, target):
        n = len(nums)
        lo = 0
        hi = n - 1
        
        while lo <= hi:
            mid = lo + (hi - lo) / 2
            if nums[mid] >= target:
                hi = mid - 1
           
            else:
                lo = mid + 1
            
            
        
        return lo
    
    def upper_bound(self, nums, target):
        n = len(nums)
        lo = 0
        hi = n - 1
       
        while lo <= hi:
            mid = lo + (hi - lo) / 2
            if nums[mid] > target:
                hi = mid - 1
            else:
                lo = mid + 1
            
            
        
        return lo
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值