剑指offer算法题

  • 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
function Find($target, $array)
{
    if(empty($array)) return false;
    $rows = count($array);
    $cols = count($array[0]);
    $row = 0;
    $col = $cols - 1;
    while($col > -1 && $row < $rows)
    {
        if($array[$row][$col] == $target) {
            return true;
        } else if($array[$row][$col] < $target){
            $row++;
        } else {
            $col--;
        }
    }
    return false;
}
  • 输入一个链表,从尾到头打印链表每个节点的值。
val = $x;
    }
}
function printListFromTailToHead($head)
{
    // write code here
    $list = [];
    getNodes($head, $list);
    return $list;
}

function getNodes($head, &$list)
{
    if($head != NULL)
    {
        getNodes($head->next, $list);
        $list[] = $head->val;
    }
}
  • 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
/*class TreeNode{
    var $val;
    var $left = NULL;
    var $right = NULL;
    function __construct($val){
        $this->val = $val;
    }
}*/
function reConstructBinaryTree($pre, $vin)
{
    $lenP = count($pre);
    $lenV = count($vin);
    if($lenP != $lenV) {
        return false;
    }
    if($lenP == 0) return NULL;
    $head = new TreeNode($pre[0]);
    for($i = 0; $i <$lenV; $i++)
    {
        if($vin[$i] == $pre[0])  break;
    }
    $lenL = $i;
    $lenR = $lenP - 1 - $lenL;
    if($lenL > 0) {
        $head->left = reConstructBinaryTree(array_slice($pre, 1, $i), array_slice($vin, 0, $i));
    } 
    if($lenR > 0) {
        $head->right = reConstructBinaryTree(array_slice($pre, $i + 1), array_slice($vin, $i + 1));
    }
    return $head;
}
  • 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
  • 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
function minNumberInRotateArray($rotateArray)
{
    if(empty($rotateArray)) return 0;
    $length = count($rotateArray);
    if($length == 1) return $rotateArray[0];
    $end = count($rotateArray) - 1;
    $begin = 0;
    $mid = $begin;
    while($rotateArray[$begin] >= $rotateArray[$end]) {
       if($end - $begin == 1) {
           $mid = $end;
           break;
       }
       $mid = (int)(($begin + $end)/2);
        if($rotateArray[$mid] >= $rotateArray[$begin]) $begin = $mid;
        elseif($rotateArray[$end] >= $rotateArray[$mid]) $end = $mid;
    }
    return $rotateArray[$mid];
}
  • 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。
    n<=39
function Fibonacci($n)
{
   if($n == 0) return 0;
   if($n == 1) return 1;
   $f0 = 0;
   $f1 = 1;
   $num = 2;
   $fn = 0;
   while($num <= $n)
   {
       $fn = $f1 + $f0;
       $f0 = $f1;
       $f1 = $fn;
       $num ++;
   }
   return $fn;
}
  • 一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
function jumpFloor($number)
{
    if($number <= 0) return 0;
    if($number == 1) return 1;
    if($number == 2) return 2;
    $j1 = 1;
    $j2 = 2;
    $count = 3;
    $jn = 0;
    while($count <= $number)
    {
        $jn = $j2 + $j1;
        $j1 = $j2;
        $j2 = $jn;
        $count ++;
    }
    return $jn;
}
  • 一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
function jumpFloorII($number)
{
    if($number <= 0) return 0;
    if($number == 1) return 1;
    if($number == 2) return 2;
    $jumpArr[0] = 0;
    $jumpArr[1] = 1;
    $jumpArr[2] = 2;
    $count = 3;
    while($count <= $number)
    {
        $jumpArr[$count] = array_sum($jumpArr) + 1;
        $count++;
    }
    return $jumpArr[$count - 1];
}
  • 我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

function rectCover($number)
{
    if($number <= 0) return 0;
    if($number == 1) return 1;
    if($number == 2) return 2;
    $j1 = 1;
    $j2 = 2;
    $count = 3;
    $jn = 0;
    while($count <= $number)
    {
        $jn = $j2 + $j1;
        $j1 = $j2;
        $j2 = $jn;
        $count ++;
    }
    return $jn;
}
  • 输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
class Solution {
public:
     int  NumberOf1(int n) {
         unsigned int count = 0;
         while(n!=0)
         {
             count++;
             n = n & (n - 1);
         }
         return count;
     }
};
  • 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
