代码随想录0704.二分查找
手把手带你撕出正确的二分法 | 二分查找法 | 二分搜索法 | LeetCode:704. 二分查找
是非常朴素的二分查找。需要注意区间的开闭,我个人喜欢用前闭后开的区间 [ l e f t , m i d ) , m i d , [ m i d + 1 , r i g h t ) [left, mid), mid, [mid + 1, right) [left,mid),mid,[mid+1,right),其中 l e f t left left初始为 0 0 0, r i g h t right right初始为 n u m . l e n g t h num.length num.length
class Solution {
public int search(int[] nums, int target) {
int left, right, mid;
left = 0;
right = nums.length - 1;
while (left <= right) {
mid = (left + right) / 2;
if(nums[mid] == target) {
return mid;
}
if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
}
代码随想录0027.移除元素
数组中移除元素并不容易! | LeetCode:27. 移除元素
移除数组中的元素,实际上是求原数组的一个子集,这个子集中元素的出现顺序与原数组相同,且不含有被指定要删除的元素。这个时候考虑到快慢指针,用 f a s t fast fast指针搜索下一个可以加入子集的元素并将该元素填入 s l o w slow slow指针所指向的位置;每次填入之后同时将 s l o w slow slow 和 f a s t fast fast向后移动,分别表示下一个可填入位置和下一轮查找的起点。最终跳出循环时, s l o w slow slow会指向所求子集最后一个元素的后一个位置,也即能表示所求子集的长度。
class Solution {
public int removeElement(int[] nums, int val) {
int slow, fast;
slow = 0;
fast = 0;
while(fast < nums.length) {
if (nums[fast] == val) {
++fast;
continue;
}
nums[slow] = nums[fast];
++slow;
++fast;
}
return slow;
}
}
没看
没看
同样是二分查找的题目。当带查找的元素在数组中存在时,与704题解法相同。当数组中不存在这样一个元素时,需要考虑一下最后跳出循环时问题的状态。
class Solution {
public int searchInsert(int[] nums, int target) {
int left, right, mid;
left = 0;
right = nums.length;
while (left < right) {
mid = (left + right) / 2;
if (nums[mid] == target) {
return mid;
}
if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid;
}
}
return right;
}
}
没看
没看
二分查找,退出循环后检查 n u m s [ m i d ] nums[mid] nums[mid] 是否是 t a r g e t target target。
class Solution {
public int[] searchRange(int[] nums, int target) {
int[] res = new int[2];
int left, right, mid;
left = 0;
right = nums.length;
mid = right / 2;
while(left < right) {
mid = (left + right) / 2;
if(nums[mid] == target){
break;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid;
}
}
if (nums.length == 0 || nums[mid] != target){
res[0] = -1;
res[1] = -1;
} else {
left = mid;
right = mid;
boolean l = false;
boolean r = false;
while(left >= 0 && right < nums.length) {
if(left == 0){
l = true;
} else if (nums[left - 1] == target) {
--left;
} else {
l = true;
}
if (right == nums.length - 1){
r = true;
} else if(nums[right + 1] == target) {
++right;
} else {
r = true;
}
if(l && r) {
res[0] = left;
res[1] = right;
break;
}
}
}
return res;
}
}
第一天打卡,题目本身不难,但是要非常注意细节,二分查找的边界处理非常重要,很久以前因为没有考虑清楚区间的开闭导致死循环超时。今天做题的时候统一使用了前闭后开,没有出错,非常奶思。