代码随想录_leetcode刷题day01_704二分查找_27移除元素

一、数组学习
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上的简单题,思路上基本是没什么问题的,但是在具体的编写时还是出现了很多问题。这也暴露出来了我在考研期间太长时间没写代码带来的问题——手生了。现在的状态是难得不会,简单的写的时候会出现各种问题。希望自己能在两个月的学习里面找回写代码的手感,提升自己写代码的水平。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值