function Power($base, $exponent)
{
    // write code here
    if($exponent < 0) {
        if($base == 0) return 0;
        else {
            $base = 1/$base;
            $exponent = abs($exponent);
        }
    }
    if($exponent == 0) return 1;
    $result = getPower($base, $exponent);
    if(($exponent & 0x1) == 1) {
        $result *= $base;
    }
    return $result;
}

function getPower($base, $exponent)
{
    $num = (int) ($exponent / 2);
    $result = $base;
    while($num > 0)
    {
        $result *= $result;
        $num--;
    }
    return $result;
}
  • 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
function reOrderArray($array)
{
    $resEven = $resOdd = [];
    foreach($array as $value)
    {
        if($value & 0x1) {
            $resOdd[] = $value;
        } else {
            $resEven[] = $value;
        }
    }
    return array_merge($resOdd, $resEven);
}
  • 输入一个链表,输出该链表中倒数第k个结点。
function FindKthToTail($head, $k)
{
    // write code here
    if($head == NULL || $k <= 0) return NULL;
    $p = $head;
    while($k > 1 && $head != NULL) {
        $head = $head->next;
        $k--;
    }
    if($head == NULL) return NULL;
    while($head != NULL)
    {
        $head = $head->next;
        if($head != NULL) {
          $p = $p->next;  
        }
    }
    return $p;
}
  • 输入一个链表,反转链表后,输出链表的所有元素。
val = $x;
    }
}*/
function ReverseList($pHead)
{
    if(!$pHead)return null;
    $tmp = $pHead->next;
    $pHead->next = NULL;
    $next = $tmp;
    while($next) {
        $next = $tmp->next;
        $tmp->next = $pHead;
        $pHead = $tmp;
        $tmp = $next;
    }
    return $pHead;
}
  • 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
val = $x;
    }
}*/
function Merge($pHead1, $pHead2)
{
    if(!$pHead1) return $pHead2;
    if(!$pHead2) return $pHead1;
    $pHead = NULL;
    if($pHead1->val < $pHead2->val)
    {
        $pHead = $pHead1;
        $pHead->next = Merge($pHead1->next, $pHead2);
    } else {
        $pHead = $pHead2;
        $pHead->next = Merge($pHead1, $pHead2->next);
    }
    return $pHead;
}
  • 输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
val = $val;
    }
}*/
function HasSubtree($pRoot1, $pRoot2)
{
    // write code here
    $isChild =false;
    if($pRoot1 != NULL && $pRoot2 != NULL) {
        if($pRoot1->val == $pRoot2->val) {
            $isChild = DoesTree1HasTree2($pRoot1, $pRoot2);
            if(!$isChild) {
                $isChild = DoesTree1HasTree2($pRoot1->left, $pRoot2);
            }
            if(!$isChild) {
                $isChild = DoesTree1HasTree2($pRoot1->right, $pRoot2);
            }
        }
    }
    return $isChild;
}

function DoesTree1HasTree2($pRoot1, $pRoot2)
{
    if($pRoot2 == NULL) return true;
    if($pRoot1 == NULL) return false;
    if($pRoot1->val != $pRoot2->val) return false;
    return DoesTree1HasTree2($pRoot1->left, $pRoot2->left) && 
   DoesTree1HasTree2($pRoot1->right, $pRoot2->right);
}
  • 操作给定的二叉树,将其变换为源二叉树的镜像。
    输入描述:


    剑指offer算法题_第1张图片
    image.png
val = $val;
    }
}*/
function Mirror(&$root)
{
    if(!$root) return;
    if($root->left != NULL || $root->right != NULL) {
        $node = $root->left;
        $root->left = $root->right;
        $root->right = $node;
    }
    if($root->left) Mirror($root->left);
    if($root->right) Mirror($root->right);
}
  • 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
 2 * $start && $row > 2 * $start)
    {
        $result = array_merge($result, getPrintNum($matrix, $start, $row, $col));
        $start++;
    }
    return $result;
}

function getPrintNum($martrix, $start, $row, $col)
{
    $num = [];
    $endX = $row - $start - 1;
    $endY = $col - $start - 1;
    for ($i = $start; $i <= $endY; $i++)
    {
        $num[] = $martrix[$start][$i];
    }
    if($start < $endX) {
        for ($i = $start + 1; $i <= $endX; $i++)
        {
            $num[] = $martrix[$i][$endY];
        }
        if($start < $endY) {
            for ($i = $endY - 1; $i >= $start; $i--)
            {
                $num[] = $martrix[$endX][$i];
            }
            if($start < $endX - 1) {
                for ($i = $endX - 1; $i > $start; $i--)
                {
                    $num[] = $martrix[$i][$start];
                }
            }
        }
    }
    return $num;
}
  • 定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。
 0) return $arr1[$num - 1];
    else return NULL;
}
function mymin()
{
    global $arr2;
    $num = count($arr2);
    if($num > 0) return $arr2[$num - 1];
    else return NULL;
}
  • 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的
  • 从上往下打印出二叉树的每个节点,同层节点从左至右打印。
