【问题标题】:Find number which is greater than or equal to N in an array在数组中查找大于或等于 N 的数
【发布时间】:2011-09-03 02:12:03
【问题描述】:

如果我有一个 PHP 数组:

$array

有价值观:

45,41,40,39,37,31

我有一个变量:

$number = 38;

如何返回值?:

39

因为这是数组中最接近 38(向上计数)的值?

问候,

泰勒

【问题讨论】:

  • 无意冒犯,但这是一个家庭作业问题吗?
  • 您的描述与您的问题标题不一致。您正在查看该数字是否存在以及在哪个索引处,或者您正在寻找最接近的数字。这是相当不同的。
  • 是的,我意识到我的标题不一致。大声笑不,这不是家庭作业,我需要找到这个值的原因是因为我有从数据库中的值动态创建的对象,具有自定义属性“数据排序”,而我想做的是放置新的通过使用 ajax 将索引页面中所有对象的“数据排序”值数组发送到 PHP 页面,并使用 jquery .after 函数附加它,按顺序排列对象(根据属性的值)到正确的位置
  • 我不确定我是否完全理解目标,但这似乎是一种相当脆弱的方式。我只需将所有对象都放入数组中,然后对数组进行排序。无论是服务器端还是客户端...

标签: php arrays arraylist


【解决方案1】:
<?php
function closest($array, $number) {

    sort($array);
    foreach ($array as $a) {
        if ($a >= $number) return $a;
    }
    return end($array); // or return NULL;
}
?>

【讨论】:

  • 如果你 Copy / Paste 代码,它不会工作,因为我忘了在 return end($array) 的末尾加上一个分号。除此之外,它适用于您的输入(现已测试):)。
  • 这充其量是一个 O(NLogN) 的解决方案,这可以在 O(N) 中执行。
  • echo closest($array, 38); 应该写 39。
  • 很抱歉,该函数没有返回最接近的值,请考虑您的数组后面是否有 37 和 41,并且您正在寻找最接近 38 的值。此实现将返回 41 (41 - 38 = 3),但你知道最接近的值是 37 (38 - 37 = 1)
  • 此函数接受一个数组和一个数字,并返回数组中大于或等于与指定数字最接近的值。这就是 OP 所要求的。
【解决方案2】:

这是获得所需结果并适用于任何数组数据的高级流程:

  • 过滤数组以保持大于或等于目标值,然后选择最低的剩余值。这是“最佳”值(如果所有值都较小,则可能是“无”)——这是O(n)
  • 或者,先对数据进行排序,然后看下面——这是O(n lg n)(希望如此)

现在,假设数组按 ASCENDING 排序,这种方法可行:

  • 遍历数组并找到大于或等于目标的first元素 -- 这是O(n)

如果数组是 DESCENDING(如帖子中所示),请执行上述操作,但是:

  • 迭代向后 -- 这是O(n)
  • 先升序排序(参见 fardjad 的回答)——这是O(n lg n)(希望如此)
  • 向前迭代,但保留后视值(如果跳过精确值,请记住“下一个最高值”)——这是O(n)

编码愉快。

【讨论】:

  • 在 op 的示例中,38 与 37 的距离与与 39 的距离相同。想象数据集:array(37.5, 38.5, 39.5),并且您想要最接近 38.9 的值。当我们真正想要的是 38.5(真正的“最接近”值)时,您的示例会给我们 39.5(大于或等于的最小值)。
【解决方案3】:

EDITarray_search 上的错字

哟...似乎很容易。这是一个函数

<?php 
$array = array(45,41,40,39,37,31);

   function closest($array, $number){
    #does the array already contain the number?
    if($i = array_search( $number, $array)) return $i;

    #add the number to the array
    $array[] = $number;

    #sort and refind the number
    sort($array);
    $i = array_search($number, $array);

    #check if there is a number above it
    if($i && isset($array[$i+1])) return $array[$i+1];

    //alternatively you could return the number itself here, or below it depending on your requirements
    return null;
}

运行echo closest($array, 38);

【讨论】:

  • 如果数字是它上面的两个数字怎么办? 3?这没有正确概括。
  • 已排序。这个数字不可能是搜索我朋友的两个数字。这会使它作为数字上最接近的数字无效
  • 如果数字是 31 并且它上面的下一个数字是 37,这会起作用吗?
  • 啊,聪明。确实,+1 只是为了使用该逻辑。但是,如果输入中根本不存在数字,array_search(...) 仍然存在问题,不是吗?
  • “因为这是数组中最接近 38(向上计数)的值?” -> 对我来说,他正在寻找两个数字之间的数字距离,以及当前数字之上的那个。所以这会使下面的任何数字无效。按照这种逻辑,我可以删除它下面的所有数字……这不是其他人的阅读方式吗?如果不够公平,你能帮我理解吗
【解决方案4】:

这是一个较小的函数,它也将返回最接近的值。如果您不想对数组进行排序(以保留键),这很有帮助。

