您的位置:首页 > 其它

剑指-4和7幸运数字 (幸运数字 4和7)

2016-09-07 19:38 316 查看
题目:

我们把只包含4或7的数称为幸运数字.

例如:4,7,44,47,74,77等等是幸运数字,而41,42不是幸运数字.

求从小到大的顺序第M个幸运数字.而M的大小是,0
<
M
<
10^18次幂

思路:

由于M数字可以非常大,基本上断绝了使用遍历的方式来求结果的方式。

我们可以首先看一下数字的规律,
[4,7,44,47,444,447,474,477,744,747,774,777]
,简单分析后,可以将其画成二叉树的形式:

0
4           7
44      47     74     77
444 447 474 477 744 747 774 777


第一行是为了方便计算自动补充的,当求第M个幸运数字时,可以看做求此二叉树的第Q个值,Q=M+1。

此外,可以看出二叉树不同的层次,数字位数是不同的,从第二层开始,每层的数字位数递增1,那么我们可以得知,当Q处于第N层时,那么该层的数字位数是N-1。

那么如何计算Q处于第几层呢?根据二叉树的性质得知,深度为k的完全二叉树,至少有2k个节点,至多有2k+1−1个节点,其中根节点的深度是0。

2k<Q<2k+1−1log2Q<k<log2(Q+1)−1

假设我们要求第8个节点(M=7),也就是第四层的第一个节点。

将其带入公式中:log28=3,可以得到第8个节点在深度为3的二叉树中,也就是在二叉树的第四层中。同样我们也可以得知第四层中的数字都是三位的。

到了此时,要求的Q已经在一个数组中了:
[444,447,474,477,774,747,774,777]
,那么如何进一步确定Q在第几个位置呢?

因为我们已经知道Q处于第四层了,而深度为2的节点总数又是22+1−1,那么用

Q−(22+1−1)−1就可以得到Q在第四层数组中的索引了,而Q = M+1,则可以知道M在第四层的索引为M−(22+1−1)。

到了此时,M所处的层数的索引也知道了,所处层数的数字位数也知道了,那么该如何求出在索引处的数字呢?

我们可以将4看做0,将7看做1,就会发现该层中
[000,001,010,011,100,101,110,111]
,而将他们分别转换成十进制就恰好是索引的数字,那么,我们就可以将索引转换为3位的二进制数,碰到一个碰到一个0就追加一个4,碰到一个1就追加一个7

public static void main(String[] args) {
System.out.println(  printLuckNumber(7));
}

private static String printLuckNumber(int m) {

// 求出m所在的深度
int k = (int) Math.ceil(Math.log((double) (m + 1)) / Math.log((double) 2));
// 求出m-1深度所有节点数
int preCount = (int) (Math.pow(2, k - 1 + 1 ) - 1);
// 计算索引
int index = (m - preCount);

// 追加0/1
StringBuilder sb = new StringBuilder();
for (int i = 0; i < k; i++) {
sb.append((index & 0x1) == 1 ? '7' : '4');
index >>>= 1;
}
return sb.reverse().toString();
}


结果
444
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: