首页 > 编程语言 >算法学习 |Day 1 数组基础 704. 二分查找,27. 移除元素

算法学习 |Day 1 数组基础 704. 二分查找,27. 移除元素

时间:2023-09-20 16:56:08浏览次数:52  
标签:27 target nums 704 mid high int low 移除

704.二分查找

  • 思路:二分查找的前置条件是数组有序且无重复元素,每次通过改变边界值来缩小查找范围。

自己写的:

可以看到对边界的判断存在问题,基本思路是左闭右闭,但是while循环的判断是按照左闭右开来写的。对于数组中仅包含一个元素且该元素是目标函数的情况会出错。重新调试后添加了一个low==high的判断,实际上可以整合到while循环里。

    public int search(int[] nums, int target) {
        int low = 0, high = nums.length - 1, mid = (low + high) / 2;
        while (low < high){
            int temp = nums[mid];
            if(temp == target){
                return mid;
            }else{
                if(temp > target){
                    high = mid - 1;   
                }else{
                    low = mid + 1;
                }
                 mid = (low + high) / 2;
            } 
        }
	//对于nums=[5]且target=5的情况重新进行边界分析后添加的判断
        if(low == high && nums[low] == target){
            return low;
        }
        return -1;
	}

左闭右闭

    public int search(int[] nums, int target) {
        int low =0, high = nums.length - 1;     //定义target在左闭右闭区间[low,high]里
        while(low <= high){                     //取等号,因为low==high的情况是合法的
            int mid = low + ((high - low) / 2); //这种写法可以避免两个int型相加溢出
            if(nums[mid] == target){            //找到target,返回下标mid
                return mid;
            }else if(nums[mid] < target){       //tareget在右半区间,low右移
                low = mid + 1;
            }else if(nums[mid] > target){       //target在左半区间,high左移
                high = mid - 1;
            }
        }
        return -1;                              
    }

左闭右开

    public int search(int[] nums, int target) {
        int low = 0, high = nums.length;    //定义target在左闭右开区间[low,high)中,右边界是不取的,所以high不用-1
        while(low < high){                  //对于左开右闭区间,low==high不合法
            int mid = low + ((high - low) / 2);
            if(nums[mid] == target){
                return mid;
            }else if(nums[mid] < target){   //target在右半部分,右移low,由于区间左闭,故low=mid+1
                low = mid + 1;
            }else if(nums[mid] > target){   //target在左半部分,左移high,由于区间右开,故high=mid
                high = mid;
            }
        }
        return -1;
    }

相关问题

35.搜索插入位置

自己写的

        public int searchInsert(int[] nums, int target) {
        int low = 0, high = nums.length - 1;
        while(low <= high){
            int mid = low + ((high - low) / 2);
            if(nums[mid] == target){
                return mid;
            }else if(nums[mid] < target){
                low = mid + 1; 
            }else if(nums[mid] > target){
                high = mid - 1;
            }
        }
        return low;
    }

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

自己写的

二分法找到第数组中第一个target后,向两边扫描找到边界。

    public int[] searchRange(int[] nums, int target) {
        int low = 0, high = nums.length - 1;
	//用于储存始末下标
        int[] locas = new int[]{-1,-1};
        while(low <= high){
            int mid = low + ((high - low) / 2);
            if(nums[mid] == target){
                locas[0] = mid;
                locas[1] = mid;
                int left = mid - 1, right = mid + 1;
		//向左边搜索第一个目标元素
                while(left >= 0 && nums[left] == target){
                    locas[0] = left;
                    left--;
                }
		//向右边搜索最后一个目标元素
                while(right < nums.length && nums[right] == target){
                    locas[1] = right;
                    right++;
                }
                break;
            }else if(nums[mid] < target){
                low = mid + 1;
            }else if(nums[mid] > target){
                high = mid - 1;
            }
        }
        return locas;
    }

使用二分法分别探索边界

存在三种情况

  • target的值不在nums区间内
  • target的值在nums区间内但不是nums的元素
  • target的值在nums区间内且是nums的元素

探索左边界,即寻找下标最小的与target值相等的元素
探索右边界,即寻找下标最大的与target值相等的元素


27. 移除元素

自己写的:

遍历数组,如果当前元素与val值相等,就用最后一个元素覆盖它并减小数组长度,并再次检查是否覆盖后的值依旧与val相等

    public int removeElement(int[] nums, int val) {
        int len = nums.length;  //记录数组长度
        for(int i = 0;i < len;i++){
            if(nums[i] == val){ //如果当前元素值等于val,用数组最后一个值覆盖并减小数组的长度
                nums[i] = nums[len - 1];
                len--;
                i--;            //存在数组最后一个值也是val的可能,再次检查
            }
        }
        return len;
    }

暴力法

用两个for循环,当第一个循环找到与val值相等的元素时,通过第二个循环将元素整体前移并减小数组长度

    public int removeElement(int[] nums, int val) {
        int len =nums.length;
        for(int i = 0;i < len;i++){
            if(nums[i] == val){
                for(int j = i + 1;j < len;j++){
                    nums[j - 1] = nums[j];
                }
                len--;
                i--;
            }
        }
        return len;
    }

