校招算法笔面试 | 校招笔面试真题-幸运数字

校招算法笔面试之幸运数字真题解析

题目## 题目

题目链接

解题思路

这是一道数字组合的递归题目,主要思路如下:

  1. 首先判断输入的合法性:

    • a a a b b b 必须在 1 1 1 1000000000 1000000000 1000000000 之间
    • b b b 必须大于等于 a a a
  2. 计算思路:

    • 获取 a a a b b b 的位数 ( l e n A ) (lenA) (lenA) ( l e n B ) (lenB) (lenB)
    • 对于每个长度从 l e n A lenA lenA l e n B lenB lenB 的数字进行组合
    • 使用递归生成所有可能的6和8的组合
    • 判断生成的数字是否在 [ a , b ] [a,b] [a,b] 范围内
  3. 优化:

    • 当数字长度超过10位时直接返回
    • 使用字符数组构建数字,最后转换为整数比较

代码

#include <iostream>
#include <string>
using namespace std;

int a, b, count = 0;

// 计算数字的位数
int intlen(int num) {
    int i = 0;
    while(num) {
        num /= 10;
        i++;
    }
    return i;
}

// 递归生成数字
void generate(char cs[], int index, int len) {
    // 超过10位直接返回
    if(len >= 10) return;
    
    // 当前位数已满,检查数字是否在范围内
    if(index == len) {
        int num = atoi(cs);
        if(num >= a && num <= b) {
            count++;
        }
        return;
    }
    
    // 在当前位置尝试6和8
    for(int i = 0; i < 2; i++) {
        cs[index] = (i == 0) ? '6' : '8';
        generate(cs, index + 1, len);
    }
}

int main() {
    // 输入并检查合法性
    cin >> a;
    if(a < 1 || a > 1000000000) {
        cout << "-1" << endl;
        return 0;
    }
    
    cin >> b;
    if(b < a || b > 1000000000) {
        cout << "-1" << endl;
        return 0;
    }
    
    // 计算位数范围
    int lenA = intlen(a);
    int lenB = intlen(b);
    
    // 对每个可能的位数生成组合
    for(int i = lenA; i <= lenB; i++) {
        char cs[11] = {0};  // 多分配一位用于字符串结束符
        generate(cs, 0, i);
    }
    
    cout << count << endl;
    return 0;
}
import java.util.*;

public class Main {
    static int count = 0;
    static int a, b;
    
    // 计算数字的位数
    static int intlen(int num) {
        int i = 0;
        while(num > 0) {
            num /= 10;
            i++;
        }
        return i;
    }
    
    // 递归生成数字
    static void generate(char[] cs, int index, int len) {
        if(len >= 10) return;
        
        if(index == len) {
            int num = Integer.parseInt(new String(cs, 0, len));
            if(num >= a && num <= b) {
                count++;
            }
            return;
        }
        
        for(int i = 0; i < 2; i++) {
            cs[index] = (i == 0) ? '6' : '8';
            generate(cs, index + 1, len);
        }
    }
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        a = sc.nextInt();
        if(a < 1 || a > 1000000000) {
            System.out.println("-1");
            return;
        }
        
        b = sc.nextInt();
        if(b < a || b > 1000000000) {
            System.out.println("-1");
            return;
        }
        
        int lenA = intlen(a);
        int lenB = intlen(b);
        
        for(int i = lenA; i <= lenB; i++) {
            char[] cs = new char[i];
            generate(cs, 0, i);
        }
        
        System.out.println(count);
    }
}
def intlen(num):
    """计算数字的位数"""
    i = 0
    while num:
        num //= 10
        i += 1
    return i

def generate(cs, index, length, a, b):
    """递归生成数字"""
    if length >= 10:
        return 0
        
    if index == length:
        num = int(''.join(cs[:length]))
        if a <= num <= b:
            return 1
        return 0
    
    count = 0
    for digit in ['6', '8']:
        cs[index] = digit
        count += generate(cs, index + 1, length, a, b)
    return count

