劍指offer試題(PHP篇一)

1.二維數組中的查找php

題目描述

在一個二維數組中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。
時間限制:1秒   空間限制:32768K
<?php

function Find($target, $array)
{
    // write code here
    foreach($array as $k=>$v){
        if(in_array($target,$v)){
            return "true";
        }
    }
  return "false"; }

運行時間:281ms   佔用內存:4252knode

感悟:數組

  這道題用PHP寫起來比較簡單,只要懂得二維數組的遍歷,以及in_array()函數的使用,不要搞錯參數位置,參數一爲要查找的字符串,參數二爲數組。app

 

2.替換空格函數

題目描述

請實現一個函數,將一個字符串中的空格替換成「%20」。例如,當字符串爲We Are Happy.則通過替換以後的字符串爲We%20Are%20Happy。
時間限制:1秒   空間限制:32768K
<?php
function replaceSpace($str)
{
    // write code here
    return str_replace(" ","%20",$str);
} 

運行時間:9ms   佔用內存:2428k測試

感悟:this

  要熟悉str_replace()函數,參數一爲要查找的值,參數二爲替換的值,參數三爲被搜索的字符串。spa

  若是搜索的字符串是數組,那麼它將返回數組,對數組中的每一個元素進行查找和替換。注意,在數組替換中,若是須要執行替換的元素少於查找到的元素的數量,那麼多餘元素將用空字符串進行替換。code

 

3.從尾到頭打印鏈表blog

題目描述

輸入一個鏈表,從尾到頭打印鏈表每一個節點的值。
時間限制:1秒   空間限制:32768K
<?php

/*class ListNode{
    var $val;
    var $next = NULL;
    function __construct($x){
        $this->val = $x;
    }
}*/
function printListFromTailToHead($head)
{
    // write code here
    $list = array();
    while($head!=null){
        $list[]=$head->val;
        $head=$head->next;
    }
    return array_reverse($list);
} 

運行時間:18ms   佔用內存:2432k

感悟:

  本題的思路爲先將鏈表的值順序裝入一個空數組中,而後使用array_reverse()函數以相反的元素順序返回數組。

 

4.重建二叉樹

題目描述

輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。
時間限制:1秒   空間限制:32768K
<?php

/*class TreeNode{
    var $val;
    var $left = NULL;
    var $right = NULL;
    function __construct($val){
        $this->val = $val;
    }
}*/
function reConstructBinaryTree($pre, $vin)
{
    // write code here
	if($pre && $vin){
		$treeRoot = new TreeNode($pre[0]);
		$index = array_search($pre[0],$vin);
		$treeRoot->left = reConstructBinaryTree(array_slice($pre,1,$index),array_slice($vin,0,$index));
		$treeRoot->right = reConstructBinaryTree(array_slice($pre,$index+1),array_slice($vin,$index+1));
		return $treeRoot;
	}
}

運行時間:35ms   佔用內存:4204k

感悟:

  本題的思路爲遞歸調用reConstructBinaryTree方法來分別執行左子樹和右子樹的遍歷查找,每次都查找出根節點並進行保存。

  題中使用到的函數:array_search(),在數組(參數二)中搜索某個鍵值(參數一),並返回對應的鍵名,若沒有找到,則返回false。

           array_slice(),在數組中根據條件取出一段值,並返回,參數一爲數組,參數二爲取值的起始位置(至關於數組下標),參數三爲選取的長度(可選,若不填,則取到數組結尾)。

 

5.用兩個棧實現隊列

題目描述

用兩個棧來實現一個隊列,完成隊列的Push和Pop操做。 隊列中的元素爲int類型。
時間限制:1秒    空間限制:32768K
<?php
$stack = array();
function mypush($node)
{
    // write code here
    global $stack;
    return $stack[]=$node;
}
function mypop()
{
    global $stack;
    if($stack){
        return array_shift($stack);
    }
    // write code here
    return $stack;
}

