代码随想录二刷——数组

 🌈hello,你好鸭,我是Ethan,西安电子科技大学大三在读,很高兴你能来阅读。

✔️目前博客主要更新Java系列、项目案例、计算机必学四件套等。
🏃人生之义,在于追求,不在成败,勤通大道。加油呀!

🔥个人主页:Ethan Yankang
🔥推荐:史上最强八股文 || 一分钟看完我的上千篇博客

🔥温馨提示:划到文末发现专栏彩蛋   点击这里直接传送

🔥本篇概览:数据结构与算法 || 详细讲解了代码随想录二刷的数组篇。🌈⭕🔥


【计算机领域一切迷惑的源头都是基本概念的模糊,算法除外】


🌈序言

算法乃我长久之志也,此关必过。如今二刷代码随想录,必然收获良多,加油不懈怠!

本次只写题目+代码实现(主要的点全都写在代码注释里面),多题合一。


🔥 前一篇章

🔥 代码随想录系列所有算法精讲一键查阅


题目:

704. 二分查找

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1

已经统一了二分法使用对称的写法left<=right

注意这里一定要使用((right-left)>>1)将整体括起来,因为这里>>运算符优先级低于+

class Solution {
    public int search(int[] nums, int target) {
        // 避免当 target 小于nums[0] nums[nums.length - 1]时多次循环运算
        if (target < nums[0] || target > nums[nums.length - 1]) {
            return -1;
        }
        int left = 0, right = nums.length - 1;

        while (left <= right) {
            int mid = left + ((right - left) >> 1);
            if (nums[mid] == target)
                return mid;
            else if (nums[mid] < target)
                left = mid + 1;
            else if (nums[mid] > target)
                right = mid - 1;
        }
        return -1;
    }
}


35. 搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O(log n) 的算法

class Solution {
    public int searchInsert(int[] nums, int target) {
        int length=nums.length;
        int left=0;
        int right=length-1;
        while (left<=right){
            int middle=left+((right-left)>>1);
            if (nums[middle]==target){
                return middle;
            } else if (nums[middle]>target){
                right=middle-1;
            } else if (nums[middle]<target){
                left=middle+1;
            }
        }
         或者return left(因为最后退出循环前一步的情形一定是left==right。
无论是left前移还是right后移,位置都是最后一个(最为匹配。二分法的精髓本就是步步最佳匹配。
所以返回left与right+1都是一样的))
        // return right+1;
        return left;
    }
}


27. 移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。

假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作:

  • 更改 nums 数组,使 nums 的前 k 个元素包含不等于 val 的元素。nums 的其余元素和 nums 的大小并不重要。
  • 返回 k

原地、移除元素、不使用额外空间==>100%双指针

class Solution {
    public int removeElement(int[] nums, int val) {
        int length=nums.length;
        int slowIndex=0;
        int fastIndex=0;
        while (fastIndex<length){
            if(nums[fastIndex]!=val){
                nums[slowIndex++]=nums[fastIndex];
            }
            fastIndex++;
        }
        return slowIndex;
    }
}


34. 在排序数组中查找元素的第一个和最后一个位置

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

这里分而治之,左右边界分开查找

最后target可能在中间的情况一定要判断(rightBorder-leftBorder>1),因为如果target没有的话,会出现RB<LB的情况,而这种情况,返回[-1,-1]

例如 1 2 3 5 6 判断4  ==》边界范围是RB=2,值为3;LB=3,值为5,所以是[3,2]显然是错的。

class Solution {
    int leftBorder=-1;
    int rightBorder=-1;
    
    public int[] searchRange(int nums[]  ,int target) {
        int length = nums.length;
//        先判断特殊情况.在两边的情况去除之
        if(length==0)return new int[]{-1,-1};
        if(target < nums[0] || target > nums[length - 1]) return new int[]{-1, -1};
        
        leftBorder = getLeftBorder(nums, target);
        rightBorder = getRightBorder(nums, target);
        
        // 这里正确答案+1,-1的情况是因为跳出循环的时候索引处一定不是本元素
        return (rightBorder-leftBorder>1)?new int[]{leftBorder+1, rightBorder-1}:new int[]{-1,-1};
    }


    private int getLeftBorder(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        while (left <= right) {
            int mid = left + ((right - left) >> 1);
            if (nums[mid] >= target) {
                right = mid - 1;
                leftBorder = right;
            } else {
                left = mid + 1;
            }
        }
        return leftBorder;
    }


    private int getRightBorder(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        while (left <= right) {
            int mid = left + ((right - left) >> 1);
            if (nums[mid] <= target) {
                left = mid + 1;
                rightBorder=left;
            } else {
                right = mid - 1;
            }
        }
        
        return rightBorder;
    }

}



📣非常感谢你阅读到这里,如果这篇文章对你有帮助,希望能留下你的点赞👍 关注❤收藏✅ 评论💬,大佬三连必回哦!thanks!!!
📚愿大家都能学有所得,功不唐捐!

👇下面是专栏彩蛋系列,你会喜欢的!(为了避免影响算法的简洁与优美,这里直接将之前的几十个专栏简化为3个部分,不过你点击开后发现惊喜。)👇


💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖

热门专栏

🌈🌈专栏彩蛋系列

🌈🌈史上最全八股文,欢迎收藏

🌈🌈一篇文章了解我的上千篇博客

💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值