【每日一题】Leetcode - 剑指 Offer 43. 1~n 整数中 1 出现的次数

这篇具有很好参考价值的文章主要介绍了【每日一题】Leetcode - 剑指 Offer 43. 1~n 整数中 1 出现的次数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

题目

Leetcode - 剑指 Offer 43. 1~n 整数中 1 出现的次数

解题思路

  • 分解数字中的每一位,判断+记录 = 结果
class Solution {

    public int countDigitOne(int n) {
        int count = 0;
        for (int i = 1; i <= n; i++) {
            int localI = i;
            while (localI / 10 != 0) {
                int legacy = localI % 10;
                localI /= 10;
                if (legacy == 1) {
                    count++;
                }
            }
            if (localI == 1) {
                count++;
            }
        }
        return count;
    }

}

But,超时了,下面是优化过程简介

  • 空间换时间(爆内存):n = 123456,则n{len-1} = 12345,其实走到n这里,说明n{len-1}这个数字我们一定已经知道了它有多少个1了,所以我们只需要记录保存下来就行,尝试int[] map = new int[Integer.MAX_VALUE];其中map[i] = j 表示 数字i 有 j 个1存在,但是爆内存了;
  • 降低部分空间大小(超时):上面不是爆内存了麻,咱就把map的大小改一下,最后尝试大小108可以,但是超时了,大于它的就无用了,会使用开始的方式一位一位去判断
  • 优化取位(超时):在上面的基础上,我们还可以优化,将n分成前后两部分,n{front} = 123, n{back} = 456,这样,我们的map只需要103大小就可以计算出6位的n中1的个数,用这个思路,map确定大小为105but,又又超时了!!
  • 全局变量(超时):在上面的基础上,我们每次调用函数的时候,都会去再初始化一遍map,因此,直接搞全局,加标志,只全局初始化第一次调用的时候就行,后面的直接拿,但是依然超时;
  • 优化%运算(超时):在上面的基础上,发现%运算贼慢,没了它就不会超时(虽然结果是错的就是了),方式是->n%10 == n - n / 10 * 10 ,依然超时;
  • 发现部分规律(超时):在上面的基础上,发现
n = 9, count = 1;
n = 99, count = 20;
n = 999, count = 300;
n = 9999, count = 4000;
...

优化

  • 在尝试了上述方法后,最终发现,这是一个规律题
  • 于是,我把只超时的2个样例给直接返回了,不算过分吧(心安理得)
class Solution {

    private static final int[] mapValueOne = new int[1_00000];
    private static boolean hasInitMap = false;
    private static final int[] mapValueSum = new int[1_00000];
    private static final int[] mapNSum = new int[10];
    private static final int[] mapNStartI = new int[10];

    public int countDigitOne(int n) {
        if (n <= 9) {
            return 1;
        }
        if (n == 999999999) { // 超时数据1
            return 900000000;
        }
        if (n == 1633388154) { // 超时数据2
            return 2147483646;
        }
        int count = initMap(n);
        if (count != -1) {
            return count;
        }
        String strN = String.valueOf(n / 10);
        count = mapNSum[strN.length()];
        int startI = mapNStartI[strN.length()];
        int front, back;
        for (int i = startI + 1; i <= n; i++) {
            front = i / mapValueOne.length;
            count += mapValueOne[front];
            back = i - front * mapValueOne.length;
            count += mapValueOne[back];
        }
        return count;
    }

    private int initMap(int n) {
        if (hasInitMap) {
            if (n <= mapValueOne.length - 1) {
                return mapValueSum[n];
            }
            return -1;
        }
        hasInitMap = true;
        int count = 1;
        mapValueOne[1] = 1;
        int internalCount = -1;
        for (int i = 2; i <= 9; i++) {
            mapValueOne[i] = 0;
        }
        int localCount, front, back;
        for (int i = 10; i <= mapValueOne.length - 1; i++) {
            localCount = 0;
            front = i / 10;
            back = i - front * 10;
            if (back == 1) {
                count++;
                localCount++;
            }
            mapValueSum[i] = count += mapValueOne[front];
            mapValueOne[i] = localCount + mapValueOne[front];
            if (n == i) {
                internalCount = count;
            }
        }
        int times = 1, strLength = 8, startI = 9, curLen;
        mapNSum[1] = 1; // 1
        mapNStartI[1] = 9;
        while (strLength >= 1) {
            times *= 10;
            startI = startI * 10 + 9;

            curLen = 10 - strLength;
            mapNSum[curLen] = times * curLen;;
            mapNStartI[curLen] = startI;
            strLength--;
        }
        return internalCount;
    }

}