運行時間:14ms   佔用內存:3688k

感悟:

  首先要清楚隊列的Push和Pop操做的含義:push(x):將x壓入隊列的末端,pop():彈出隊列的第一個元素。

  本題要點爲定義全局數組$stack,其次爲array_shift()函數:刪除數組中的第一個元素,並返回被刪除元素的值。

 

6.旋轉數組的最小數字

題目描述

把一個數組最開始的若干個元素搬到數組的末尾,咱們稱之爲數組的旋轉。 輸入一個非遞減排序的數組的一個旋轉,輸出旋轉數組的最小元素。 例如數組{3,4,5,1,2}爲{1,2,3,4,5}的一個旋轉,該數組的最小值爲1。 NOTE:給出的全部元素都大於0,若數組大小爲0,請返回0。
時間限制:3秒   空間限制:32768K
<?php

function minNumberInRotateArray($rotateArray)
{
    // write code here
    /*
    if(count($rotateArray) == 0){
        return 0;
    }
    $min = min($rotateArray);
    foreach($rotateArray as $k=>$v){
        if($v == $min){
            $arrLeft[] = array_slice($rotateaArray,0,$k+1);
            $arrRight[] = array_slice($rotateArray,$k+1);
        }
    }
    弄了半天不是讓輸出翻轉後的數組。。。。
    */
    if(count($rotateArray)){
        return min($rotateArray);
    }else{
        return 0;
    }
}

運行時間:985ms   佔用內存:5156k

感悟:

  這道題告訴我必定要審題審題審題=  =|,原本本身在一味的求解反轉後的數組,結果不知何時一看,發現只是讓求最小數,對於php而言太簡單了。。。不過對於這道題,仍是要提醒你們細心(汗)。

 

7.斐波那契數列

題目描述

你們都知道斐波那契數列,如今要求輸入一個整數n,請你輸出斐波那契數列的第n項。

n<=39

時間限制:1秒   空間限制:32768K

<?php

function Fibonacci($n)
{
    // write code here
    if($n < 0 || $n > 39)
        return false;
    $ret = [];
    for($i = 0; $i <= $n; $i++){
        if($i == 0){
            $ret[$i] = 0;
            continue;
        }elseif($i == 1){
            $ret[$i] = 1;
            continue;
        }
        $ret[$i] = $ret[$i-1]+$ret[$i-2];
    }
    return $ret[$n];
}

運行時間:15ms   佔用內存:2316k

感悟:

  這道題,只要理解斐波那契數列,知道用遞歸來實現就徹底ok,再說思路,首先,排除掉不成立的狀況,其次,將0和1的特殊狀況拿出來單獨賦值,最後,就是通常狀況的循環遞歸。

 

8.跳臺階

題目描述

一隻青蛙一次能夠跳上1級臺階,也能夠跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法。
時間限制:1秒   空間限制:32768K
<?php

function jumpFloor($number)
{
    // write code here
    $arr = [];
    for($i=1;$i<=$number;$i++){
        if($i==1){
            $arr[1]=1;
            continue;
        }
        if($i==2){
            $arr[2]=2;
            continue;
        }
        $arr[$i]=$arr[$i-1]+$arr[$i-2];
    }
    return $arr[$number];
}

運行時間:9ms   佔用內存:2316k

感悟:

  惟一的感覺。。居然撞題了= =,不廢話,這道題按照通常的思路有些難解,但換種想法,比較傾向於找規律的解法,f(1) = 1, f(2) = 2, f(3) = 3, f(4) = 5,  能夠總結出f(n) = f(n-1) + f(n-2)的規律,可是爲何會出現這樣的規律呢?假設如今6個臺階,咱們能夠從第5跳一步到6,這樣的話有多少種方案跳到5就有多少種方案跳到6,另外咱們也能夠從4跳兩步跳到6,跳到4有多少種方案的話,就有多少種方案跳到6,其餘的不能從3跳到6什麼的啦,因此最後就是f(6) = f(5) + f(4);這樣子也很好理解變態跳臺階的問題了,看到這裏,你就會驚喜的發現!沒錯,就是斐波那契數列的問題,不過是少了0那種狀況。

 

