网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
题目描述: 💦
👉题目链接👈
🏠解法一、暴力求解
思路分析: 💫
相比说到暴力求解多少都有点思路了,直接遍历数组,一个一个找相同的数,然后统计总数。
代码展示: 👇
class Solution {
public int search(int[] nums, int target) {
int count = 0;
//for(数据类型 变量名 :集合对象名)
for(int x : nums){ //我这里遍历数组简写了 习惯了for-each循环
if(x == target){
count ++; //统计总数
}
}
return count;
}
}
以上算法实现的复杂度分析:
- 时间复杂度是: O(n)
- 空间复杂度是 : O(1)
🏠解法二、二分法
重新审题看细节:
统计一个排序数组,看到排序(顺序)第一个反应就是“二分法”,所以这道题真正考验的就是你每次都能做对的二分法了(滑稽)
代码展示: 👇
//利用两次二分法分别确定target的左右边界(左右边界为target值序列的左/右一位,因此最终结果是right-left-1)
class Solution {
public int search(int[] nums, int target) {
if(nums.length == 0) {
return 0;
}
//初始左右指针位置
int i = 0;
int j = nums.length-1;
//第一次二分:找right边界
//这边是“小于等于”,因此当循环结束后,ij不重合,且如果存在target值的话,i的位置就是右边界(target值序列右边第一个大于target值的位置),因为最后一次循环一定是i=mid+1;且此时j指向target
while(i <= j) {
int mid = (i+j) >> 1;
//这里是“小于等于”,目的是为了确定右边界,就是说当mid等于target时,因为不确定后面还有没有target,所以同样需要左边收缩范围
if(nums[mid] <= target){
i = mid+1;
}
else{
j = mid-1;
}
}
//在更新right边界值之前,需要判断这个数组中是否存在target,如果不存在(看j指向的位置是不是target,为什么看的是j指针?详见上面的注释)
if(j>=0&&nums[j] != target){
return 0;
}
int right = i; //更新right边界
//重置指针
i = 0;
j = nums.length-1;
//第二次二分:找left边界
//结束之后,j指向target序列左边第一个小于它的位置,i指向target(经过上面判断,target一定存在)
![img](https://img-blog.csdnimg.cn/img_convert/54df13f24450f3c42e891167eac0c64e.png)
![img](https://img-blog.csdnimg.cn/img_convert/5bf780ca7665952541c1c08a454f66af.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**
文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**