leetcode第34题

简介: 从左向右遍历,一旦出现等于 target 的值就结束,保存当前下标。如果从左到右没有找到 target,那么就直接返回 [ -1 , -1 ] 就可以了,因为从左到右没找到,那么从右到左也一定不会找到的。如果找到了,然后再从右到左遍历,一旦出现等于 target 的值就结束,保存当前下标。时间复杂度是 O(n)并不满足题意,但可以了解下这个思路,从左到右,从右到左之前也遇到过。

image.png

找到目标值的第一次出现和最后一次出现的位置,同样要求 log ( n ) 下完成。

先分享 leetcode 提供的两个解法。

解法一 线性扫描

从左向右遍历,一旦出现等于 target 的值就结束,保存当前下标。如果从左到右没有找到 target,那么就直接返回 [ -1 , -1 ] 就可以了,因为从左到右没找到,那么从右到左也一定不会找到的。如果找到了,然后再从右到左遍历,一旦出现等于 target 的值就结束,保存当前下标。

时间复杂度是 O(n)并不满足题意,但可以了解下这个思路,从左到右,从右到左之前也遇到过。

publicint[] searchRange(int[] nums, inttarget) {
int[] targetRange= {-1, -1};
// 从左到右扫描for (inti=0; i<nums.length; i++) {
if (nums[i] ==target) {
targetRange[0] =i;
break;
        }
    }
// 如果之前没找到,直接返回 [ -1 , -1 ]if (targetRange[0] ==-1) {
returntargetRange;
    }
//从右到左扫描for (intj=nums.length-1; j>=0; j--) {
if (nums[j] ==target) {
targetRange[1] =j;
break;
        }
    }
returntargetRange;
}

时间复杂度:O(n)。

空间复杂度:O(1)。

解法二 二分查找

让我们先看下正常的二分查找。

intstart=0;
intend=nums.length-1;
while (start<=end) {
intmid= (start+end) /2;
if (target==nums[mid]) {
returnmid;
    } elseif (target<nums[mid]) {
end=mid-1;
    } else {
start=mid+1;
    }
}

二分查找中,我们找到 target 就结束了,这里我们需要修改下。

我们如果找最左边等于 target 的值,找到 target 时候并不代表我们找到了我们所需要的,例如下边的情况,

image.png

此时 target == nums [ mid ] ,但由于我们改成了 end = mid - 1,所以继续更新,end 就到了 mid 的左边,此时 start > end 了,就会走出 while 循环, 我们要找的值刚好就是 start 指向的了。那么我们修改的代码如下:

while (start<=end) {
intmid= (start+end) /2;
if (target==nums[mid]) {
end=mid-1;
    } elseif (target<nums[mid]) {
end=mid-1 ;
    } else {
start=mid+1;
    }
}

找右边的同样的分析思路,就是判断需要丢弃哪一边。

所以最后的代码就出来了。leetcode 中是把找左边和找右边的合并起来了,本质是一样的。

publicint[] searchRange(int[] nums, inttarget) {
intstart=0;
intend=nums.length-1;
int[] ans= { -1, -1 };
if (nums.length==0) {
returnans;
    }
while (start<=end) {
intmid= (start+end) /2;
if (target==nums[mid]) {
end=mid-1;
        } elseif (target<nums[mid]) {
end=mid-1;
        } else {
start=mid+1;
        }
    }
//考虑 tartget 是否存在,判断我们要找的值是否等于 target 并且是否越界if (start==nums.length||nums[ start ] !=target) {
returnans;
    } else {
ans[0] =start;
    }
ans[0] =start;
start=0;
end=nums.length-1;
while (start<=end) {
intmid= (start+end) /2;
if (target==nums[mid]) {
start=mid+1;
        } elseif (target<nums[mid]) {
end=mid-1;
        } else {
start=mid+1;
        }
    }
ans[1] =end;
returnans;
}

时间复杂度:O(log(n))。

空间复杂度:O(1)。

相关文章
|
2月前
【LeetCode 02】暴力法总结
【LeetCode 02】暴力法总结
19 1
|
4月前
|
算法
LeetCode第66题加一
LeetCode第66题"加一"的解题方法,通过遍历数组从后向前处理每一位的加法,并考虑进位情况,最终实现给定数字加一的功能。
LeetCode第66题加一
|
7月前
leetcode-1219:黄金矿工
leetcode-1219:黄金矿工
84 0
|
7月前
leetcode-475:供暖器
leetcode-475:供暖器
50 0
LeetCode 354. Russian Doll Envelopes
给定一些标记了宽度和高度的信封,宽度和高度以整数对形式 (w, h) 出现。当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。 请计算最多能有多少个信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。
82 0
LeetCode 354. Russian Doll Envelopes
|
测试技术
一和零(LeetCode-474)
一和零(LeetCode-474)
139 0
一和零(LeetCode-474)
leetcode第38题
难在了题目是什么意思呢? 初始值第一行是 1。 第二行读第一行,1 个 1,去掉个字,所以第二行就是 11。 第三行读第二行,2 个 1,去掉个字,所以第三行就是 21。 第四行读第三行,1 个 2,1 个 1,去掉所有个字,所以第四行就是 1211。 第五行读第四行,1 个 1,1 个 2,2 个 1,去掉所有个字,所以第五航就是 111221。 第六行读第五行,3 个 1,2 个 2,1 个 1,去掉所以个字,所以第六行就是 312
leetcode第38题
|
人工智能 算法
leetcode第41题
对于这种要求空间复杂度的,我们可以先考虑如果有一个等大的空间,我们可以怎么做。然后再考虑如果直接用原数组怎么做,主要是要保证数组的信息不要丢失。目前遇到的,主要有两种方法就是交换和取相反数。
leetcode第41题
|
存储 算法 Java
leetcode第29题
这道题看起来简单,却藏了不少坑。首先,我们用一次一次减造成了超时,然后我们用递归实现了加倍加倍的减,接着由于 int 表示的数的范围不是对称的,最小的负数并不能转换为对应的相反数,所以我们将之前的算法思路完全逆过来,正数边负数,大于变小于,还是蛮有意思的。
leetcode第29题
|
算法
leetcode第30题
如上图,利用循环变量 i ,依次后移,判断每个子串是否符合即可。 怎么判断子串是否符合?这也是这个题的难点了,由于子串包含的单词顺序并不需要固定,如果是两个单词 A,B,我们只需要判断子串是否是 AB 或者 BA 即可。如果是三个单词 A,B,C 也还好,只需要判断子串是否是 ABC,或者 ACB,BAC,BCA,CAB,CBA 就可以了,但如果更多单词呢?那就崩溃了。 链接)的作者提出了,用两个 HashMap 来解决。首先,我们把所有的单词存到 HashMap 里,key 直接存单词,value 存单词出现的个数(因为给出的单词可能会有重复的,所以可能是 1 或 2 或者其他)。然后扫描子
124 0
leetcode第30题