代码随想录算法训练营第一天| 数组理论基础 |704. 二分查找、27. 移除元素。

数组

  • 数组是存放在连续内存空间上的相同类型数据的集合。
  • 二维数组的地址:java里面没有指针,看不到每个元素的地址情况,输出的是经过处理后的数值。
public static void test_arr() {
    int[][] arr = {{1, 2, 3}, {3, 4, 5}, {6, 7, 8}, {9,9,9}};
    System.out.println(arr[0]);
    System.out.println(arr[1]);
    System.out.println(arr[2]);
    System.out.println(arr[3]);
}

'''
输出如下:
[I@7852e922
[I@4e25154f
[I@70dea4e
[I@5c647e05

'''
  • 数组的元素不能删除,只能覆盖。在对数组增删时,除了要处理待增删的元素,还需要移动待增删元素的后面的元素。


704 二分查找

链接:https://leetcode.cn/problems/binary-search/description/

关键词:有序、整型数组、无重复元素、查找、时间复杂度:O(log n)

1、二分查找需要注意的地方就是确定边界条件,也就是数组的区间,一般两种情况:       

  • 左闭右闭、
  • 左闭右开
  • (左开右开和左开右闭和上面类似)

2、代码:

//我写的
class Solution {
    public int search(int[] nums, int target) {
        //左闭右闭
        int left=0;
        int right=nums.length-1;
        while(left<=right){
            int middle;
            middle=(left+right)/2;
            if(target==nums[middle]){
                return middle;
            }
            if(target>nums[middle]){
                left=middle+1;
            }else{
                right=middle-1;
            }

        }
        return -1;
    }
}
//我写的
class Solution {
    public int search(int[] nums, int target) {  
  //左闭右开:
    int left=0;
    int right=nums.length-1;
    while(left<right){
        int middle=(left+right)/2;
        if(nums[middle]==target){
            return middle;
        }
        if(nums[middle]<target){
                left=middle+1;
        }else if(nums[middle]>target){
                right=middle;
        }
    }
    return -1;  
}
}

3、犯的错:

在算middle的时候,我用的:

int middle=(left+right)/2;

这种写法有溢出的风险, 因为int占四个字节,如果left+right的值超过了四个字节(-2147483648~2147483647),是会溢出的,结果会出错!

所以可以改成这种写法:

int mid = left + ((right - left) / 2);

 最后,位运算相对来说会快一点,所以可以进一步改成这种写法:

int mid = left + ((right - left) >> 1);

 这也是随想录里的方法。


27. 移除元素

链接:https://leetcode.cn/problems/remove-element/

关键词:原地修改、数组

1、代码

//暴力搜索
//先找到等于val的元素,再将这个元素右边的那些元素往左移一位,同时让数组的长度减一。
//下次搜索的时候,还是从相同的索引开始,如果用for循环,要注意

class Solution {
    public int removeElement(int[] nums, int val) {
        int k=nums.length;
        int i=0;
        while(i<k){
            if(nums[i]!=val){
                i++;
                continue;
            }else{
                for(int j=i;j<k-1;j++){
                    nums[j]=nums[j+1];
                }k--;
            }
        }
        return k;

    }
}
//双指针(快慢指针)
//用两个指针,第一个指针遍历数组,找符合要求的元素,所以while的中止条件是fast<nums.length。
//第二个指针更新数组的下标/值。
//注意第一个指针不管有没有找到符合要求的元素,都是要加1的。第二个指针只有在找到元素后,才加1.
class Solution {
    public int removeElement(int[] nums, int val) {
        int fast=0;
        int slow=0;
        while(fast<nums.length){
            if(nums[fast]!=val){
                nums[slow]=nums[fast];
                slow++;
            }
            fast++;
        }
        return slow;
    }
}
//相向指针
class Solution {
    public int removeElement(int[] nums, int val) {

        int left=0;
        int right=nums.length-1;
        while(left<=right){
            while(left<=right&&nums[left]!=val){
                left++;
            }
            while(right>=left&&nums[right]==val){
                right--;
            }
            if(left<right){
            nums[left]=nums[right];
            left++;
            right--;
            } 
        }
        return left;

    }
}

2、问题:

暴力解法:我开始用的for循环,但是在外层循环时,没有注意到数组元素左移之后,下次外层循环仍然要从上次的索引开始,所以外层循环的i要减一;

for(int i=0;i<k;i++){//错误写法
            if(nums[i]!=val){
                i++;
                continue;
            }else{
                for(int j=i;j<k-1;j++){
                    nums[j]=nums[j+1];
                }k--;
                //这里应该加一个i--;
            }
}

双指针:快慢指针相对来说容易一点,相向指针写着写着我就晕了,循环条件各种混乱。。。。QAQ

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值