目录
回复内容:
不带修改的静态查询
仅带添加操作的动态查询,不改变顺序
带添加删除操作(较大数)的动态查询
首页 后端开发 php教程 如何快速取出所对应的值

如何快速取出所对应的值

Dec 01, 2016 am 01:27 AM
php 算法

一个php的索引数组,数组里面的值为从1到100之间的整数(不重复),并且数值可能是断续,也就是可能有就7,9但是没有8。并且顺序是打乱的,也就是,不是从1排到100这样的

现在假设$a=50, 怎样最快的取出==$a或者是跟$a最相邻的两个数值呢?

对了其中数组中的值不一定有等于$a的

回复内容:

一个php的索引数组,数组里面的值为从1到100之间的整数(不重复),并且数值可能是断续,也就是可能有就7,9但是没有8。并且顺序是打乱的,也就是,不是从1排到100这样的

现在假设$a=50, 怎样最快的取出==$a或者是跟$a最相邻的两个数值呢?

对了其中数组中的值不一定有等于$a的

  1. array_search — 在数组中搜索给定的值,如果成功则返回相应的键名

  2. 获得键名,$arr[$key-1], $arr[$key+1]即可

楼上的已经非常简单了,不过需要是如果没有找到这个数,就找最接近的,而原数组顺序是打乱的,所以上下两个并不一定就是最接近的,当然,二分查找也是一种思路,我提供一下自己用算法的思路,我的想法是先用木桶排序(我目前所了解的在正整数中的排序的最快方式)

<code>//这个是要求的数组
$arr = [1,2,3...];

//填充一个1-100范围的数组
$search_arr = array_fill(0 , 99 , 0);

//遍历数组
foreach($search_arr as $k=>$v){
    if(in_array($k , $arr)){
        ++ $v;
    }
}

//此时search_arr数组里面值是1的就是要找的,同时已经排序好了
foreach($search_arr as $k=>$v){
    if($v >= 1){
        $new_arr[] = $k;
    }
}

//此时的new_arr就是一个键从0自增,同时值是排序的数组,然后再结合楼上的写法,便可求出。
</code>
登录后复制

不知道这样效率怎么样

<code>$arr = range(1, 100); // 要求的数组
$target = 10; // 目标值
shuffle($arr); // 打乱顺序

$val_key = array_search($target, $arr);
// 测试 $target 不存在的情况去掉以下注释
// array_splice($arr, $val_key, 1);
// $val_key = '';
if ($val_key) {
    echo "这个值是:{$arr[$val_key]}";
} else {
    sort($arr);
    foreach ($arr as $key => $value) {
        if (($value  $target)) {
            echo "左边:{$value} <br>";
            echo "右边:{$arr[$key+1]}";
            exit;
        }
    }
}</code>
登录后复制

不带修改的静态查询

  • 将它排序(升序),复杂度nlogn(一次排序)

  • 然后二分快速定位,复杂度logn(一次查询)

// 在有序数组$arr中得到大于等于$val的第一个下标
// 如果想要获得离$val最近的值,通过返回值判断
// 如果大于最大的值,返回数组的长度
function binary_search($arr, $val){
    $n = count($arr) - 1;
    $ans = $n + 1;
    $l = 0; $r = $n; 
    while($l <= $r){
        $mid = ($l + $r) >> 1;
        if($arr[$mid] >= $val){
            $ans = $mid;
            $r = $mid -1;
        }
        else $l = $mid + 1;
    }
    return $ans;
}

$arr = [1,5,9,3,8,7,10,12];
sort($arr);
foreach($arr as $key => $val){
    printf("%d ", $val);
}
printf("\n");

$search_num = 6;

printf("%d\n", binary_search($arr, $search_num));
登录后复制

仅带添加操作的动态查询,不改变顺序

1-100有100个数,且其值也为1-100,若询问69所在位置下标,可以以69为中心,二分查找到它附近的点的下标,若某个位置存在数,则标为1,否则标为0,那么以69为中心,往左边二分找最长的区间和为0,往右边二分找最长的区间和为0,快速求区间和可以用了树状数组,更新查询复杂度为logn,添加数的复杂度为logn。
要求和目的:

  • 树状数组保存区间标志和(某个区间的值是否出现),更新和查询复杂度logn

  • 以某值为中心查找离它最近的值,然后返回其下标,二分查,复杂度logn

  • 以空间换时间,保存值->下标的映射。

  • 可以在数组末尾添加数,不要求按顺序添加

以下代码解决以下问题

假设有一个数组[5,9,3,8,7,10,12]
询问离12最近的坐标,返回6
询问离2最近的坐标,返回2
添加一个不重复的数15
添加一个不重复的数18
添加一个不重复的数16
添加一个不重复的数13
询问离13最近的坐标,返回10
询问离17最近的坐标,返回9

// 树状数组初始化长度为106,赋空值为0
$arr_bit = array();
for($i = 0;$i <= 105;$i ++){
    $arr_bit[$i] = 0;
}

// 查询1-$x之间的和
function query($x){
    global $arr_bit;
    $sum = 0;
    while($x > 0){
        $sum += $arr_bit[$x];
        $x -= $x & -$x;
    }
    return $sum;
}

// 更新第$x位的标志
function add($x, $val){
    global $arr_bit;
    while($x <= 105){
        $arr_bit[$x] += $val;
        $x += $x & -$x; 
    }
}

