给出一个电话号码列表,确定它是否一致,因为没有数字是另一个号码的前缀。假设电话目录列出了这些数字:
紧急情况911 爱丽丝97 625 999 鲍勃91 12 54 26
在这种情况下,无法呼叫Bob,因为只要您拨打了Bob的电话号码的前三位数字,中心就会将您的呼叫转到紧急线路。所以这个列表不一致。
输入
第一行输入给出一个整数,1≤t≤40,测试用例的数量。每个测试用例以单独一行的电话号码n开始,1≤n≤10000。然后跟随n行,每行有一个唯一的电话号码。电话号码是最多十位数的序列。
输出
对于每个测试用例,如果列表一致则输出“YES”,否则输出“NO”。
该程序应该从标准读取,并写入标准输出。我们还可以假设输入符合规范。这是我的代码:
<?php
fscanf(STDIN, "%d", $numOfTestCases);
for ($i = 0; $i < $numOfTestCases; $i++) { //Loop for reading test cases
fscanf(STDIN, "%d", $numOfPhoneNumbers);
$phoneNumbers = array();
$isConsistent = true;
for ($j = 0; $j < $numOfPhoneNumbers; $j++) { //Loop for reading phone numbers of each test case
fscanf(STDIN, "%d", $newNumber);
if ($isConsistent != false) { //If list already inconsistent, we dont need to check further input
if (empty($phoneNumbers)) { // If the array of phone numbers is empty, we just add the new one
$phoneNumbers[$j] = $newNumber;
} else {
foreach ($phoneNumbers as $k => $testNumber) { //Loop for checking if new number is consistent or not
$newNumLen = strlen($newNumber);
$testNumlen = strlen($testNumber);
$newBeginning = substr($newNumber, 0, $testNumlen);
$testBeginning = substr($testNumber, 0, $newNumLen);
if ($newNumber == $testBeginning || $testNumber == $newBeginning) {
$isConsistent = false;
break;
}
}
if ($isConsistent == true) $phoneNumbers[$j] = $newNumber;
}
}
}
$newAnswer = ($isConsistent) ? "YES" : "NO";
$ansString = ($i == 0) ? $newAnswer : $ansString."\n".$newAnswer;
}
fwrite(STDOUT, $ansString);
exit(0);
?>
我的问题是有一个运行它的测试程序,超时为4秒。第二个测试文件总是超时。我无法访问测试程序或文件,但我认为文件很长,甚至可能有40个测试用例,每种情况下都有10000个电话号码。
任何人都可以看到我如何以任何方式让这段代码运行得更快?
以下是一个示例运行:
Sample Input:
2
3
911
97625999
91125426
5
113
12340
123440
12345
98346
Sample Output:
NO
YES
答案 0 :(得分:10)
如你所知,树是你的解决方案。 创建一个树,每个节点代表一个数字中的数字。 每个数字的最后一位数字将标记为isNumber = true,其余数字将标记为isNumber = false。
向树中添加数字时,遍历树的节点并检查是否遍历isNumber = true的节点。若然,则返回false / print something。
例如:见下面的ilustration
添加数字21:迭代数字。 create new node = 1,new node = 2(isNumber = true)
添加数字911:迭代数字。创建新节点= 9,新节点= 1,新节点= 1(isNumber = true) 添加数字9125:迭代数字。创建新节点= 9,新节点= 1,新节点= 2,新节点= 5(isNumber = true)
添加数字91 1 2:迭代数字。创建新节点= 9,新节点= 1,新节点= 1(错误:失败,因为isNumber = true )
希望它有所帮助。修改强>
好的,既然我感兴趣,我试图实施解决方案,而且我非常接近你的。
我制作了一个简单的脚本来创建一个 testcase.txt ,包含10000个数字(1≤n≤10000)。
我制作了一个简单的 unittest.php 脚本,该脚本在同一个文件上运行40次(1≤t≤40)。
<?php
// create_testcase.php
$handle = fopen("testcase.txt",'w');
for($i=0 ; $i < 10000 ; $i++){
$number = rand(1,9999999999);
fwrite($handle,$number."\n");
}
fclose($handle);
// unittest.php
class Node{
private $digit;
private $leaf = false;
private $children = array();
function __construct($digit,$leaf = false){
$this->digit = $digit;
$this->leaf = $leaf;
}
function isLeaf(){
return $this->leaf;
}
function hasChild($digit){
return array_key_exists($digit,$this->children);
}
function hasChildren(){
return count($this->children);
}
function addChild($digit,$isLeaf){
$this->children[$digit] = new Node($digit,$isLeaf);
return $this->children[$digit];
}
function getChild($digit){
return $this->children[$digit];
}
}
for($i=0 ; $i < 40 ; $i++){
$anchor = new Node(0,false);
$isConsistent = true;
$handle = fopen("testcase.txt",'r');
while(($number = fgets($handle)) != false){
$node = $anchor;
$number = rtrim($number);
$number_length = strlen($number);
foreach(str_split($number) as $index => $digit){
if($node->hasChild($digit)){
$node = $node->getChild($digit);
if($node->isLeaf()){
$isConsistent = false;
break;
}
}
else{
(($index+1) == $number_length) ? ($isLeaf = true) : ($isLeaf = false);
$node = $node->addChild($digit,$isLeaf);
}
}
if($node->hasChildren()){
$isConsistent = false;
}
if(!$isConsistent){
break; // don't continue to next number in test case
}
}
if($isConsistent){
print "Consist list\n";
}
else{
print "Not Consist list\n";
}
fclose($handle);
}
对于我的旧版仍在使用,core2duo,2GB内存的结果: 真实 0m26.123s 用户0m26.064s sys 0m0.048s
表示:40x10000 = 400,000个数字。
对于单个测试用例: 真实 0m0.554s 用户0m0.544s sys 0m0.008s