function closest($array, $number) {
    //does an exact match exist?
    if ($i=array_search($number, $array)) return $i;

    //find closest
    foreach ($array as $match) {
        $diff = abs($number-$match); //get absolute value of difference
        if (!isset($closeness) || (isset($closeness) && $closeness>$diff)) {
            $closeness = $diff;
            $closest = $match;
        }
    }
    return $closest;
}

【讨论】:

  • 对整个数组进行排序至少需要 O(n*logn)。这是 O(n) 的一个很好的算法。
【解决方案5】:

对每个数字进行线性扫描并更新两个变量,然后就完成了。

Python代码(性能是O(N),我认为不可能超过O(N)):

def closestNum(numArray, findNum):
    diff = infinity       # replace with actual infinity value
    closestNum = infinity # can be set to any value
    for num in numArray:
        if((num - findNum) > 0 and (num - findNum) < diff):
            diff = num - findNum
            closestNum = num
    return closestNum

请酌情添加空检查。

【讨论】:

    【解决方案6】:

    如果你真的想要距离上“最接近”的值,即使它是一个较小的值,试试这个,@Jason 获得了大部分功劳。

    想象一个场景,当您希望在以下情况下最接近 38.9 的数字:

    $array = array(37.5, 38.5, 39.5);
    

    这里的大多数解决方案都会给你 39.5,而 38.5 更接近。 如果您正在查找的内容恰好位于数组中两个数字之间的中间,则此解决方案只会采用下一个最大值:

    function nearest_value($value, $array) {
    if (array_search($value, $array)) {
        return $value;
    } else {
        $array[] = $value;
        sort($array);
        $key = array_search($value, $array);
        if ($key == 0) { return $array[$key+1]; }
        if ($key == sizeof($array)-1) { return $array[$key-1]; }
        $dist_to_ceil = $array[$key+1]-$value;
        $dist_to_floor = $value-$array[$key-1];
        if ($dist_to_ceil <= $dist_to_floor) {
            return $array[$key+1];
        } else {
            return $array[$key-1];
        }
    }
    }
    

    它缺乏优雅,但它弥补了准确性。再次感谢@Jason。

    【讨论】:

      【解决方案7】:

      试试这个简单的 PHP 函数:

      <?php
      function nearest($number, $numbers) {
          $output = FALSE;
          $number = intval($number);
          if (is_array($numbers) && count($numbers) >= 1) {
              $NDat = array();
              foreach ($numbers as $n)
                  $NDat[abs($number - $n)] = $n;
              ksort($NDat);
              $NDat   = array_values($NDat);
              $output = $NDat[0];
          }
          return $output;
      }
      
      echo nearest(90, array(0, 50, 89, 150, 200, 250));
      ?>
      

      【讨论】:

        【解决方案8】:

        我为此做了一个更短的函数:

        function nearestNumber($num, $array) {
            if(!in_array($num, $array)) $array[] = $num;
            sort($array);
            $idx = array_search($num, $array);
            if(($array[$idx] -$array[$idx-1]) >= ($array[$idx+1] -$array[$idx])) return $array[$idx+1];
            else return $array[$idx-1];
        }
        

        在我的情况下效果很好:$array = array(128,160,192,224,256,320); $num = 203 :)

        它采用最接近的数字,如果两个数字之间的距离相同(例如我的示例中的 208),则使用下一个最大的数字。

        【讨论】:

          【解决方案9】:

          +1 给杰森。

          下面是我的实现,但没有那么快

          $array = array(1,2,4,5,7,8,9);
          
          function closest($array, $number) {
              $array = array_flip($array);
          
              if(array_key_exists($number, $array)) return $number;
          
              $array[$number] = true;
          
              sort($array);
          
              $rendered = array_slice($array, $number, 2, true); 
          
              $rendered = array_keys($rendered);
          
              if(array_key_exists(1, $rendered)) return $rendered[1]; 
          
              return false;
          }
          
          print_r(closest($array, 3));
          

          【讨论】:

            【解决方案10】:

            您可以为此使用array_reduce,这使其更具函数式编程风格:

            function closest($needle, $haystack) {
                return array_reduce($haystack, function($a, $b) use ($needle) {
                    return abs($needle-$a) < abs($needle-$b) ? $a : $b;
                });
            }
            

            对于其余部分,这遵循与其他 O(n) 解决方案相同的原则。

            【讨论】:

              【解决方案11】:

              这是我的解决方案。

              $array=array(10,56,78,17,30);
              $num=65;
              $diff=$num;
              $min=$num;
              
              foreach($array as $a){
                        if( abs($a-$num)< $diff ){
                            $diff=abs($a-$num);
                            $min=$a;
                        }
              }
              
              echo $min;
              

              【讨论】:

                猜你喜欢
                • 2014-12-20
                • 1970-01-01
                • 1970-01-01
                • 2021-06-09
                • 1970-01-01
                • 2023-04-02
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多