我给了两个整数“ n”和“ m”,我必须找到在[n,m]范围内的所有步进数。如果所有相邻数字的绝对差为2,则该数字称为步进数。131是步进数,而421不是。我面临的问题是我必须按排序顺序打印它们,而不能重复从小到大的数字但是我的算法会随机打印它们,并且M最多可以为10 ^ 30,这在设置我的程序时会耗尽内存。有什么建议我该怎么做?
import java.util.*;
class Main {
public static void bfs(Long n, Long m, Long num) {
Queue<Long> q = new LinkedList<Long>();
q.add(num);
while (!q.isEmpty()) {
Long stepNum = q.poll();
if (stepNum <= m && stepNum >= n) {
System.out.print(stepNum+" ");
}
if (stepNum == 0 || stepNum > m)
continue;
Long lastDigit = stepNum % 10;
Long stepNumA = stepNum * 10 + (lastDigit - 2);
Long stepNumB = stepNum * 10 + (lastDigit + 2);
if (lastDigit == 0)
q.add(stepNumB);
else if (lastDigit == 9)
q.add(stepNumA);
else {
q.add(stepNumA);
q.add(stepNumB);
}
}
}
public static void displaySteppingNumbers(Long n, Long m) {
for (Long i = (long) 0; i <= 9; i++)
bfs(n, m, i);
}
// Driver code
public static void main(String args[]) {
Long n = (long) 1;
Long m = (long) Math.pow(10, 16);
displaySteppingNumbers(n, m);
}
}
答案 0 :(得分:1)
我相信您可能已经考虑过了。我将从一种确定单个long
是否为步进数的方法开始。使用String.valueOf(long)
获得String
表示形式,然后遍历该String
中的字符,比较相邻的值。如果两个数字的绝对差不是2,则返回false。检查所有数字后,默认为true
。喜欢,
private static boolean isSteppingNumber(long v) {
char[] arr = String.valueOf(v).toCharArray();
for (int i = 0; i + 1 < arr.length; i++) {
// The - '0' is really only useful for debugging.
int a = arr[i] - '0', b = arr[i + 1] - '0';
if (Math.abs(b - a) != 2) {
return false;
}
}
return true;
}
并且,如果有帮助,您可以使用lambda之类的方法
private static boolean isSteppingNumber(long v) {
char[] arr = String.valueOf(v).toCharArray();
return IntStream.range(0, arr.length - 1)
.allMatch(i -> Math.abs(arr[i + 1] - arr[i]) == 2);
}
接下来,从n
到m
的循环(我更喜欢原始的long
类型)。喜欢,
public static void displaySteppingNumbers(long n, long m) {
LongStream.rangeClosed(n, m).filter(x -> isSteppingNumber(x))
.forEachOrdered(System.out::println);
}
答案 1 :(得分:0)
您有一个正确的想法,就是可以像搜索图形一样搜索数字。但是,为了以正确的顺序获取它们,我建议使用最低优先级队列而不是队列。
您的实现还有另一个问题-您没有正确检查邻接关系的边界,例如如果lastDigit大于7,则lastDigit + 2不相邻。
import java.util.*;
public class Main {
public static void displaySteppingNumbers(Long m, Long n) {
PriorityQueue<Long> heap = new PriorityQueue<>();
for (Long i = 1L; i <= 9L; i++) {
heap.add(i);
}
while (heap.peek() <= n) {
Long steppingNumber = heap.poll();
System.out.println(steppingNumber);
Long lastDigit = steppingNumber % 10;
if (lastDigit >= 2)
heap.add(steppingNumber * 10 + lastDigit - 2);
if (lastDigit <= 7)
heap.add(steppingNumber * 10 + lastDigit + 2);
}
}
public static void main(String []args){
Long m = 100L;
Long n = 300L;
displaySteppingNumbers(m, n);
}
}
答案 2 :(得分:0)
请在将来发布伪信息。 这是程序中前1000个数字的输出:
1 9 13 97 131 135 975 979
2 20 24 202 242 246
3 31 35 309 313 353 357
4 42 46 420 424 464 468
5 53 57 531 535 575 579
6 64 68 642 646 686 690
7 75 79 753 757 797
8 86 90 864 868 902
9 97 975 979
我只是在每个bfs调用之前添加了/n
。
这实际上是一个有趣的小难题
写出一组数字的输出
您会找到一个二进制链接,其中0表示
依次减2和1,再在
中减2
序列,即数字131357
可以写为:
110111
,您只需要查找之间的所有二进制数
给定范围,这就是您的解决方案:D