• 技术文章 >后端开发 >php教程

    关于腾讯的那谈题截取字符串的题

    2016-06-13 12:51:54原创353
    关于腾讯的那道题截取字符串的题
    记得是前阵子去腾讯面试时的那道题,当时用笔我没写出来,就大概说了下思路,今天有空,就写了一下,发现要做到完美还是很麻烦的。


    题目是:
    假设有"123abc456def789"这么一个字符串,写一个函数,可以传入一个字符串,和一个要截取的长度。返回截取后的结果。

    要求:
    1 标记不得计算在长度之内。
    2 截取后的字符串,要保留原有标签,不过如果最后有一个标签没有闭合,则去掉其开始标签。

    示例:
    题中的字符串,要截取长度5,则返回的字符串应该为:123ab,要截取长度8,应返回123abc45。



    我的做法大概思路是:
    1 首先顺序读取字符串,并用一个resultstr变量来记录所有字符,当发现<标记时,开始将这个子字符串用tag变量记录下来。
    2 如果发现tag变量形式为<\w+>也就是html标签的开始标记),就将其入栈。用栈结构来存储这个标记。若遇到<\/\w+>(html标签的结束标记),就出栈。

    3 否则如果是常规字符的话,长度计数器++。直到与传入的要截取长度相等。

    4 最后判断栈是否为空,如果为空,直接返回截取后的字符串,否则,将栈中剩余元素一个个出栈,循环从截取后的字符串中查找栈顶标签元素最后一次出现的位置,返回索引,将这个标签替换为空。直到整个栈为空为止。最后返回处理后的字符串。



    原题其实是没有考虑标签嵌套的情况的,我尽量的让程序可以处理嵌套标签,使其更健壮。并且尽量少的去用php的内置函数,因为那样可能会掩盖算法本身。如可以处理a1

    b2c3d4

    e5
    这种形式的嵌套标签。但我发现如果标签是这种不规则形式a1

    b2c3d4

    e5的话,程序就会出问题了。因为我只将取到的结束标记与栈顶的元素相比较,而没有去循环搜索整个栈。这里要改一下其实也可以。


    不知大家还有没有其他思路,我感觉我这么做实在是太麻烦了,罗罗嗦嗦一大堆。这么多代码面试时拿笔写非得疯了不可。而且这个时间复杂度不理想,大概为O(n*(n2))。空间方面也占了很多多余的空间。我相信一定有很简单的办法。希望大家一起想想有什么更简单的方法没?




    function mySubstr( $str, $length ){

    $tagcnt = 0;
    $charcnt = 0;
    $tag = '';
    $maxlen = strlen( $str );
    $resultstr = '';
    $tagstack = array();

    for( $i = 0; $i < $length; $i++ ){
    if( $str[$i] == '<' ){

    $resultstr .= $str[$i];

    for( $j=$i; $str[$j]!='>'; $j++,$length++ ){
    $tag .= $str[$j];
    }
    $tagcnt++;
    $length++;
    $tag .= '>';

    //如果是开始标记,则入栈,如果是与之相对应的结束标记则出栈
    if( preg_match('/<([^\/]+)?>/i', $tag, $r) ){
    echo '入栈:',htmlspecialchars($r[1]),'
    ';
    array_push($tagstack, $r[1]);
    }
    elseif( preg_match( '//m.sbmmt.com/m/'.$tagstack[count($tagstack)-1].'//m.sbmmt.com/m/', $tag ) ){
    echo '出栈:',htmlspecialchars($tagstack[count($tagstack)-1]),'
    ';
    array_pop( $tagstack );
    }

    $tag = '';
    continue;
    }

    $charcnt++;
    $resultstr .= $str[$i];
    }


    echo '
    最后结果为:';

    //栈是空的直接返回
    if(empty($tagstack)){
    return $resultstr;
    }
    //否则去掉没有结束标记的开始标记
    else{

    while(!empty($tagstack)){

    $tag = array_pop($tagstack);

    $index = strrpos($resultstr, $tag);

    for($i = $index-1; $resultstr[$i] != '>'; $i++ ){
    $resultstr[$i] = '';
    }

    $resultstr[$i++] = '';

    }

    return $resultstr;
    }

    }

    $sttime = microtime(true);

    $stmem = memory_get_usage();

    $str = "a1b2

    c3d4e5

    f6g7h8";

    echo '处理结果为:

    ',htmlspecialchars( mySubstr( $str, 18 ) ),'
    ';

    echo "内存使用情况:",(memory_get_usage()-$stmem),'
    ';

    echo "算法运行时间(microtime):",(microtime(true)-$sttime),'
    ';


    ------解决方案--------------------
    呵呵,这题有印象

    来添砖加瓦
     
    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:nbsp lt gt resultstr tagstack
    20期PHP线上班

    相关文章推荐

    • 【活动】充值PHP中文网VIP即送云服务器• 请问一下memcache相关的 • 神奇的没见过的技术大神们来围观啊mysql一次自动插入2条数据,求解。解决方案 • php生成xml文件 请问 • 调查问卷数据提交有关问题 • 小弟我这个如何做比较好呢
    1/1

    PHP中文网