数组理论基础
1. 数组是存放在连续内存空间上的相同类型数据的集合。
2. 数组内存空间的地址是连续的。(因此在删除或者增添元素的时候,就难免要移动其他元素的地址。)
3. 数组的元素不能删除,只能覆盖。
4. C++中二维数组在地址空间上是连续的。
leetcode704. 二分查找
这题是二刷了,一看到题就马上知道思路,但是用代码实现起来还是有些问题在的,所以还得多写代码。在面试笔试的时候也是这样,很多题虽做过但实现起来不顺利,没做过的能想出思路但实现不了,应该还是写代码写少了,继续加油。
总结一下这题的注意点:
- 弄清楚哪些才是变量(要操作的数组,指向数组的左右边界指针left和right,中间值的下标mid)。只要改变left和right指针就能改变要操作的数组nums,因此变量只有left,right,mid。
- 循环不变量规则。弄清楚哪些是不变量,区间的定义就是不变量。要在二分查找的过程中,保持不变量,就是在while寻找中每一次边界的处理都要坚持根据区间的定义来操作,这就是循环不变量规则。
- 防止溢出操作:left + ((right - left) >> 1)。位运算>>效率比 /2 效率高。
- 开头先排除掉一些特殊情况,提升代码效率。
class Solution {
public int search(int[] nums, int target) {
int len = nums.length;
// 当 target 小于 nums[0] 或大于 nums[len - 1] 时,直接返回-1,避免进入while循环进行多次计算
if (target < nums[0] || target > nums[len - 1]) {
return -1;
}
// 左闭右闭区间
int left = 0;
int right = len - 1;
while (left <= right) {
int mid = left + ((right - left) >> 1); // 防止溢出 等同于(left + right)/2
if (target > nums[mid]) {
left = mid + 1;
} else if (target < nums[mid]) {
right = mid - 1;
} else {
return mid;
}
}
return -1;
}
}
拓展题目(二刷再做,现在没时间)
leetcode35. 搜索插入位置
leetcode34. 在排序数组中查找元素的第一个和最后一个位置
leetcode27. 移除元素
这题也是二刷,虽然在不看提示的情况下最后也写出来提交AC了,但是前几次提交都通过不了,主要是没看清题目的具体意思。还有这里建议用本地IDE来做算法题(建了个随想录的文件夹,不同数据结构的题目分别放好来),一是方便debug,二是效率高(写代码有提示、运行程序比浏览器快、方便写输入测试样例等),下面除了有我力扣上的代码,也有在IDE上的代码展示。
总结一下这题的注意点:
- 弄清楚题目的意思(返回的是新数组的长度以及新数组)。在第一遍提交时没AC
- 双指针的起始点;
- 根据题意,if() 的判断条件设置为查找值不等于val会更方便。因为目标是把等于val的值都移到数组尾部,不等于val的元素都放在数组头部,所以当查找值不等于val时才交换slow和fast指向的元素,这样就能达成目标。
- 我的代码和随想录的法一有点出入。随想录上的是直接覆盖掉等于val的元素了,而我的是把等于val值的元素都移到了数组尾部。
- 法二:相向双指针法。等有空再写
在力扣上写题:
class Solution {
// 法一:快慢双指针
public int removeElement(int[] nums, int val) {
int len = nums.length;
// 定义快慢指针
int slow = 0;
int fast = 0;
// 遇到不等于val值的元素,则进行交换,并使慢指针右移一位;快指针在每一次循环都要右移一位;
while (fast < len) {
if (nums[fast] != val) {
int tmp = nums[fast];
nums[fast] = nums[slow];
nums[slow] = tmp;
slow++;
}
fast++;
}
int ans = slow;
return ans;
}
}
在本地IDE上写题:
public class leetcode27 {
public static int removeElement(int[] nums, int val) {
int len = nums.length;
// 定义快慢指针
int slow = 0;
int fast = 0;
// 遇到不等于val值的元素,则进行交换,并使慢指针右移一位;快指针在每一次循环都要右移一位;
while (fast < len) {
if (nums[fast] != val) {
int tmp = nums[fast];
nums[fast] = nums[slow];
nums[slow] = tmp;
slow++;
}
fast++;
}
int ans = slow;
return ans;
}
// 在main方法里调用
public static void main(String[] args) {
int[] nums = {3,2,2,3};
//int[] nums = {0,1,2,2,3,0,4,2};
//int[] nums = {3,3,3,3};
int val = 3;
// 调用函数
int ans = removeElement(nums, val);
System.out.println(ans);
}
}
拓展题目(二刷再做,现在没时间)
leetcode26. 删除排序数组中的重复项
leetcode283. 移动零
leetcode844. 比较含退格的字符串
leetcode977. 有序数组的平方