val = $val;
    }
}*/
function PrintFromTopToBottom($root)
{
    // write code here
    if($root == NULL) {
        return [];
    }
    $queue[] = $root;
    $res = [];
    while($queue) {
        $node = array_shift($queue);
        $res[] = $node->val;
        if($node->left) {
            $queue[] =  $node->left;
        }
        if($node->right) {
            $queue[] =  $node->right;
        }
    }
    return $res;
}
  • 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
 1) {
        $isTree = VerifySquenceOfBST($leftTree);
    } else {
        $isTree = true;
    }
    if($isTree && count($rightTree) > 1) {
        return VerifySquenceOfBST($rightTree);
    }
    return $isTree;
}
  • 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
val = $val;
    }
}*/
function FindPath($root, $expectNumber)
{
    if(!$root) {
        return [];
    }
    $res = $stack = [];
    ToFind($root, $expectNumber, $stack, 0, $res);
    return $res;
}

function ToFind($root, $expectNumber, &$stack, $currentSum, &$res)
{
    $currentSum += $root->val;
    array_push($stack, $root->val);
    $isLeaf = $root->left == NULL && $root->right == NULL;
    if($isLeaf && $currentSum == $expectNumber) {
       $res[] = $stack;
    }
    if($root->left != NULL){
        ToFind($root->left, $expectNumber, $stack, $currentSum, $res);
    }
    if($root->right != NULL){
        ToFind($root->right, $expectNumber, $stack, $currentSum, $res);
    }
    $currentSum -= $root->val;
    array_pop($stack);
}
  • 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
label = $x;
    }
}*/
function MyClone($pHead)
{
    if($pHead == NULL) {
        return NULL;
    }
    $headOfLink = $head = $pHead;
    //复制
    while($pHead)
    {
        $node = new RandomListNode($pHead->label);
        $node->next = $pHead->next;
        $pHead->next = $node;
        
        $pHead = $node->next;
    }
    //random指针处理
    while($head)
    {
        $new = $head->next;
        $new->random = $head->random->next;
        
        $head = $new->next;
    }
    $newHead = $tmp = $headOfLink->next;
    $orginalHead = $newHead->next;
    while($orginalHead)
    {
        $tmp->next = $orginalHead->next;
        $tmp = $orginalHead->next;
        $orginalHead = $tmp->next;
    }
    return $newHead;
}
  • 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向
val = $val;
    }
}*/

function Convert($pRootOfTree)
{
    $head = NULL;
    ConvertTreeToLink($pRootOfTree, $head);
    while($head != NULL && $head->left != NULL)
    {
        $head = $head->left;
    }
    return $head;
}

function ConvertTreeToLink($pRootOfTree, &$head)
{
    if($pRootOfTree == NULL)
        return;
    if($pRootOfTree->left != NULL){
        ConvertTreeToLink($pRootOfTree->left, $head);
    }
    $pRootOfTree->left = $head;
    if($head) {
        $head->right = $pRootOfTree;
    }
    $head = $pRootOfTree;
    if($pRootOfTree->right != NULL){
        ConvertTreeToLink($pRootOfTree->right, $head);
    }
}
  • 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
= $len-1) {
        $res[] = $str;
    } else {
        for($i = $beginPos; $i < $len; $i++)
        {
            if($i != $beginPos && $str[$beginPos] == $str[$i]) continue;
            $tmp = $str[$i];
            $str[$i] = $str[$beginPos];
            $str[$beginPos] = $tmp;
            
            GetAllStr($str, $len, $beginPos + 1, $res);

            $tmp = $str[$i];
            $str[$i] = $str[$beginPos];
            $str[$beginPos] = $tmp;
        }
    }
}
  • 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
 (intval)($len/2)) return $res;
    else return 0;
}
  • 输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
 $len) return [];
    quickSort($input, 0, $len - 1);
    $out = [];
    $i = 0;
    while($i < $k)
        $out[] = $input[$i++];
    return $out;
}
function quickSort(&$arr, $start, $end)
{
    if($start < $end) {
        $mid = partition($arr, $start, $end);
        quickSort($arr, $start, $mid - 1);
        quickSort($arr, $mid + 1, $end);
    }
}