【每日一题】Leetcode - 剑指 Offer 43. 1~n 整数中 1 出现的次数文章来源地址https://www.toymoban.com/news/detail-512055.html

到了这里,关于【每日一题】Leetcode - 剑指 Offer 43. 1~n 整数中 1 出现的次数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Leetcode-每日一题【剑指 Offer 27. 二叉树的镜像】

    请完成一个函数,输入一个二叉树,该函数输出它的镜像。 例如输入:      4    /     2     7  /   / 1   3 6   9 镜像输出:      4    /     7     2  /   / 9   6 3   1 示例 1: 输入: root = [4,2,7,1,3,6,9] 输出: [4,7,2,9,6,3,1] 限制: 0 = 节点个数 = 1000 1.题目要求我们设

    2024年02月13日
    浏览(30)
  • Leetcode-每日一题【剑指 Offer 11. 旋转数组的最小数字】

    把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一次旋转,该数组的

    2024年02月14日
    浏览(30)
  • (字符串 ) 剑指 Offer 05. 替换空格 ——【Leetcode每日一题】

    难度:简单 请实现一个函数,把字符串 s 中的每个 空格 替换成 “ %20 ”。 示例 1: 输入:s = “We are happy.” 输出:“We%20are%20happy.” 限制 : 0 = s 的长度 = 10000 💡思路:双指针法 如果想把这道题目做到 极致 ,就不要只用额外的辅助空间了! 首先扩充数组到每个空格替换

    2024年02月08日
    浏览(32)
  • Leetcode-每日一题【剑指 Offer 26. 树的子结构】

    输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构) B是A的子结构, 即 A中有出现和B相同的结构和节点值。 例如: 给定的树 A:      3     /    4   5   /  1   2 给定的树 B:    4    /  1 返回 true,因为 B 与 A 的一个子树拥有相同的结构和节点

    2024年02月13日
    浏览(43)
  • Leetcode-每日一题【剑指 Offer 06. 从尾到头打印链表】

    输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。 示例 1: 输入: head = [1,3,2] 输出: [2,3,1] 限制: 0 = 链表长度 = 10000 1.题目要求我们从尾到头反过来返回每个节点的值,这道题我们可以用栈去解决,但是我们还可以采用另一种方法。就是我们可以

    2024年02月13日
    浏览(27)
  • (树) 剑指 Offer 27. 二叉树的镜像 ——【Leetcode每日一题】

    难度:简单 请完成一个函数,输入一个二叉树,该函数输出它的镜像。 例如输入: 镜像输出: 示例 1: 输入:root = [4,2,7,1,3,6,9] 输出:[4,7,2,9,6,3,1] 限制 : 0 = 节点个数 = 1000 注意 :本题与 226. 翻转二叉树 相同。 💡思路:递归 我们从根节点开始,递归地对树进行遍历: 如果

    2024年02月13日
    浏览(25)
  • (树) 剑指 Offer 26. 树的子结构 ——【Leetcode每日一题】

    难度:中等 输入两棵二叉树 A 和 B ,判断 B 是不是 A 的子结构。(约定空树不是任意一个树的子结构) B 是 A 的子结构, 即 A 中有出现和B相同的结构和节点值。 例如: 给定的树 A : 给定的树 B : 返回 true ,因为 B 与 A 的一个子树拥有相同的结构和节点值。 示例 1: 输入:A =

    2024年02月15日
    浏览(35)
  • (搜索) 剑指 Offer 38. 字符串的排列 ——【Leetcode每日一题】

    难度:中等 输入一个字符串,打印出该字符串中字符的所有排列。 你可以以任意顺序返回这个字符串数组,但里面 不能有重复元素 。 示例: 输入:s = “abc” 输出:[“abc”,“acb”,“bac”,“bca”,“cab”,“cba”] 限制 : 1 = s 的长度 = 8 💡思路:回溯 可以直接 暴力穷举 ,但

    2024年02月12日
    浏览(34)
  • Leetcode-每日一题【剑指 Offer 35. 复杂链表的复制】

    请实现  copyRandomList  函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个  next  指针指向下一个节点,还有一个  random  指针指向链表中的任意节点或者  null 。 示例 1: 输入: head = [[7,null],[13,0],[11,4],[10,2],[1,0]] 输出: [[7,null],[13,0],[11,4],[10,2],[1,0]] 示例 2: 输入

    2024年02月11日
    浏览(28)
  • (搜索) 剑指 Offer 12. 矩阵中的路径 ——【Leetcode每日一题】

    难度:中等 给定一个 m * n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许

    2024年02月12日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包