我发现了这个面试问题,经过深思熟虑,我并没有能够开发出一个可靠的算法。
给定一个连续数字的字符串,找出缺失的数字。数字范围未知。
样例输入:"9899100101103104105"
答案:102
我发现了这个面试问题,经过深思熟虑,我并没有能够开发出一个可靠的算法。
给定一个连续数字的字符串,找出缺失的数字。数字范围未知。
样例输入:"9899100101103104105"
答案:102
这是一个简单的问题。
以你的例子为例:
9899100101103104105
首先猜测长度为1
read 9
the next number should be either 10 or 11. Read the next two digits, you get 89.
That is incorrect, so the initial guess was wrong.
第二次猜测长度为2
read 98
the next number should be either 99 or 100. Read the next two digits for 99
the next number should be either 100 or 101. Read the next three digits for 100
... 101
... 103 (remember 102 as the missed number)
... 104
... 105
end of input
长度为2的猜测被确认为正确的猜测,102报告为缺失数字。
这里有一个可行的C#解决方案,你可以在LINQPad中检查:
void Main()
{
FindMissingNumberInString("9899100101103104105").Dump("Should be 102");
FindMissingNumberInString("78910121314").Dump("Should be 11");
FindMissingNumberInString("99899910011002").Dump("Should be 1000");
// will throw InvalidOperationException, we're missing both 1000 and 1002
FindMissingNumberInString("99899910011003");
}
public static int FindMissingNumberInString(string s)
{
for (int digits = 1; digits < 4; digits++)
{
int[] numbers = GetNumbersFromString(s, digits);
int result;
if (FindMissingNumber(numbers, out result))
return result;
}
throw new InvalidOperationException("Unable to determine the missing number fro '" + s + "'");
}
public static int[] GetNumbersFromString(string s, int digits)
{
var result = new List<int>();
int index = digits;
int number = int.Parse(s.Substring(0, digits));
result.Add(number);
while (index < s.Length)
{
string part;
number++;
digits = number.ToString().Length;
if (s.Length - index < digits)
part = s.Substring(index);
else
part = s.Substring(index, digits);
result.Add(int.Parse(part));
index += digits;
}
return result.ToArray();
}
public static bool FindMissingNumber(int[] numbers, out int missingNumber)
{
missingNumber = 0;
int? found = null;
for (int index = 1; index < numbers.Length; index++)
{
switch (numbers[index] - numbers[index - 1])
{
case 1:
// sequence continuing OK
break;
case 2:
// gap we expect to occur once
if (found == null)
found = numbers[index] - 1;
else
{
// occured twice
return false;
}
break;
default:
// not the right sequence
return false;
}
}
if (found.HasValue)
{
missingNumber = found.Value;
return true;
}
return false;
}
这段代码可能可以大大简化,但在探索性编程时,我喜欢编写清晰易懂的代码,而不是试图用尽可能少的代码行或尽可能快地编写它。
当然,唯一困难的部分是确定数字有多少位。我看到两种方法。
digits=1
digits
个数字。digit+=1
,回到1。digit+=1
,回到2,否则你已经找到了间隙。digit+=1
,回到2。(我不确定这种情况是否会发生)示例:
给定:"131416"。
1. 数字=1
2. 解析 '1'
3. 解析 '3'
4. 它没有减少
5. 可能找到了间隙:解析剩余的 '1416' 失败,因为 '1' != '4'
=> 数字+=1 (数字=2) 转到 2
2. 解析 '13'
3. 解析 '14'
4. 它没有减少
5. 它不比上次解析的数(13)高2
6. 它比上次解析的数高1(14 = 13+1)=> 转到 3
3. 解析 '16'
4. 它没有减少
5. 可能找到了间隙:解析剩余的 '' 成功,因为没有更多的内容可解析,
=> 找到了间隙:'15' 是缺失的数字