def main():
    # 输入并检查合法性
    a, b = map(int, input().split())
    if a < 1 or a > 1000000000:
        print("-1")
        return
        
    if b < a or b > 1000000000:
        print("-1")
        return
    
    # 计算位数范围
    len_a = intlen(a)
    len_b = intlen(b)
    
    # 统计所有可能的组合
    total = 0
    for length in range(len_a, len_b + 1):
        cs = ['0'] * length
        total += generate(cs, 0, length, a, b)
    
    print(total)

if __name__ == "__main__":
    main()

算法及复杂度

  • 算法:递归 + 回溯
  • 时间复杂度: O ( 2 n ) \mathcal{O}(2^n) O(2n) - 其中 n n n 为数字的最大位数,每位有2种选择
  • 空间复杂度: O ( n ) \mathcal{O}(n) O(n) - 递归调用栈的深度为数字的位数

题目链接

解题思路

这是一个进制转换和数位和计算问题。关键点:

  1. 十进制数位和 f ( x ) f(x) f(x)

    • 对数字 x x x 10 10 10 取余,累加每一位
    • f ( 123 ) = 1 + 2 + 3 = 6 f(123) = 1 + 2 + 3 = 6 f(123)=1+2+3=6
  2. 二进制数位和g(x)

    • 对数字 x x x 2 2 2 取余,累加每一位
    • 123 ( 1111011 ) 123(1111011) 123(1111011) g ( 123 ) = 1 + 1 + 1 + 1 + 0 + 1 + 1 = 6 g(123) = 1+1+1+1+0+1+1 = 6 g(123)=1+1+1+1+0+1+1=6
  3. 幸运数判断

    • 遍历 1 1 1 n n n 的每个数
    • 判断 f ( x ) = = g ( x ) f(x) == g(x) f(x)==g(x)

代码

#include <iostream>
using namespace std;

// 计算十进制数位和
int getDecimalSum(int x) {
    int sum = 0;
    while(x > 0) {
        sum += x % 10;
        x /= 10;
    }
    return sum;
}

// 计算二进制数位和
int getBinarySum(int x) {
    int sum = 0;
    while(x > 0) {
        sum += x & 1;
        x >>= 1;
    }
    return sum;
}

int main() {
    int n;
    while(cin >> n) {
        int count = 0;
        for(int i = 1; i <= n; i++) {
            if(getDecimalSum(i) == getBinarySum(i)) {
                count++;
            }
        }
        cout << count << endl;
    }
    return 0;
}
import java.util.*;

public class Main {
    // 计算十进制数位和
    private static int getDecimalSum(int x) {
        int sum = 0;
        while(x > 0) {
            sum += x % 10;
            x /= 10;
        }
        return sum;
    }
    
    // 计算二进制数位和
    private static int getBinarySum(int x) {
        int sum = 0;
        while(x > 0) {
            sum += x & 1;
            x >>= 1;
        }
        return sum;
    }
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()) {
            int n = sc.nextInt();
            int count = 0;
            for(int i = 1; i <= n; i++) {
                if(getDecimalSum(i) == getBinarySum(i)) {
                    count++;
                }
            }
            System.out.println(count);
        }
    }
}
# -*- coding:utf-8 -*-

def get_decimal_sum(x):
    """计算十进制数位和"""
    sum = 0
    while x > 0:
        sum += x % 10
        x //= 10  # 使用整除
    return sum

def get_binary_sum(x):
    """计算二进制数位和"""
    sum = 0
    while x > 0:
        sum += x & 1
        x >>= 1
    return sum

while True:
    try:
        n = int(input())  # 改用input()
        count = 0
        for i in range(1, n + 1):  # 改用range
            if get_decimal_sum(i) == get_binary_sum(i):
                count += 1
        print(count)  # 添加括号
    except:
        break

算法及复杂度

  • 算法:模拟
  • 时间复杂度: O ( n log ⁡ n ) \mathcal{O}(n\log n) O(nlogn),每个数字需要 O ( log ⁡ n ) O(\log n) O(logn) 的时间计算数位和
  • 空间复杂度: O ( 1 ) \mathcal{O}(1) O(1),只使用常数额外空间
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值