经纬创投笔试题算法-php实现

括号匹配问题
问题描述

有如’()(())’这样的字符串,要进行判断该字符串是否完全匹配,也就是括号是否是都可以匹配完,如’()((()(‘这样的字符串就不能正常匹配。如果是’{[]}([])’这样的字符串,又该如何处理。

问题分析

想到这里要对括号进行匹配,就可以把左边的括号压入栈中,然后字符串中遇到右边的括号的时候将栈顶元素进行弹出就可以了,最后判断栈是否为空,从而进行判断。

代码实现:
/**
 * [判断一段字符串中的括号是否匹配]
 * @param  [string] $str [要进行判断的字符串]
 * @return [boolean]      [最终结果]
 */
function adjust($str) {
    $resArr = array();

    for ($i=0; $i < strlen($str); $i++) {
        // 判断字符串的第一个字符是否是),最后一个元素是否是(,是则直接返回false
        if ($str[0] == ')') {
            return false;
        } else if ($str[strlen($str) - 1] == '(') {
            return false;
        }

        // 如果遇到(进行入栈
        if ($str[$i] == '(') {
            $resArr[count($resArr)] = $str[$i];
        } else if ($str[$i] == ')') {
            // 如果遇到)就弹出栈顶元素,但是在弹出的时候要进行判断,栈是否已经为空了
            if (count($resArr) > 0) {
                array_pop($resArr);
            }else{
                return false;
            }
        }
    }

    // 判断栈是否为空
    if (count($resArr) == 0) {
        return true;
    }else {
        return false;
    }
}

上面的代码只描述了只有小括号的情况,但是在中括号或者大括号的情况下,思路基本上是一致的,不过多了一个判断就是在弹出栈顶元素的时候,要对栈顶元素进行判断,是否是后边要进行匹配的元素,然后再弹出。

寻找中位数问题
问题描述

有一个序列如:{1, 5, 19, 34, 50},该序列是升序的,其中位数就是19,现在有两个中需的序列如:s1, {1, 5, 19, 34, 50}; s2, {2, 4, 8, 10, 30},这样则两个序列的中位数就是:8。

问题分析

这里可以看到两个序列的时候是将两个序列合并之后再找到合并之后的序列的中位数,可是这样做的时候会发现其时间复杂度和空间复杂度都不是最好的。
又想到合并之后的序列可以进行删除序列的头元素和尾元素,这样循环,知道合并后的序列剩余一个或两个元素时,停止删除,得到的就是中位数了。但是这样做的时候空间复杂度又不是最好的。
所以最终的想法是:分别删除两个序列中的最小和最大元素,知道两个序列中的元素总和剩余一个或两个时,停止删除,得到中位数。

代码实现
/**
 * [获取两个数组中的中位数]
 * @param  [array] $arr [第一个数组]
 * @param  [array] $brr [第二个数组]
 * @return [int]      [返回中位数]
 */
function getMiddleNum($arr, $brr) {
    $length = count($arr) + count($brr);
    $loopNum = ceil($length / 2) - 1;

    while ($loopNum > 0) {
        // 声明最小和最大的数,用以后边判断
        $lowA = null;
        $lowB = null;
        $highA = null;
        $highB = null;

        // 数组有长度的时候再获取当前数组中的最小和最大的数
        if (count($arr)) {
            $lowA = $arr[0];
            $highA = $arr[count($arr) - 1];
        }

        // 数组有长度的时候再获取当前数组中的最小和最大的数
        if (count($brr)) {
            $lowB = $brr[0];
            $highB = $brr[count($brr) - 1];
        }

        // 删除两个序列中最小的元素
        if ((null != $lowB) && (null != $lowA)) {
            if ($lowA > $lowB) {
                array_shift($brr);
            }else{
                array_shift($arr);
            }
        }else if (null == $lowB) {
            array_shift($arr);
        }else if (null == $lowA) {
            array_shift($brr);
        }

        // 删除两个序列中最大的元素
        if ((null != $highA) && (null != $highB)) {
            if ($highB > $highA) {
                array_pop($brr);
            }else{
                array_pop($arr);
            }
        }else if (null == $highB) {
            array_pop($arr);
        }else if (null == $highA) {
            array_pop($brr);
        }

        // 判断如果两个数组的总长度为2或者1的时候,获取中位数
        $finalLength = count($arr) + count($brr);
        if (1 == $finalLength) {
            if (count($arr)) {
                return $arr[0];
            }else{
                return $brr[0];
            }
        }else if (2 == $finalLength) {
            if (2 == count($arr)) {
                return $arr[0];
            }else if (2 == count($brr)) {
                return $brr[0];
            }else{
                if($arr[0] > $brr[0]) {
                    return $brr[0];
                }else{
                    return $arr[0];
                }
            }
        }

        $loopNum--;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值