/**
 * 快速排序法切分
 * @param array int数组
 * @param int $start 开始下标
 * @param int $end 结束下标
 * @return int
 */
function partition(&$arr, $start, $end)
{
    $measure = $arr[$end];
    $p = $start - 1;
    for($i = $start; $i < $end; $i++) {
        if($arr[$i] <= $measure) {
            $p = $p + 1;
            $tmp = $arr[$i];
            $arr[$i] = $arr[$p];
            $arr[$p] = $tmp;
        }
    }
    $arr[$end] = $arr[$p + 1];
    $arr[$p + 1] = $measure;
    return $p + 1;
}
  • 在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。你会不会被他忽悠住?(子向量的长度至少是1)

function FindGreatestSumOfSubArray($array)
{
    // write code here
    if(empty($array)) return 0;
    $curSum = 0;
    $sum = -1*2^31;
    foreach($array as $v)
    {
        if($curSum < 0) 
        {
            $curSum = $v;
        }else {
            $curSum += $v;
        }
        if($curSum > $sum) $sum = $curSum;
    }
    return $sum;
}
  • 求出113的整数中1出现的次数,并算出1001300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数。
不会
  • 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
  • 把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
  • 在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置
function FirstNotRepeatingChar($str)
{
    // write code here
    $len = strlen($str);
    if($len < 1) return -1;
    if($len == 1) return 0;
    $hash = [];
    for($i = 0; $i< $len; $i++)
    {
        if(isset($hash[$str[$i]])) {
            $hash[$str[$i]]++;
        } else {
            $hash[$str[$i]] = 1;
        }
    }
    for($i = 0; $i< $len; $i++)
    {
        if($hash[$str[$i]] == 1) return $i;
    }
    return -1;
}
  • 输入两个链表,找出它们的第一个公共结点。
val = $x;
    }
}*/
function FindFirstCommonNode($pHead1, $pHead2)
{
    $len1 = GetLength($pHead1);
    $len2 = GetLength($pHead2);
    
    $lenDiff = $len2 - $len1;
    if($lenDiff > 0) {
        $long = $pHead2;
        $short = $pHead1;
    } else {
        $long = $pHead1;
        $short = $pHead2;
        $lenDiff = abs($lenDiff);
    }
    while($lenDiff>0) {
        $long = $long->next;
        $lenDiff--;
    }
    while($long != NULL && $short != NULL && $long != $short)
    {
        $long = $long->next;
        $short = $short->next;
    }
    return $long;
}

function GetLength($pHead)
{
    if($pHead == NULL) return 0;
    $len = 0;
    while($pHead != NULL)
    {
        $len++;
        $pHead = $pHead->next;
    }
    return $len;
}
  • 统计一个数字在排序数组中出现的次数。
function GetNumberOfK($data, $k)
{
    $count = 0;
    foreach($data as $v)
    {
        if($k == $v) {
            $count++;
        }
    }
    return $count;
}
要用二分法才对
  • 输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
val = $val;
    }
}*/
function TreeDepth($pRoot)
{
    /**$max = $deep = 0;
    getDeep($pRoot, $deep, $max);
    return $max;**/
    if($pRoot == NULL) return 0;
    $left = TreeDepth($pRoot->left);
    $right = TreeDepth($pRoot->right);
    return $left > $right ? $left +1 : $right + 1;
}

/**
* 旧方法
**/
function getDeep($pRoot, &$deep, &$max)
{
    if(!$pRoot) return;
    $deep++;
    if($pRoot->left == NULL && $pRoot->right == NULL) 
    {
        if($deep > $max) $max = $deep;
    }
    if($pRoot->left) getDeep($pRoot->left, $deep, $max);
    if($pRoot->right) getDeep($pRoot->right, $deep, $max);
    $deep--;
}
  • 输入一棵二叉树,判断该二叉树是否是平衡二叉树。
val = $val;
    }
}*/
function IsBalanced_Solution($pRoot)
{
    if($pRoot == NULL) return true;
    $left = getDepth($pRoot->left);
    $right = getDepth($pRoot->right);
    if(abs($left - $right) > 1) return false;
    return IsBalanced_Solution($pRoot->left) && IsBalanced_Solution($pRoot->right);
}

function getDepth($pRoot)
{
    if($pRoot == NULL) return 0;
    $left = getDepth($pRoot->left);
    $right = getDepth($pRoot->right);
    return $left > $right ? $left + 1 : $right + 1;
}
  • 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字

你可能感兴趣的:(剑指offer算法题)