导入:
对某个整数进行遍历,按常规的编程思维都是
for(int i=0;i<=number;i++){}
但是如果这个数比较大,大到无法的话,可能使用普通for循环方式进行遍历就有些吃力了。
那么针对这个问题,可以考虑深度搜索算法dfs来辅助完成。
对于要遍历的这个数来说,不要当成是一个数,要当成一个由多个单数组成的字符串。
这样的话就将数的遍历,变成了对数串的每一位进行遍历。
- 可以考虑将这个数拆分成一个数组
如 134512=>[2,1,5,4,3,1]
321=>[1,2,3]
即 数最高位在数组中依然是最高位(索引值最大,且为数位-1)
用java实现可以参考这个写法:
num%10 取num的个位
num/=10 去除num的个位(减少一位)
public static int raw[]=null;// 数值拆分后单个数值
public static void Handle(int num){
raw=new int[(num+"").length()];
for(int i=0;i<raw.length;i++){
raw[i]=num%10;
num/=10;
}
}
- 使用dfs算法递归输出数据
若要输出[0-235]区间内所有整数,可以参考下列这个图来进行理解。
- 整个数可以分成3位,那么第一个数就是000,第二个数就是001 ===》最高位为0,1,2可以选择。当第一位选择0和1时,后面的几位都不做限制可以选择0-9任意数。而当第一位为2时,那么第二位的值便不能是0-9了。比如当第二位取4时,那么第三位取0也得到240,比235还大。
- 因此可以定义一个变量为当前取值位置p,第一次是p为最高位,在数组中的索引位置为长度-1,即数组的最后一位。这里不理解可以参考321=>[1,2,3]
- 还得再定义一个变量就是当前位置取值是否已经达到临界点。
如最高位取值为0时,后续两位可以取到000-099
最高位取1时,后续两位可以取到100-199
最高位取2时,后续两位就不能取到200-299了。这时就需要告诉下一位,即第二位,取值时不能超过自身原本的上限值3. 若超过,那么就超过原本的数值范围,无意义了。那么定义一个布尔类型的变量limit就很有必要了。
4.当定义位置小于0时,证明已经遍历完这个数了就不再进行深度递归了。
具体的java代码实现参考
public static int num[]=null;//每次递归产生的一个数
public static void dfs(int p,boolean limit){
if(p<0){
for(int i=raw.length-1;i>=0;i--){
System.out.print(num[i]);
}
System.out.println();
return;
}
int up=limit?raw[p]:9;//如果上一位是限制位,那么当前位最大值是对应的那位的值 否则当前位最大值为9
for(int i=0;i<=up;i++){
num[p]=i;
dfs(p-1, limit&&i==up); //limit&&i==up 如果当前i已经是最大的那个值,证明已经到达限制位了 如 2 3 5 的最高位为2 那么 0 1 不是限制位 2就到达临界点,就到限制位了
}
}
可以借助这个图来进行代码理解
例如 215 生成过程
- 先dfs(p=2,limit=true)=> 产生for(int i=0;i<=2;i++){}循环 当i=1时,dfs(p=1,limit=false)
i=2时 此时b[2]=2- dfs(p=1,limit=true) =>此时的上限值为3 产生for(int i=0;i<=3;i++){}循环 i=1是 b[1]=1;
- 再继续dfs[p=0,limit=false] =>此时的上限值为9 产生for(int i=0;i<=9;i++){} i=5时 b[0]=5;
- 因此df递归三次形成了一个数组b
b[2]=2,b[1]=1,b[0]=3 ===》调换顺序输出结果为213
完整的示例如下:
public class Test {
//深度搜索
public static int raw[]=null;// 数值拆分后单个数值
public static int num[]=null;//每次递归产生的一个数
public static void dfs(int p,boolean limit){
if(p<0){
for(int i=raw.length-1;i>=0;i--){
System.out.print(num[i]);
}
System.out.println();
return;
}
int up=limit?raw[p]:9;//如果上一位是限制位,那么当前位最大值是对应的那位的值 否则当前位最大值为9
//注意理解这个循环 第一次循环 其产生的是最高位 第一次循环中每次循环都递归调用了 且p变成了p-1 也即是dfs这个函数会紧接着生成第二位 然后是第三位
for(int i=0;i<=up;i++){
num[p]=i;
dfs(p-1, limit&&i==up);
}
}
public static void Handle(int number){
raw=new int[(number+"").length()];
num=new int[(number+"").length()];
for(int i=0;i<raw.length;i++){
raw[i]=number%10;
number/=10;
}
dfs(raw.length-1, true); //第一层就是有限制的
}
public static void main(String[] args) {
//数位搜索算法
int num=123;
Handle(num);
}
…
说明
- 这个案例只是演示了数位算法生成一个范围数的过程,其效率因为输出语句等原因,并没有使用普通for循环那么来得快,具体如何使用。还需要各位看官进一步深究。
- 本案例通过数位算法,来提供了一种遍历某个范围数的过程。而不是简单逐个相加
- 此案例经测试,如果不加输出语句的话,其执行效率还是蛮ok的。有兴趣的可以测一测不加输出语句时,这个算法和for循环哪个的速度更快一些。