持续记录刷题打卡。。。
1. 数组
数组理论基础
数组是存放在连续内存空间上的相同类型数据的集合
文章链接:https://programmercarl.com/%E6%95%B0%E7%BB%84%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html
1. 二分查找(leetcode704)
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target
思路:二分查找比较简单,就是取中间值和目标值进行大小比较,主要是
对于边界的判断,对于数组,一般题目都是左闭右闭,注意位置1,和位置2,位置3。在循环中要固定住不变的边界。循环不变量。
可以想象举例是左闭右开呢,位置1:因为取不到nums.length,此时如果还是nums.length - 1,那比较时直接忽略了最后一个位置的数
代码实现
public int search(int[] nums, int target) {
//赋值左右指针
int left = 0;
int right = nums.length - 1; //位置1,如果是左闭右开就是nums.length了
//循环比较
while(left <= right){ //位置2 如果是左闭右开就是left<right
//取中间值
int middle = (left + right) >> 1;
取中间值与目标值比较
if(nums[middle] > target){
right = middle-1; //位置3 如果是左闭右开就是right=middle
} else if (nums[middle] < target) {
left = middle+1;
}else {
return middle;
}
}
return -1;
}
时间复杂度:O(log n)
空间复杂度:O(1)
总结
其实主要就是对区间的定义没有理解清楚,在循环中没有始终坚持根据查找区间的定义来做边界处理。区间的定义就是不变量,那么在循环中坚持根据查找区间的定义来做边界处理,就是循环不变量规则。
拓展题目:
35.搜索插入位置 和 34. 在排序数组中查找元素的第一个和最后一个位置 (周末刷)
2.移除元素 ( leetcode27)
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
前提条件:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改
思路: 双指针,利用快慢双指针的思想,将数组上等于val的值全部覆盖掉
通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
定义快慢指针
快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
慢指针:指向更新 新数组下标的位置
public int removeElement(int[] nums, int val) {
//慢指针
int slow = 0;
for (int fast = 0; fast < nums.length; fast++) {
//快指针判断是否等于val,不等于的话,将快指针的值赋值给慢指针
// slow和fast同时后移
if(nums[fast] != val){
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
时间复杂度:O(n)
空间复杂度:O(1)
暴力法:直接两个循环,第一个循环找val,第二个循环将后面所有值向前移动一位
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;
}