day01 打卡704. 二分查找,27. 移除元素
day01 打卡704. 二分查找,27. 移除元素
704.二分查找
1.第一次错误代码
class Solution {
public int search(int[] nums, int target) {
int min = 0;
int max = nums.length;
int mid = max / 2;
while(min < max) {
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
min = mid + 1;
} else if (nums[mid] > target) {
max = mid - 1;
}
}
return -1;
}
}
2.debug后,发现问题
- 最严重的问题是mid的值没有重新再赋值
- 初始化max的值 和 跳出while的条件 没有考虑到,界限问题。我这里用的是左闭右闭的情况
- mid = ( max + min ) / 2中( max + min )可能会超出int的上限值。需要改成mid =min+ ( max-min ) / 2或者mid=min+((max-min)>>1)
class Solution {
public int search(int[] nums, int target) {
int min = 0;
int max = nums.length - 1;
int mid = max / 2;
while(min <= max) {
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
min = mid + 1;
} else if (nums[mid] > target) {
max = mid - 1;
}
mid = min + ( max - min ) / 2;
}
return -1;
}
}
3.改进提高效率的地方: target 如果大于最大的 小于最小的 可以最开始的时候判断直接return -1。放35题改进了。
704的拓展之35.搜索插入位置
1.参考二分查找
class Solution {
public int searchInsert(int[] nums, int target) {
int left = 0 ;
int right = nums.length - 1;
int mid;
if (nums[0] >= target) {
return 0;
}
if (nums[right] == target) {
return right;
}
if (nums[right] < target) {
return right + 1;
}
while (left <= right) {
mid = ( left + right ) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
}
}
return left;
}
}
704的拓宽之34.
1.暴力解法,直接两次分开的循环得到开始位置和结束位置
class Solution {
public int[] searchRange(int[] nums, int target) {
int[] result = {-1, -1};
for (int i = 0 ; i<nums.length ; i++) {
if (nums[i] == target) {
result[0] = i;
break;
}
}
for (int i = nums.length-1 ; i>=0; i--) {
if (nums[i] == target) {
result[1] = i;
break;
}
}
return result;
}
}
2.二分查找左边和右边的界限。暂时有点疑问,后续再补
27.移除元素
1.暴力解法。通过两层的循环,讲后面的数值覆盖前面的
class Solution {
public int removeElement(int[] nums, int val) {
int n = nums.length;
int count = 0;
int i = 0;
while (i<n-count) {
if (nums[i] == val) {
count++;
for (int j = i+1 ; j<n; j++) {
nums[j-1] = nums[j];
}
} else {
i++;
}
}
return n - count;
}
}
2.快慢指针。快指针是不包含目标元素的下标;慢指针是更新数组的下标
class Solution {
public int removeElement(int[] nums, int val) {
int slow = 0;
for (int fast = 0 ; fast<nums.length ; fast++) {
if (nums[fast] != val) {
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
}
3.相向双指针。左指针从0下标开始,右指针从n-1下标开始。右指针需要一直保持不等于val的最右边值的下标,左指针不断增加的过程中,一旦遇到了等于val的值,就需要重新赋值,重新赋值的值是此时右指针对应的值(肯定不等于val),并且左指针需要减小,并且保证最右边不等于val。
class Solution {
public int removeElement(int[] nums, int val) {
int n = nums.length;
int left = 0;
int right = n-1;
// 保证最右边不等于val
while(right >= 0 && nums[right] == val) right--;
while(left <= right) {
// 左指针遇到了等于val的值,就需要重新赋值
if (nums[left] == val) {
nums[left] = nums[right];
right--;
}
left++;
// 保证最右边不等于val
while(right >= 0 && nums[right] == val) right--;
}
return left;
}
}

浙公网安备 33010602011771号