1. 将字符串右转n位,要求时间复杂度为O(n),空间复杂度为O(1)。
比如字符串为'abcde',右转两位为'cdeab'。
解法1:利用字符串翻转,先按右转长度将字符串分为两部分进行翻转,'ab'->'ba',‘cde’->'edc',然后再将字符串整体翻转,'baedc'->'cdeab',时间复杂度O(n),在翻转字符串的时候使用一个临时变量用于交换和一个变量用于记录字符串长度,空间复杂度为O(1)。
php代码:
function turnRight($str,$n)
{
$len = strlen($str);
$n = $n%$len; //防止n>len
if($n>0)
{
reverse($str,0,$n-1);
reverse($str,$n,$len-1);
reverse($str,0,$len-1);
}
echo $str;
}
function reverse(&$str,$start,$end)
{
for(;$start<$end;$start++,$end--)
{
$tem = $str[$start];
$str[$start] = $str[$end];
$str[$end] = $tem;
}
}
turnRight('abcde',2);
解法2:采用递归,将需要右移的字符串逐步向右移动,比如'abcde'->'cdabe'->'cdeab'
php代码:
function turnRight($str,$n)
{
$len = strlen($str);
$n = $n%$len; //当n>len
$s = 0; //标记要移动字符串的头和尾
$e = $n-1;
if($e>0)
turn($str,$s,$e,$len,$n);
echo $str;
}
function turn(&$str,$s,$e,$len,$n)
{
if($e+1>=$len) return;
for($i=$s;$i<=$e;$i++)
{
if($i+$n>=$len) //已经移动到结尾处
{
turn($str,$i,$e,$len,$e-$i+1);
break;
}
else
{
$tem = $str[$i];
$str[$i] = $str[$i+$n];
$str[$i+$n] = $tem;
}
}
$s = $s+$n;
$e = $e+$n;
turn($str,$s,$e,$len,$n);
}
2.判断字符串是否包含
给出一长一短两字符串,用最短时间判断短字符串里的字符在长字符串里都有。
既然要求时间复杂度显然不能逐个字符去找,很自然的想到空间换时间,这类解法很多,比如HashTable,素数乘积法,bitmap,时间复杂度最小为O(n),最大为O(n+m),n为短字符串的长度,m为长字符串的长度。这里给出HashTable的解法和bitmap。
HashTable:
function isInclude($longStr,$shortStr)
{
$store = array();
$len = strlen($shortStr);
for($i=0;$i<$len;$i++)
{
$str = $shortStr[$i];
$store[$str] = 1; //构建HashTable,初始值为1
}
$len = strlen($longStr);
for($i=0;$i<$len;$i++)
{
$str = $longStr[$i];
$store[$str] = 0; //如果字符在长字符串中存在,则将HashTable对应值置0
}
foreach($store as $value)
{
if($value)
{
echo "false";
return;
}
}
echo "true";
}
Bitmap:
function isInclude($longStr,$shortStr)
{
$len = strlen($shortStr);
$longDic = 0;
$shortDic = 0;
for($i=0;$i<$len;$i++)
{
$shortDic |= 1 << (ord($shortStr[$i]) - ord('A'));
}
$len = strlen($longStr);
for($i=0;$i<$len;$i++)
{
$longDic |= 1 << (ord($longStr[$i]) - ord('A'));
}
if(($shortDic|$longDic) == $longDic) echo 'true';
else echo 'false';
}