剑指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题。

 

注:以上均为我的理解,若有错误,请提出,必改正。

相关文章
相关标签/搜索