先写一下自己的背景吧。
某211大三Java选手,暑期实习投了很多很多,笔试很多,Java开发没有一个进面试,唯一进面的是第二志愿运维开发岗,一面挂。虽然对目前大环境和经济抱有怨言,但是算法是必须要刷的,没有任何捷径。之前刷过了牛客hot101,但是还差得远,题量少,也没有系统学习过算法,这肯定还敲不开大厂的门。所以,从现在开始,真正脚踏实地,去克服这些困难。种下一棵树的最好时机,一个是十年前,一个就是现在。
Day01题目
LeetCode704 二分查找,在数组中查找到target所在的下标
核心部分是:在二分查找的时候,如何确定循环的边界条件?
class Solution {
public int search(int[] nums, int target) {
int left = 0 ;
int right = nums.length- 1;
// while是<=还是<呢?和初始右边界定义为nums.length还是nums.length-1相对应
// 因为对于下标为nums.length-1,如果left=right都是nums.length-1,数组不越界,所以加上=
while(left <= right){
int middle = (left+right)/2;
if(nums[middle] > target){
//right为middle还是middle-1?因为middle对应的值已经是大于目标值的了,下一个要判断的值最大时middle-1对应的,这段代码中因为while中是<=可以取到右边界,所以右边界就取middle-1
right = middle-1;
}else if( nums[middle] < target){
left = middle+1;
}else{
return middle;
}
}
return -1;
}
}
LeetCode 27 移除元素,移除数组中对应元素
核心部分是:数组移除一个元素必须将后面的左移。暴力算法复杂度为n2,使用双指针可以很好简化复杂度。
双指针中,一个来遍历完这个数组,另外一个用来记录“新数组”的索引。
这个新数组指的是去除对应元素之后的数组。
class Solution {
public int removeElement(int[] nums, int val) {
// 快慢指针,慢指针记录的是新数组的下标
// j 为新数组的索引
int j = 0 ;
for(int i = 0 ; i< nums.length ; i ++){
if(nums[i] != val ){
// 这里的元素是要“加到新数组”的
nums[j] = nums[i];
j++;
}
}
return j;
}
}
LeetCode34 在排序数组中查找元素的第一个和最后一个位置
相对上面的题目,这道题目查找左右边界的时候需要对二分查找找到目标值的时候的left,right取值非常明确。因为while执行的条件是 left <= right ,所以最后返回的时候 left 一定是大于right的。
根据middle 和 target 相等的时候移动left 还是right,使得left 移动到所有 target值的最右边,right 移动到target值的左边。得到的结果是,如果target在数组中的第二位,下标为1,right边界是2,left边界时0,返回 0+1 和 2-1 就行了。
class Solution {
public int[] searchRange(int[] nums, int target) {
// 这里时获取左右边界,左边界在所有target值的最左边,右边界在最右边。
int left = searchLeft(nums, target);
int right = searchRight(nums, target);
int[] res = new int[2];
res[0] = -1;
res[1] = -1;
if (left == -2 || right == -2)
return res;
else if (right - left > 1) {
res[0] = left + 1;
res[1] = right - 1;
}
return res;
}
public int searchLeft(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
int leftBorder = -2;
while (left <= right) {
int middle = left + (right - left) / 2;
if (nums[middle] < target) {
left = middle + 1;
} else {
right = middle - 1;
// 获取左边界,nums[middle]与target相等的时候,也让right左移,这样right会一直左移到 所有target值的最左边
leftBorder = right;
}
}
return leftBorder;
}
public int searchRight(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
int rightBorder = -2;
while (left <= right) {
int middle = left + (right - left) / 2;
if (nums[middle] <= target) {
left = middle + 1;
// 获取右边界,当nums[middle]与target相等的时候,让left右移,这样最后左边界会移动到所有target的右边。
rightBorder = left;
} else {
right = middle - 1;
}
}
return rightBorder;
}
}
8106



被折叠的 条评论
为什么被折叠?



