LeetCode.2999. 统计强大整数的数目

统计强大整数的数目

  • 题目
  • 整体思路
  • Code
  • 代码详细解释
    • `calculate` 函数
    • `numberOfPowerfulInt` 函数
  • 复杂度分析

题目

2999. 统计强大整数的数目

给你三个整数 startfinishlimit 。同时给你一个下标从 0 开始的字符串 s ,表示一个 整数。

如果一个 整数 x 末尾部分是 s (换句话说,sx后缀),且 x 中的每个数位至多是 limit ,那么我们称 x强大的

请你返回区间 [start..finish] 内强大整数的 总数目

如果一个字符串 xy 中某个下标开始(包括 0 ),到下标为 y.length - 1 结束的子字符串,那么我们称 xy 的一个后缀。比方说,255125 的一个后缀,但不是 512 的后缀。

示例 1:
输入:start = 1, finish = 6000, limit = 4, s = "124"
输出:5
解释:区间 [1..6000] 内的强大数字为 124 ,1124 ,2124 ,3124 和 4124 。这些整数的各个数位都 <= 4 且 "124" 是它们的后缀。注意 5124 不是强大整数,因为第一个数位 5 大于 4 。
这个区间内总共只有这 5 个强大整数。

示例 2:
输入:start = 15, finish = 215, limit = 6, s = "10"
输出:2
解释:区间 [15..215] 内的强大整数为 110 和 210 。这些整数的各个数位都 <= 6 且 "10" 是它们的后缀。
这个区间总共只有这 2 个强大整数。

示例 3:
输入:start = 1000, finish = 2000, limit = 4, s = "3000"
输出:0
解释:区间 [1000..2000] 内的整数都小于 3000 ,所以 "3000" 不可能是这个区间内任何整数的后缀。

整体思路

代码通过两个主要函数 calculatenumberOfPowerfulInt 来完成计算。

  • calculate 函数:用于计算小于等于给定整数 x 且以字符串 s 为后缀,同时每个数位都不超过 limit 的整数的数量。
  • numberOfPowerfulInt 函数:利用 calculate 函数,通过计算 finishstart - 1 对应的满足条件的整数数量,然后相减得到区间 [start, finish] 内满足条件的整数数量。

Code

long long calculate(const char* x, const char* s, int limit) {
    int x_len = strlen(x);
    int s_len = strlen(s);
    if (x_len < s_len) {
        return 0;
    }
    if (x_len == s_len) {
        return strcmp(x, s) >= 0 ? 1 : 0;
    }

    char* suffix = (char*)malloc(s_len + 1);
    strncpy(suffix, x + x_len - s_len, s_len);
    suffix[s_len] = '\0';
    long long count = 0;
    int preLen = x_len - s_len;
    
    for (int i = 0; i < preLen; i++) {
        int digit = x[i] - '0';
        if (limit < digit) {
            count += (long long)pow(limit + 1, preLen - i);
            free(suffix);
            return count;
        }
        count += (long long)digit * (long long)pow(limit + 1, preLen - 1 - i);
    }
    if (strcmp(suffix, s) >= 0) {
        count++;
    }
    free(suffix);
    return count;
}

long long numberOfPowerfulInt(long long start, long long finish, int limit, const char* s) {
    char start_[20], finish_[20];
    sprintf(start_, "%lld", start - 1);
    sprintf(finish_, "%lld", finish);
    return calculate(finish_, s, limit) - calculate(start_, s, limit);
}

代码详细解释

calculate 函数

long long calculate(const char* x, const char* s, int limit) {
    int x_len = strlen(x);
    int s_len = strlen(s);
    if (x_len < s_len) {
        return 0;
    }
    if (x_len == s_len) {
        return strcmp(x, s) >= 0 ? 1 : 0;
    }

    char* suffix = (char*)malloc(s_len + 1);
    strncpy(suffix, x + x_len - s_len, s_len);
    suffix[s_len] = '\0';
    long long count = 0;
    int preLen = x_len - s_len;
    
    for (int i = 0; i < preLen; i++) {
        int digit = x[i] - '0';
        if (limit < digit) {
            count += (long long)pow(limit + 1, preLen - i);
            free(suffix);
            return count;
        }
        count += (long long)digit * (long long)pow(limit + 1, preLen - 1 - i);
    }
    if (strcmp(suffix, s) >= 0) {
        count++;
    }
    free(suffix);
    return count;
}
  • 参数说明

    • x:表示一个整数的字符串形式。
    • s:表示后缀字符串。
    • limit:表示每个数位的上限。
  • 逻辑步骤

    1. 长度检查
    • x 的长度小于 s 的长度,说明 x 不可能以 s 为后缀,直接返回 0。
    • x 的长度等于 s 的长度,使用 strcmp 函数比较 xs,若 x 大于等于 s,则返回 1,否则返回 0。
    1. 提取后缀
    • 分配内存给 suffix 用于存储 x 的后缀部分,长度为 s_len
    • 使用 strncpy 函数复制 x 的后缀部分到 suffix,并添加字符串结束符 '\0'
    1. 计算前缀部分的组合数
    • preLen 表示 x 除去后缀部分的长度。
    • 遍历 x 的前缀部分,对于每个数位:
      • 若该数位大于 limit,则计算剩余部分所有可能的组合数(每个数位可以取 0 到 limitlimit + 1 种值),并返回结果。
      • 否则,累加当前数位乘以剩余部分所有可能的组合数。
    1. 检查后缀
    • suffix 大于等于 s,则满足条件的整数数量加 1。
    1. 释放内存并返回结果
    • 释放 suffix 分配的内存,并返回满足条件的整数数量。

numberOfPowerfulInt 函数

long long numberOfPowerfulInt(long long start, long long finish, int limit, const char* s) {
    char start_[20], finish_[20];
    sprintf(start_, "%lld", start - 1);
    sprintf(finish_, "%lld", finish);
    return calculate(finish_, s, limit) - calculate(start_, s, limit);
}
  • 参数说明

    • start:区间的起始值。
    • finish:区间的结束值。
    • limit:每个数位的上限。
    • s:表示后缀字符串。
  • 逻辑步骤

    1. 将整数转换为字符串
    • 使用 sprintf 函数将 start - 1finish 转换为字符串形式,分别存储在 start_finish_ 中。
    1. 计算区间内满足条件的整数数量
    • 调用 calculate 函数分别计算小于等于 finish 和小于等于 start - 1 的满足条件的整数数量。
    • 两者相减得到区间 [start, finish] 内满足条件的整数数量,并返回结果。

复杂度分析

  • 时间复杂度calculate 函数的时间复杂度为 O ( l o g 10 x ) O(log_{10}x) O(log10x),其中 x x x 是输入的整数。numberOfPowerfulInt 函数调用两次 calculate 函数,因此总的时间复杂度也是 O ( l o g 10 f i n i s h ) O(log_{10}finish) O(log10finish)
  • 空间复杂度:主要是 calculate 函数中分配的 suffix 数组的空间,空间复杂度为 O ( l o g 10 x ) O(log_{10}x) O(log10x),其中 x x x 是输入的整数。

你可能感兴趣的:(LeetCode,linux,运维,leetcode,算法,数据结构,链表)