一、数组学习
1.数组内存
讨论数组的存储之前先复习一下java的存储分区,java的五大存储区域,栈、堆、方法区、本地方法栈、寄存器。
数组所在的方法的代码部分存放在方法区,在运行时调入栈内,而数组变量作为方法所属的引用变量,与此方法一起存储在栈内。但是存储时数组分为两部分,一部分时数组名,作为引用变量,其本质是一个地址。另一部分是数组体,这部分作为一个对象而被放在堆内存里。
2.数组内删除元素
在删除元素时,思想就是从目标元素开始,后面的元素覆盖前面的元素,走一个循环。但是有一点要明确那就是数组的右边界是会留下脏数据的,即arr.length这个数组本身的属性并没有改变。
3.二维数组空间
数组同行是连续的,这一点毋庸置疑,与一维数组一致。但是二维数组的实现上c++与java有区别,c++的二维数组整体是连续的,而java二维数组只满足行连续。
二、二分查找
题目链接https://leetcode.cn/problems/binary-search/
对于刚考完研的我来说二分查找真的完全不用过脑子,甚至没有思考就写出来了,然后一遍过。结果写完就发现问题了。我写了一个for循环(如下),感觉自己像个傻子,写for循环都遍历了还写什么二分,完全失去了O(log2n)的优势,羞愧不已赶紧改成while。
当然二分法其实最重要的是边界问题,这个在考研的时候就有强调过,主要是注意右边界能不能取到的问题,我个人习惯将left和right看成数组的index指针,所以直接给的right = length-1,保证能取到,所以循环停止的条件就是left = right = mid的时候。
class Solution {
public int search(int[] nums, int target) {
int left = 0,right = nums.length - 1, mid = 0;
//for(int i = 0;i < length; i++)
while(left <= right){
mid = (left + right) / 2;
if(target == nums[mid]){
return mid;
}
else if(nums[mid] > target){
right = mid -1;
//1 2 3 4 5 6
}
else if(nums[mid] <target){
left = mid + 1;
}
}
return -1;
}
}
三、移除元素
题目链接:https://leetcode.cn/problems/remove-element/
直接暴力解,二重循环删除。当然这个只是我脑子宕机的写法,真正在项目里写个O(n2)就等死吧(吐槽一下我第一次还忘了写 i–,忘记了在后元素覆盖前面元素时,指针 i 本身所指的元素其实已被删除了,此时执行 i++会跳过所删除元素后面的一个元素,而如果出现两个连续的元素要删除,如122304 删除 2 ,一轮下来会变成 12304 )。
class Solution {
public int removeElement(int[] nums, int val) {
int length = nums.length;
for(int i = 0; i < length; i++){
if(nums[i] == val){
//1223042
for(int j = i;j <length-1;j++){
nums[j] = nums[j+1];
}
i--;
length--;
}
}
return length;
}
}
真正在项目中遇到这类问题时,肯定不能用循环嵌套的,真正的解法是双指针法。
一个快指针,一个慢指针。快指针负责遍历数组,找到目标元素,慢指针负责记录目标元素应该所在的位置,将目标元素赋值到慢指针所指向的位置即可。
class Solution {
public int removeElement(int[] nums, int val) {
int length = nums.length;
int i = 0,j = 0;//定义快慢指针
for(i = 0;i < length;i++){//快指针遍历整个循环
//2233 2
if(nums[i] != val){
//j++; 想错了,这样虽然会得到删除元素后数组的长度,但是并没有移动元素的位置
nums[j] = nums[i];//还是要移动一下元素
j++;
}
}
return j;
}
}
总结
两道都是leetcode上的简单题,思路上基本是没什么问题的,但是在具体的编写时还是出现了很多问题。这也暴露出来了我在考研期间太长时间没写代码带来的问题——手生了。现在的状态是难得不会,简单的写的时候会出现各种问题。希望自己能在两个月的学习里面找回写代码的手感,提升自己写代码的水平。