9.變態跳臺階

題目描述

一隻青蛙一次能夠跳上1級臺階,也能夠跳上2級……它也能夠跳上n級。求該青蛙跳上一個n級的臺階總共有多少種跳法。
時間限制:1秒   空間限制:32768K
<?php
 
function jumpFloorII($number)
{
    // write code here
    if($number == 1) return 1;
    return pow(2,($number - 1));
}  

運行時間:24ms   佔用內存:2936k

感悟:

  由於n級臺階,第一步有n種跳法:跳1級、跳2級、到跳n級;

  跳1級,剩下n-1級,則剩下跳法是f(n-1);

  跳2級,剩下n-2級,則剩下跳法是f(n-2),

因此f(n)=f(n-1)+f(n-2)+...+f(1),由於f(n-1)=f(n-2)+f(n-3)+...+f(1),因此f(n)=2*f(n-1)

因此,f(n)=2的n-1次方。

固然,還要知道php的pow(x,y)函數,返回 x 的 y 次方。

 

10.矩形覆蓋

題目描述

咱們能夠用2*1的小矩形橫着或者豎着去覆蓋更大的矩形。請問用n個2*1的小矩形無重疊地覆蓋一個2*n的大矩形,總共有多少種方法?
時間限制:1秒   空間限制:32768K
<?php

function rectCover($number)
{
    // write code here
    if($number==0){
        return 0;
    }
     $arr = [];
    for($i=1;$i<=$number;$i++){
        if($i==1){
            $arr[1]=1;
            continue;
        }
        if($i==2){
            $arr[2]=2;
            continue;
        }
        $arr[$i]=$arr[$i-1]+$arr[$i-2];
    }
    return $arr[$number];
}

運行時間:29ms   佔用內存:2928k

感悟:
  走過的彎路:開始只是簡單地將 n 分紅奇、偶討論,並將 2*2 做爲基本單元。測試後通不過,代碼就不貼出來獻醜了。
思路分析:痛定思痛,仍是不可以貪小便宜。用概括法概括以下,
(1)當 n < 1時,顯然不須要用2*1塊覆蓋,按照題目提示應該返回 0。
(2)當 n = 1時,只存在一種狀況。
 
(3)當 n = 2時,存在兩種狀況。
 
(4)當 n = 3時,明顯感受到若是沒有章法,思惟難度比以前提高挺多的。
 
... 嘗試概括,本質上 n 覆蓋方法種類都是對 n - 1 時的擴展。
能夠明確,n 時一定有 n-1時原來方式與2*1的方塊結合。也就是說, f(n) = f(n-1) + ?(暫時沒法判斷)。
(4)若是咱們如今概括 n = 4,應該是什麼形式?
4.1)保持原來n = 3時內容,並擴展一個 2*1 方塊,形式分別爲 「| | | |」、「= | |」、「| = |」
4.2)新增長的2*1 方塊與臨近的2*1方塊組成 2*2結構,而後能夠變造成 「=」。因而 n = 4在原來n = 3基礎上增長了"| | ="、「= =」。
再本身看看這多出來的兩種形式,是否是隻比n = 2多了「=」。其實這就是關鍵點所在...由於,只要2*1或1*2有相同的兩個時,就會組成2*2形式,因而就又能夠變形了。
因此,天然而然能夠得出規律: f(n) = f(n-1) + f(n-2), (n > 2)。
而後這個時候,你就會驚喜的發現,又回到斐波那契數列了。。。思路再也不細說,有須要的朋友能夠看7題和8題。

 

注:以上均爲我的理解,若有錯誤,請提出,必改正。

相關文章
相關標籤/搜索