学习任务:
- 数组理论基础
- Leetcode704.二分查找
- Leetcode27. 移除元素
Leetcode704.二分查找
难度:简单
| 相关标签:数组、二分查找
- 题目: 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
- 思路:
- 设定左右指针
- 找出中间位置,并判断该位置值是否等于 target
- nums[mid] == target 则返回该位置下标
nums[mid] > target 则右侧指针移到中间
nums[mid] < target 则左侧指针移到中间
- 注意:
- 这道题目的前提是数组为有序数组,同时题目还强调数组中无重复元素,因为一旦有重复元素,使用二分查找法返回的元素下标可能不是唯一的,这些都是使用二分法的前提条件。
- 写二分法,区间的定义一般为两种,左闭右闭即[left, right],或者左闭右开即[left, right)。一定好好好区分掌握。
- 注意mid的写法:
int middle = left + ((right - left) / 2);
可以防止溢出 ,等同于(left + right)/2
- 代码: 左闭右闭
class Solution {
public int search(int[] nums, int target) {
int i = 0;
int j = nums.length - 1;
while(i <= j){
int mid = (i + j) / 2;
if(nums[mid] == target){
return mid;
}else if(nums[mid] > target){
j = mid - 1;
}else{
i = mid + 1;
}
}
return -1;
}
}
- 反思: 在区间开闭上迟疑了很久,一定好好好区分和掌握两种不同的二分写法
Leetcode27.移除元素
难度:简单
| 相关标签:数组、双指针
-
题目: 给你一个数组 nums 和一个值 val,你需要
原地
移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。 假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作:- 更改 nums 数组,使 nums 的前 k 个元素包含不等于 val 的元素。nums 的其余元素和 nums 的大小并不重要。
- 返回 k。
-
思路: 暴力破解就是用后面的元素覆盖前面需要移除的元素;如果是双指针定义快慢指针,快指针指的是无论是否找到 val 都正常往后移动但是慢指针就不是这样了,遇到val 它就不更新了
-
注意:
- 定义快慢指针:
快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
慢指针:指向更新 新数组下标的位置
- 定义快慢指针:
-
代码:
暴力破解:
两层for循环,一个for循环遍历数组元素 ,第二个for循环更新数组
class Solution {
public int removeElement(int[] nums, int val) {
int size = nums.length;
for (int i = 0; i < size; i++) {
if (nums[i] == val) { // 发现需要移除的元素,就将数组集体向前移动一位
for (int j = i + 1; j < size; j++) {
nums[j - 1] = nums[j];
}
i--; // 因为下标i以后的数值都向前移动了一位,所以i也向前移动一位
size--; // 此时数组的大小-1
}
}
return size;
}
}
双指针法:
通过一个快指针和慢指针在一个for循环下完成两个for循环的工作
class Solution1 {
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;
}
}
//相向双指针法
class Solution2 {
public int removeElement(int[] nums, int val) {
int left = 0;
int right = nums.length - 1;
while(right >= 0 && nums[right] == val) right--; //将right移到从右数第一个值不为val的位置
while(left <= right) {
if(nums[left] == val) { //left位置的元素需要移除
//将right位置的元素移到left(覆盖),right位置移除
nums[left] = nums[right];
right--;
}
left++;
while(right >= 0 && nums[right] == val) right--;
}
return left;
}
}
- 反思: 一开始暴力也没写出来,想着如果找到与val相等的值,是后面一个值往前移动覆盖掉这个值,但是如果后面的值也是等于val怎么办呢,然后就没思路了。一定要好好掌握双指针的方法。