快慢指针

快指针扫描旧数组,慢指针标记新数组下标。
当快指针扫描到的元素不等于val时赋给慢指针标记的位置并更新慢指针;
若快指针扫到的元素等于val时,只更新快指针,跳过该元素

    public int removeElement(int[] nums, int val) {
        int slow = 0;
        for(int fast = 0; fast < nums.length; fast++){
            if(nums[fast] != val){
                nums[slow] = nums[fast];
                slow ++;
            }
        }
        return slow;
    }

标签:27,target,nums,704,mid,high,int,low,移除
From: https://www.cnblogs.com/rong-hee/p/17717207.html

相关文章

  • abc278题面
    A问题陈述给你一个长度为\(N\)的序列\(A=(A_1,A_2,\dots,A_N)\)。你正好执行了下面的操作\(K\)次:删除\(A\)的初始元素,并在\(A\)的尾部追加一个\(0\)。操作后打印\(A\)的所有元素。限制因素\(1\leqN\leq100\)\(1\leqK\leq100\)\(1\leqA_i\leq1......
  • dns缓存中毒43.227.199.x
    什么是DNS缓存中毒DNS缓存中毒是一种网络攻击,它使您的计算机误以为它会到达正确的地址,但事实并非如此。攻击者使用DNS缓存中毒来劫持互联网流量并窃取用户凭据或个人数据。DNS缓存中毒攻击也称为DNS欺骗,它试图诱骗用户将其私人数据输入不安全的网站。什么是DNS缓存在讨论攻击之......
  • 【POJ 3278】Catch That Cow 题解(广度优先搜索)
    农夫约翰已被告知一头逃亡奶牛的位置,并想立即抓住她。他从一条数字线上的N点(0≤N≤100000)开始,奶牛在同一条数字线上的K点(0≥K≤100000)。农夫约翰有两种交通方式:步行和坐车。*步行:FJ可以在一分钟内从任何点X移动到点X-1或X+1*坐车:FJ可以在一分钟内从任何X点移动到2×X点。如果奶......
  • Three.js——八、坐标、更改模型原点、移除、显示隐藏模型对象
    世界坐标.getWorldPosition()基础坐标也就是模型的.position属性世界坐标:就是模型资深.position和所有父对象.position累加的坐标用.getWorldPosition()属性需要用三维向量表示摸个坐标后方可读取例如:constgeometry=newTHREE.BoxGeometry(100,100,100);constmaterial......
  • 27_linux 网络编程
    linux网络编程HTTP协议对应于应用层,Socket则是对ICP/IP协议的封装和应用Socket的出现只是使得程序员更方便地使用ICP/IP协议栈而已,是对ICP/IP协议的抽象,从而形成了我们知道的一些最基本的函数接口,比如create、listen、connect、accept、send、read和write等。......
  • 【POJ 3278】Catch That Cow 题解(深度优先搜索)
    农夫约翰已被告知一头逃亡奶牛的位置,并想立即抓住她。他从一条数字线上的N点(0≤N≤100000)开始,奶牛在同一条数字线上的K点(0≥K≤100000)。农夫约翰有两种交通方式:步行和坐车。*步行:FJ可以在一分钟内从任何点X移动到点X-1或X+1*坐车:FJ可以在一分钟内从任何X点移动到2×X点。如果奶......
  • 【学习笔记】(27) 整体 DP
    1.算法简介整体DP就是用线段树合并维护DP。有一些问题,通常见于二维的DP,有一维记录当前x的信息,但是这一维过大无法开下,O(nm)也无法通过。但是如果发现,对于x,在第二维的一些区间内,取值都是相同的,并且这样的区间是有限个,就可以批量处理。所以我们就可以用线段树来维护DP。......
  • 203.移除链表元素 707.设计链表 206.反转链表
    203.移除链表元素力扣题目链接(opensnewwindow)题意:删除链表中等于给定值val的所有节点。示例1:输入:head=[1,2,6,3,4,5,6],val=6输出:[1,2,3,4,5]示例2:输入:head=[],val=1输出:[]示例3:输入:head=[7,7,7,7],val=7输出:[]思路操作链表的两种方式:直接使用原来的......
  • CentOS8 ifconfig时显示127.0.0.1问题
    CentOS8ifconfig时ip地址为127.0.0.1参考:https://blog.csdn.net/weixin_43888891/article/details/131893425?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2~default~YuanLiJiHua~Position-3-131893425-blog-131429967.235^v38^pc_relev......
  • 27、Flink 的SQL之SELECT (SQL Hints 和 Joins)介绍及详细示例(2-2)
    Flink系列文章[1、Flink部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接][13、Flink的tableapi与sql的基本概念、通用api介绍及入门示例][14、Flink的tableapi与sql之数据类型:内置数据类型以及它们的属性][15、Flink的t......