题目1:输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。要求时间复杂度是O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。
例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。
分析:如果我们不考虑时间复杂度,最简单想法的莫过去先在数组中固定一个数字,再依次判断数组中剩下的n-1个数字与它的和是不是等于输入的数字。可惜这种思路需要的时间复杂度是O(n2)。
但是上述策略并没有考虑到数组是有序的特性。此处是不是可以在有序的基础上作工作呢?
思路如下:找到数组的第一个数字和最后一个数字。当两个数字的和大于输入的数字时,把较大的数字往前移动;当两个数字的和小于数字时,把较小的数字往后移动;当相等时,输出等式。这样扫描的顺序是从数组的两端向数组的中间扫描。时间复杂度为O(n).
1 function getNums($a, $length, $sum) { 2 if($length < 2) return; 3 $start = 0; 4 $end = $length - 1; 5 while($start < $end){ 6 if($a[$start] + $a[$end] > $sum) 7 $end--; 8 else if($a[$start] + $a[$end] < $sum) 9 $start++; 10 else{ 11 printf("%d, %d ",$a[$start],$a[$end]); 12 $end--; 13 continue; 14 } 15 } 16 } 17 $a = array(1, 2, 4, 7, 11, 14, 15); 18 $length = count($a); 19 $sum = 15; 20 getNums($a, $length, $sum);
题目2:在一个字符串中找到第一个只出现一次的字符。如输入abaccdeff,则输出b。(2006年google)
1 function getStrFirst($str){ 2 $length = strlen($str); 3 $aStr = array(); 4 for ($index = 0; $index < $length; $index++) { 5 $aStr[strtolower($str{$index})]++; 6 } 7 foreach ($aStr as $key=>$value) { 8 if ($value==1) { 9 return $key; 10 } 11 } 12 } 13 echo getStrFirst('abbadsSsfayjuioyopgaAWDDERRGTHRccdeff');