算法打卡:第一章 数组part01

1. 今日收获:数组理论基础,二分查找,快慢指针,相向双指针

2. 数组理论基础:

(1)数组是存放在连续内存空间上的相同类型数据的集合。

(2)Java二维数组的排列方式

3. 二分查找,例题 704. 二分查找

题目:704. 二分查找

思想:从数组的两个端点开始,每次将目标值和区间中间的元素相比,根据比较结果可以减小区间范围为原来的一半

方法一:区间左闭右闭

class Solution {
    public int search(int[] nums, int target) {
        int left=0;
        int right=nums.length;
​
        // 左闭右开
        while(left<right){
            int mid=left+((right-left)>>1);
            // 相等
            if (nums[mid]==target){
                return mid;
            }
​
            if (nums[mid]>target){  // 目标在左区间
                right=mid;
                continue;
            }
​
            if (nums[mid]<target){  // 目标在右区间
                left=mid+1;
                continue;
            }
        }
​
        return -1;
    }
}

方法二:区间左闭右开

class Solution {
    public int search(int[] nums, int target) {
        int left=0;
        int right=nums.length;
​
        // 左闭右开
        while(left<right){
            int mid=left+((right-left)>>1);
            // 相等
            if (nums[mid]==target){
                return mid;
            }
​
            if (nums[mid]>target){  // 目标在左区间
                right=mid;
                continue;
            }
​
            if (nums[mid]<target){  // 目标在右区间
                left=mid+1;
                continue;
            }
        }
​
        return -1;
    }
}

总结:需要掌握循环不变量:区间的开闭。如果端点处是开区间,则目标值不在端点处;如果是闭区间,则目标值不在端点处,就需要考虑相等的情况。上面两种方法的不同之处在于right初始值的定义,循环终止条件的判断,以及缩小区间范围时与mid的关系

4. 快慢指针,例题 27. 移除元素

题目:27. 移除元素

思想:方法一暴力解法:首先遍历数组,遇到等于val的元素就移动数组后面的元素,但是要记得移动之后修改数组的长度和指针的位置;方法二是快慢指针,快指针出去"闯荡江湖",寻找满足条件的"好苗子",找到之后就赋值给"守家"的慢指针

方法一:暴力解法

class Solution {
    public int removeElement(int[] nums, int val) {
        // 暴力解法,两个for循环
        int len=nums.length;
​
        for (int i=0;i<len;i++){  
            // 判断是否需要移除元素
            if (nums[i]==val){
                // 覆盖元素
                for (int j=i;j<len-1;j++){
                    nums[j]=nums[j+1];
                }
                i--;  // * 移动指针,减少长度
                len--;
            }
        }
        return len;
    }
}

方法二:快慢指针

class Solution {
​
    public int removeElement(int[] nums, int val) {
​
        // 双指针法
​
        int slow=0;
​
        int len=nums.length;
​
        for (int fast=0;fast<len;fast++){
​
            if (nums[fast]!=val){  // 满足条件
​
                nums[slow++]=nums[fast];  // 慢指针赋值
​
            }
​
        }
​
        return slow;
​
    }
​
}

总结:快慢指针可以在一个数组上遍历一次完成任务,之后在遇到类似需要两个for操作时,可以考虑这样的解法,一个指针"寻找",一个指针"收集"。

5. 相向双指针,例题 977.有序数组的平方

题目:977.有序数组的平方

思想:定义两个指针分别指向数组的头和尾,哪一个指针指向元素的平方比较大,就将数据写入结果数组,然后再移动对应的指针,指向此方向的下一个元素

方法:相向双指针

class Solution {
    public int[] sortedSquares(int[] nums) {
        int len=nums.length;
        int[] result=new int[len];
        int k=len-1;
        int i=0;  // 相向双指针
        int j=len-1;
​
        while (i<=j){
            if (nums[i]*nums[i]>nums[j]*nums[j]){
                result[k--]=nums[i]*nums[i];
                i++;
            }else {
                result[k--]=nums[j]*nums[j];
                j--;
            }
        }
        return result;
    }
}

总结:同向指针和双向指针的区别在于方向的不同,27题可以从头到尾遍历数组,977题中最大元素可能是头尾元素的平方,两个指针都向中间聚拢。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值