$arr = [5,9,3,8,7,10,12];
$arr_tmp = array();
foreach($arr as $key => $val){
    $arr_tmp[$val] = $key;
    printf("%d ",$val);
    add($val, 1);
}
printf("\n");

// 查找离某值最近的下标
// 先查找左边 然后再找右边,若不存在,返回-1
function find_val_pos($val){
    if($val < 1 || $val > 100){
        return -1;
    }
    global $arr_tmp;
    $n = count($arr);
    $l = 1; $r = $val; $ans_l = -1;
    // 得到$val左边最靠近的
    while($l <= $r){
        $mid = ($l + $r) >> 1;
        // 获得$val到$mid的标志区间和
        $mid_val = query($val) - query($mid - 1);
        // 若标志区间和大于1,记录答案,l往右移继续查
        if($mid_val >= 1){
            $ans_l = $mid;
            $l = $mid + 1;
        }
        else $r = $mid - 1;
    }
    $l = $val; $r = 101; $ans_r = -1;
    // 得到$val右边最靠近的
    while($l <= $r){
        $mid = ($l + $r) >> 1;
        // 获得$mid到$val的标志区间和
        $mid_val = query($mid) - query($val - 1);
        if($mid_val >= 1){
            $ans_r = $mid;
            $r = $mid - 1;
        }
        else $l = $mid + 1;
    }
    if($ans_l == -1) return $arr_tmp[$ans_r];
    elseif ($ans_r == -1) return $arr_tmp[$ans_l];
    else {
        if($val - $ans_l > $ans_r - $val)
            return $arr_tmp[$ans_r];
        else
            return $arr_tmp[$ans_l];
    }
}

function add_num($val){
    if($val < 1 || $val > 100) return false;
    global $arr_tmp;
    if(isset($arr_tmp[$val])){
        return false;
    }
    else {
        global $arr;
        $arr_n = count($arr);
        $arr_tmp[$val] = $arr_n;
        $arr[$arr_n] = $val;
        add($val, 1);
        return true;
    }
}

// 查询12最近的坐标
printf("%d\n",find_val_pos(12)); // 结果为6
// 查询2最近的坐标
printf("%d\n",find_val_pos(2));  // 结果为2

add_num(15); // 15位于7
add_num(18); // 18位于8
add_num(16); // 16位于9
add_num(13); // 13位于10

// 查询13最近的坐标
printf("%d\n",find_val_pos(13)); // 结果为10

// 查询17最近的坐标
printf("%d\n",find_val_pos(17)); // 结果为9

// 查询15最近的坐标
printf("%d\n",find_val_pos(15)); // 结果为7

printf("hh\n");
// 查询100最近的坐标
printf("%d\n",find_val_pos(100)); // 结果为8,因为第8个位置是18,是最大的数
登录后复制

带添加删除操作(较大数)的动态查询

需要额外维护一个下标占用的区间值,然后套一个平衡二叉树,查询复杂度logn,添加删除复杂度logn。

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

适用于 Ubuntu 和 Debian 的 PHP 8.4 安装和升级指南 适用于 Ubuntu 和 Debian 的 PHP 8.4 安装和升级指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 带来了多项新功能、安全性改进和性能改进,同时弃用和删除了大量功能。 本指南介绍了如何在 Ubuntu、Debian 或其衍生版本上安装 PHP 8.4 或升级到 PHP 8.4

CakePHP 日期和时间 CakePHP 日期和时间 Sep 10, 2024 pm 05:27 PM

为了在 cakephp4 中处理日期和时间,我们将使用可用的 FrozenTime 类。

讨论 CakePHP 讨论 CakePHP Sep 10, 2024 pm 05:28 PM

CakePHP 是 PHP 的开源框架。它的目的是使应用程序的开发、部署和维护变得更加容易。 CakePHP 基于类似 MVC 的架构,功能强大且易于掌握。模型、视图和控制器 gu

CakePHP 文件上传 CakePHP 文件上传 Sep 10, 2024 pm 05:27 PM

为了进行文件上传,我们将使用表单助手。这是文件上传的示例。

CakePHP 创建验证器 CakePHP 创建验证器 Sep 10, 2024 pm 05:26 PM

可以通过在控制器中添加以下两行来创建验证器。

如何设置 Visual Studio Code (VS Code) 进行 PHP 开发 如何设置 Visual Studio Code (VS Code) 进行 PHP 开发 Dec 20, 2024 am 11:31 AM

Visual Studio Code,也称为 VS Code,是一个免费的源代码编辑器 - 或集成开发环境 (IDE) - 可用于所有主要操作系统。 VS Code 拥有针对多种编程语言的大量扩展,可以轻松编写

CakePHP 快速指南 CakePHP 快速指南 Sep 10, 2024 pm 05:27 PM

CakePHP 是一个开源MVC 框架。它使开发、部署和维护应用程序变得更加容易。 CakePHP 有许多库可以减少大多数常见任务的过载。

您如何在PHP中解析和处理HTML/XML? 您如何在PHP中解析和处理HTML/XML? Feb 07, 2025 am 11:57 AM

本教程演示了如何使用PHP有效地处理XML文档。 XML(可扩展的标记语言)是一种用于人类可读性和机器解析的多功能文本标记语言。它通常用于数据存储

See all articles