1. 程式人生 > >【劍指offer】二維陣列中的查詢——複雜度為O(n+m)——採用PHP寫法

【劍指offer】二維陣列中的查詢——複雜度為O(n+m)——採用PHP寫法

背景

今天偶然進入牛客網,看到《劍指offer》模組有演算法題,就開始試著答題

 

題目描述

在一個二維陣列中(每個一維陣列的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數。

一開始我的思路比較笨,不就直接遍歷二維陣列嘛?

輸入以下程式碼提交了

<?php

function Find($target, $array)
{
    // write code here
    for($i = 0; $i < count($array[0]); $i++){
        for($j = 0; $j < count($array[1]); $j++){
            if($target === $array[$i][$j]){
                return 1;
            }
        }
    }
}

雖說第一次直接提交成功了,但是感覺好像這個時間複雜度有點高

仔細審了題,使用另外一種思路作答

思路:

  •  由於題目中的二維陣列是有序排列的,而且是根據每一行從左到右遞增,每一列從上到下遞增,那麼在查詢二維陣列的時候,可以通過這個規律來改變實現方法
  • 從每一個二維陣列的左下角跟右上角開始查詢比較方便(至於為什麼方便,大家可以自己思考一下)

1、假設從右上角開始查詢

          如果$target < $array[$i][$j],則往左邊移動一個單位(即$j--);

          如果$target > $array[$i][$j],則往下邊移動一個單位(即$i++);

          如果$target = $array[$i][$j],則返回true;

2、假設從左下角開始查詢

          如果$target < $array[$i][$j],則往上邊移動一個單位(即$i--);

          如果$target > $array[$i][$j],則往右邊移動一個單位(即$j++

);

          如果$target = $array[$i][$j],則返回true;

程式碼實現: 

<?php

function Find($target, $array)
{
    $length = count($array[0]);      //一維陣列的長度
    $i      = 0;                     //起始橫座標
    $j      = $length - 1;           //起始縱座標
    for($n = 0; $n < ($length - 1) + (count($array) - 1); $n++){ //最多移動$length減1 + 二維陣列長度減1次
        if($array[$i][$j] === $target){//查詢到目標,返回true
            return true;
        }
        if($array[$i][$j] < $target){//查詢目標大於右上角元素,則$i++,下移
            $i++;
            continue;
        }
        if($array[$i][$j] > $target){//查詢目標小於右上角元素,則$j--,左移
            $j--;
            continue;
        }
    }
}

程式碼講解:

for迴圈中,最多隻需要移動$length減1 + 二維陣列長度減1 次,什麼意思呢?

畫個圖你們就明白了

假設有如下二維陣列:

我們從右上角開始查詢22這個數 

由於22比8大,所以我們先下移,22比18大,我們繼續下移,由於22比28小,我們需要左移......

最終我們移動了8次才找到22這個數,而且8次是移動次數最多的,為什麼呢?

因為每一次只能下移或者左移,所以

左移次數最多6次(即一維陣列長度減1次)

下移次數最多2次(即二維陣列長度減1次)

這就是為什麼for迴圈中,最多需要迴圈$length減1 + 二維陣列長度減1次,$length就是一維陣列的長度

因此這個演算法的時間複雜度為O(n+m),其中n為一維陣列的長度,m為二維陣列的長度(忽略減去的2次) 

相比之前的O(n*m),還是快了些的。

 

總結 

牛客網真的是一個很不錯的網址,上面不僅有大量的試題,而且還有很多大佬的經驗分享,值得大家去好好利用這個資源,相信牛客網能給各位帶來許多幫助,一起加油!