簡體   English   中英

未排序的數組 - 從下一個更高的值獲取索引 | 復雜度 O(n),PHP

[英]Unsorted array - Getting index from next higher value | Complexity O(n), PHP

我搜索了一個復雜度為 O(n)的 PHP 算法。 我有一個整數數組,我想要每個元素的索引號比這個最近的大值或 -1 如果它不存在。
注意:每個值都是唯一的。

示例

$arr = [7, 3, 5, 4];
$result = [-1, 3, 0, 2];

解釋:

  • 7 沒有更大的值 => -1
  • 3 下一個更大的值 4 => 3
  • 5 下一個更大的值 7 => 0
  • 4 下一個更大的值 5 => 2

解決方案工作正常,但它具有 O(n²):

function follows ($arr, $index) {
    $filter = array_filter($arr, function($el) use ($arr, $index) { return $el > $arr[$index]; });
    if (count($filter)===0)
        return -1;
    else
        return array_search(min($filter), $arr);
}

$res = [];
for ($i=0; $i<count($arr); $i++) {
    $res[] = follows($arr,$i);
}
var_dump($res); // => [-1, 3, 0, 2]

搜索 O(n) 的解決方案

我應該使用asort (例如: [3, 4, 5, 7] ),所以這些值被排序,我可以在那里獲得下一個元素的原始索引。

這是它的想法的一部分:

$arr = [ 7, 3, 5, 4];
asort($arr);
for($i=0; $i<count($arr); $i++) {
    echo 'For: ' . $i . ': ' . $arr[$i].'<br>';
}

echo "<br>";

foreach ($arr as $key => $val) {
    echo 'ForEach; ' . $key . ': ' . $val .'<br>';
}

echo '<br><br>' . $arr[2];

使用 asort 排序后,索引與您在for-loop看到的相同,但在forEach-loop它們是新排序的,但索引仍然相同。
思路:從for循環中取出索引,得到forEach-loop對應的索引加1,得到原始索引。
示例:我的數組中的索引 1 的值為 3,在 for 循環中的索引仍為 1,但在 forEach 循環中的索引為 0。到達那里時,值為 4 的下一個元素(索引 1)的原始索引為3.

最后一步很簡單。 任何人都可以幫助在沒有找到的情況下從 for 索引到 forEach 索引獲取缺失的鏈接嗎?

我將數組迭代 3 次(array_flip、for、for)並對它排序 1 次(ksort)。 我不知道如何計算復雜度......也許,將循環計數為O(N)並將 ksort 計數為O(N*log(N)) 所以最終的復雜度是O(N*log(N)) 我不能讓它變小:)

$arr = [7, 3, 5, 4];

$flip = array_flip($arr); // prepare for sort
ksort($flip); // sort

// put results into place
$keys = array_keys($flip);
for ($i = 0; $i < count($flip) - 1; $i++) {
    $flip[$keys[$i]] = $flip[$keys[$i + 1]];
}
$flip[$keys[count($keys) - 1]] = -1;

// finalize results
$result = [];
for ($i = 0; $i < count($arr); $i++) {
    array_push($result, $flip[$arr[$i]]);
}

print_r($result);

外部測試鏈接: 點擊

這是一個不翻轉數組的版本,因此可以處理任何類型的數組數據。 它使用一個單一的回路和asort所以是O(n*log(n)) 一旦數據被排序, key函數用於確定循環中下一個較大值的key; 當循環結束時,最終的“下一個”值設置為 -1(因為沒有更大的值)。 此時輸出具有正確的鍵/值對,但不是按數字順序排列的(這可能足以滿足您的需要):

$arr = [7, 3, 5, 4];
asort($arr);
$temp = [];
$count = 1;
$key = key($arr);
while (next($arr) !== false) {
    $temp[$key] = key($arr);
    $key = key($arr);
    $count++;
}
$temp[$key] = -1;
print_r($temp);

輸出:

Array
(
    [1] => 3
    [3] => 2
    [2] => 0
    [0] => -1
)

如果您需要對鍵進行排序(例如,如果您希望在使用foreach循環時按順序排列條目),您可以使用另一個循環,利用上面代碼中生成的$count變量來復制值進入一個新的有序數組:

$result = [];
for ($i = 0; $i < $count; $i++) {
    $result[] = $temp[$i];
}
print_r($result);

輸出:

Array
(
    [0] => -1
    [1] => 3
    [2] => 0
    [3] => 2
)

如果你不需要這個,你可以從第一個代碼塊中刪除$count的計算。

3v4l.org 上的演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM