我发现这个面试问题四处游荡,经过深思熟虑,我无法真正为它开发出合理的算法。
给定一串按顺序排列的数字,找到缺失的数字。数字的范围没有给出。
示例输入:“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 被报告为缺失数字。
digits=1
digits
数字只包含数字一样。 digit+=1
,转到 1。 digit+=1
则转到2,否则您已找到间隙。 digit+=1
,转到2。(我不确定这种情况是否会发生) 示例:
给定:“131416”。
1.digits=1
2.解析'1' 3.解析'3'
4.不减
5.可能发现差距:解析其余的'1416'失败,因为'1' != '4'
=> digit+ =1 (digit=2) goto 2
2. parse '13'
3. parse '14'
4. 它不减少
5. 它不比最后解析的一 (13) 高 2
6. 它高 1 (14 = 13+1) => goto 3
3. 解析 '16'
4. 它没有减少
5. 可能找到了差距:解析剩下的 '' 因为没有什么要解析了,
=> 找到了 gab: '15' 是丢失的号码
当然,唯一困难的部分是弄清楚数字有多少位数。我看到两种方法。
这是一个可用的 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;
}
这可能会大大简化,但在探索性编码期间,我喜欢写出清晰易懂的代码,而不是尝试用尽可能少的代码行或尽可能快的速度编写它。