当前位置:首页 > 技术 > 正文内容

Java 数组原地修改算法与二分搜索边界控制解析

访客 技术 2026年9月26日 12

数组元素的原地移除策略

在处理类似 LeetCode 27 号题目时,核心任务是剔除指定值并返回新的有效长度。由于编程语言中的数组通常是定长结构,所谓的"移除"实际上是通过后续数据前移覆盖目标值,从而压缩逻辑上的数组容量。

方案一:常规遍历覆盖

最直观的思路是遍历每一个位置,一旦发现匹配目标值的元素,就将其后面的所有元素依次向前移动一位。这种方法的时间复杂度较高,但在理解数组内存移动方面具有教学意义。

class Solution {
    public int removeItem(int[] arr, int targetVal) {
        int currentSize = arr.length;
        
        for (int i = 0; i < currentSize; ) {
            if (arr[i] == targetVal) {
                // 发生位移操作
                for (int k = i; k < currentSize - 1; k++) {
                    arr[k] = arr[k + 1];
                }
                // 索引回退以便重新检查当前位置的新元素
                i--; 
                currentSize--;
            } else {
                // 仅当不匹配时才前进
                i++;
            }
        }
        return currentSize;
    }
}

注意:循环条件必须基于动态变化的数组长度,否则可能引发越界或无效迭代。此外,若发现待移除元素,指针需要回退以确保新移入的值被正确校验。

方案二:快慢指针协同(推荐)

为了将时间复杂度降低至线性级别,可以采用双指针技术。定义一个读取指针扫描原数据,一个写入指针记录保留数据的位置。读取指针负责筛选合法值,写入指针负责紧凑排列。

public class Solution {
    public int compactArray(int[] data, int valueToRemove) {
        int writeIdx = 0;
        int totalLen = data.length;
        
        for (int readIdx = 0; readIdx < totalLen; readIdx++) {
            // 跳过目标值,仅复制非目标值
            if (data[readIdx] != valueToRemove) {
                data[writeIdx++] = data[readIdx];
            }
        }
        return writeIdx;
    }
}

该方法只需遍历一次数组,空间复杂度为常数级,是解决此类问题的标准范式。


二分查找的区间边界处理

二分检索的核心在于每次迭代将搜索范围缩小一半。实现的关键难点在于维护循环不变量,即明确区间的开闭状态,这直接决定了终止条件和边界更新逻辑。

模式 A:闭区间 [left, right]

在此模式下,左右边界均包含在内。循环继续的条件是左边界小于等于右边界。当计算出的中点不符合目标时,需根据比较结果调整边界。

class BinarySearcher {
    public int findTarget(int[] list, int goal) {
        int l = 0;
        int r = list.length - 1; // 初始化为最后一个有效索引
        
        while (l <= r) {
            int mid = l + (r - l) / 2;
            
            if (list[mid] == goal) {
                return mid;
            } else if (list[mid] < goal) {
                // 目标在右半部分,排除当前中点
                l = mid + 1;
            } else {
                // 目标在左半部分,排除当前中点
                r = mid - 1;
            }
        }
        return -1;
    }
}

模式 B:半开区间 [left, right)

这种写法常见于 C++ STL 风格或特定语言库中。右边界代表不包含该索引,因此初始右值为数组长度。循环条件变为严格小于。当右侧边界收缩时,直接赋值给中点即可。

class BinarySearcherOpen {
    public int locateIndex(int[] sequence, int query) {
        int left = 0;
        int right = sequence.length; // 右边界不可达
        
        while (left < right) {
            int pivot = left + (right - left) / 2;
            
            if (sequence[pivot] == query) {
                return pivot;
            } else if (sequence[pivot] < query) {
                // 搜索范围变为 [pivot+1, right)
                left = pivot + 1;
            } else {
                // 搜索范围变为 [left, pivot),pivot 本身被排除
                right = pivot;
            }
        }
        return -1;
    }
}

两种实现最终都能达成目的,关键在于开发者需始终保持对循环终止状态的清晰认知,避免死循环或索引越界。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。