day01:704.二分查找、27移除元素
LeetCode 704 二分查找
题目链接:
文章讲解:
https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html
视频讲解:
https://www.bilibili.com/video/BV1fA4y1o715
思路和解法:
暴利法:
直接遍历数组,找到需要的值后返回下标,时间复杂度O(N),但这样做就没意义了,舍弃!
二分法:
定义好查找的范围后,每次查找取范围的中点,比较nums[mid]和target的大小,然后根据情况更新查找范围。
主要有两种写法,区别是边界条件的不同, 左闭右闭 [left, right] 或 左闭右开 [left, right)
时间复杂度:O(logN)
一、左闭右闭 [left, right],循环条件:while(left <= right)
public int Search(int[] nums, int target) {
int left = 0;
int right = nums.Length - 1;
while(left <= right)
{
int mid = (right - left) / 2 + left;
if(nums[mid] < target)
{
left = mid + 1;
}
else if(nums[mid] > target)
{
right = mid - 1;
}
else
{
return mid;
}
}
return -1;
}
二、左闭右开[left, right),while(left < right)
public int Search(int[] nums, int target) {
int left = 0;
int right = nums.Length;//特殊情况:目标值在最右边,所以right的初始值要为nums.Length
while(left < right)
{
int mid = (right - left) / 2 + left;
if(nums[mid] < target)
{
left = mid + 1;
}
else if(nums[mid] > target)
{
//因为边界条件是左闭右开的,所以要保证右区间合法
right = mid;
}
else
{
return mid;
}
}
return -1;
}
LeetCode 27移除元素
题目链接
文章讲解
https://programmercarl.com/0027.%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0.html
视频讲解
https://www.bilibili.com/video/BV12A4y1Z7LP
思路和方法
暴力法:
两层for循环,一层循环遍历数组,一层循环更新数组
public int RemoveElement(int[] nums, int val) {
int n = nums.Length;
for(int i = 0; i < n; i++)
{
//发现需要移除的元素,就将数组集体向前移动一位
if(nums[i] == val)
{
for(int j = i + 1; j < n; j++)
{
nums[j - 1] = nums[j];
}
i--;//因为下标i之后的值都向前移动了一位,所以i也要向前移一位
n--;//此时数组的大小减一
}
}
return n;
}
双指针法
通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
定义快慢两个指针。
-
快指针:用于寻找新数组的元素,新数组指不含有目标元素的数组
-
慢指针:指向新数组要更新的下标
public int RemoveElement(int[] nums, int val) {
int slow = 0,fast = 0;
while(fast < nums.Length)
{
if(nums[fast] != val)
{
nums[slow] = nums[fast];
slow++;//slow右移,指向下一个位置
}
fast++;
}
return slow;//因为slow当前指向的位置未被处理,所以不用slow-1
}
总结:
上述两题涉及到的方法虽然看上去很复杂,但只要跟着思路把每一步、每次一遍历画出来,就很容易理解了,多画图!