剑指-4和7幸运数字 (幸运数字 4和7)
2016-09-07 19:38
316 查看
题目:
我们把只包含4或7的数称为幸运数字.
例如:4,7,44,47,74,77等等是幸运数字,而41,42不是幸运数字.
求从小到大的顺序第M个幸运数字.而M的大小是,0
思路:
由于M数字可以非常大,基本上断绝了使用遍历的方式来求结果的方式。
我们可以首先看一下数字的规律,
第一行是为了方便计算自动补充的,当求第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已经在一个数组中了:
因为我们已经知道Q处于第四层了,而深度为2的节点总数又是22+1−1,那么用
Q−(22+1−1)−1就可以得到Q在第四层数组中的索引了,而Q = M+1,则可以知道M在第四层的索引为M−(22+1−1)。
到了此时,M所处的层数的索引也知道了,所处层数的数字位数也知道了,那么该如何求出在索引处的数字呢?
我们可以将4看做0,将7看做1,就会发现该层中
我们把只包含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
相关文章推荐
- 剑指offer-面试题41:和为s的两个数字VS和为s的连续正数序列
- 剑指Offer-44:数字序列中某一位的数字
- 牛客网 牛客练习赛13-幸运数字Ⅰ
- 剑指offer 旋转数组的最小数字
- 幸运数字 2
- 剑指offer 数字在排序数组中出现的次数 从尾到头打印链表 跳台阶 变态跳台阶
- 剑指Offer-面试题41-和为s 的两个数字vs 和为s 的连续正数序列
- Bzoj4568 [Scoi2016]幸运数字
- 剑指Offer之 - 数字在排序数组中出现的次数
- [剑指Offer]40.数组中只出现一次的数字
- 剑指offer-将字符串转化为数字
- 剑指Offer—40—数组中只出现一次的数字
- [剑指Java offer]4.数组中只出现一次的数字
- 剑指offer--圆圈中最后剩下的数字
- 剑指offer-8 旋转数组的最小数字
- 幸运数字 4和7
- 剑指offer — 数组中只出现一次的数字
- 剑指offer35题:第一个只出现一次的字符+剑指offer55题:字符流中第一个不重复的字符+剑指offer51题:数组中重复的数字
- 剑指Offer--029-数组中出现次数超过一半的数字
- [剑指Offer]数组中重复的数字