难题
对于每个输入数n(n <10),存在输出数m,使得:
输出应为m,其中m是满足上述条件的最小数。如果没有这样的数字,则输出应为-1;
示例
n = 3 - &gt; m = 311
n = 4 - &gt; m = 4113(请注意,这不是4111,因为它将重复11)
n = 9 - &gt; m = 971131737
我有点工作的解决方案
这是我对此的第一次尝试,即“蛮力”方法。我正在寻找一种更优雅的解决方案,因为随着n变大,效率非常低。
public long GetM(int n)
{
long start = n * (long)Math.Pow((double)10, (double)n - 1);
long end = n * (long)Math.Pow((double)10, (double)n);
for (long x = start; x < end; x++)
{
long xCopy = x;
bool allDigitsPrime = true;
List<int> allPrimeNumbers = new List<int>();
while (xCopy >= 10)
{
long lastDigitsLong = xCopy % 100;
int lastDigits = (int)lastDigitsLong;
bool lastDigitsSame = allPrimeNumbers.Count != 0 && allPrimeNumbers.Contains(lastDigits);
if (!IsPrime(lastDigits) || lastDigitsSame)
{
allDigitsPrime = false;
break;
}
xCopy /= 10;
allPrimeNumbers.Add(lastDigits);
}
if (n != 1 && allDigitsPrime)
{
return x;
}
}
return -1;
}
关于如何提高效率的初步想法
所以,显然这里的瓶颈是遍历整个数字列表,这些数字可以满足这个条件从n ....到(n + 1)....除了简单地增加循环的每次迭代的次数之外,必须有一些聪明的方法来根据2位数序列必须是素数的要求来跳过数字。例如,对于n = 5,没有点经过50000 - 50999(50不是素数),51200 - 51299(12不是素数),但我不太确定如何实现这一点或者如果它这将足以使算法运行n = 9。
有关此方法或不同优化方法的任何想法?
答案 0 :(得分:3)
您不必尝试所有号码。你可以使用不同的策略,总结为&#34;尝试追加数字&#34;。
哪个数字?好吧,这样的数字
这应该以递归方式(而不是迭代方式)完成,因为您可能会用完选项,然后您必须回溯并在数字的前面尝试不同的数字。
这仍然是指数时间算法,但它避免了大部分搜索空间,因为它从不尝试任何不符合规则的数字,即每对相邻数字必须形成素数。
答案 1 :(得分:2)
这是R中使用递归的可能解决方案。构建所有可能路径的树
会很有趣# For every input number n (n < 10)
# there is an output number m such that:
# m's first digit is n
# m is an n digit number
# every 2 digit sequence inside m must be a different prime number
# Need to select the smallest m that meets the criteria
library('numbers')
mNumHelper <- function(cn,n,pr,cm=NULL) {
if (cn == 1) {
if (n==1) {
return(1)
}
firstDigit <- n
} else {
firstDigit <- mod(cm,10)
}
possibleNextNumbers <- pr[floor(pr/10) == firstDigit]
nPossible = length(possibleNextNumbers)
if (nPossible == 1) {
nextPrime <- possibleNextNumbers
} else{
# nextPrime <- sample(possibleNextNumbers,1)
nextPrime <- min(possibleNextNumbers)
}
pr <- pr[which(pr!=nextPrime)]
if (is.null(cm)) {
cm <- nextPrime
} else {
cm = cm * 10 + mod(nextPrime,10)
}
cn = cn + 1
if (cn < n) {
cm = mNumHelper(cn,n,pr,cm)
}
return(cm)
}
mNum <- function(n) {
pr<-Primes(10,100)
m <- mNumHelper(1,n,pr)
}
for (i in seq(1,9)) {
print(paste('i',i,'m',mNum(i)))
}
示例输出
[1] "i 1 m 1"
[1] "i 2 m 23"
[1] "i 3 m 311"
[1] "i 4 m 4113"
[1] "i 5 m 53113"
[1] "i 6 m 611317"
[1] "i 7 m 7113173"
[1] "i 8 m 83113717"
[1] "i 9 m 971131737"
更新解决方案以从可用素数集中选择最小素数,并删除错误路径检查,因为它不是必需的。
答案 2 :(得分:0)
我刚刚列出了两位数的素数,然后手工解决问题;它只用了几分钟。不是每个问题都需要一台电脑!