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

news2024/11/18 19:33:22

题目

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;
    }

}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/706779.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Leetcode-每日一题【143.重排链表】

题目 给定一个单链表 L 的头节点 head &#xff0c;单链表 L 表示为&#xff1a; 请将其重新排列后变为&#xff1a; 不能只是单纯的改变节点内部的值&#xff0c;而是需要实际的进行节点交换。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5]输出&#xff1a;[1,5,2,…

Ubuntu 23.10 现在由Linux内核6.3提供支持

对于那些希望在Ubuntu上尝试最新的Linux 6.3内核系列的人来说&#xff0c;今天有一个好消息&#xff0c;因为即将发布的Ubuntu 23.10&#xff08;Mantic Minotaur&#xff09;已经重新基于Linux内核6.3。 Ubuntu 23.10的开发工作于4月底开始&#xff0c;基于目前的临时版本Ubu…

光模块封装类型有哪些?光模块“皮肤”大揭秘

什么是光模块&#xff1f; 光模块&#xff08;Optical Transceiver&#xff09;全称为光收发一体模块&#xff0c;它是光通信中的核心器件&#xff0c;能够完成信号的光-电/电-光转换过程&#xff0c;它由光电子器件、功能电路和光接口等部件组成&#xff0c;其中的光电子器件…

【STL】iterator adapters_反向迭代器的实现

放在专栏【C知识总结】&#xff0c;会持续更新&#xff0c;期待支持 本章相关文章&#xff1a; 【STL】容器适配器 【STL】list的模拟实现 【STL】vector的模拟实现 1、反向迭代器介绍 1.1、前言 在前文中我们已经讲过STL中的适配器概念&#xff0c;即在底层将一个类的接口转…

centos7卸载自带jdk(openjdk)

前提&#xff1a;root模式 1、查看自带jdk 首先确定我们有自带的jdk&#xff0c;然后搜索jdk java -version rpm -qa | grep jdk 2、使用如下命令卸载openjdk rpm -e --nodeps [name] 复制带有openjdk的那两行&#xff0c;有的人可能有多行。一条条执行。 最后java -ver…

win10/11环境解决fastboot模式看不到设备

问题描述&#xff1a; C:\Users\good>adb devices * daemon not running. starting it now on port 5037 * * daemon started successfully * List of devices attached ? device C:\Users\good>fastboot devices fastboot devices 不是内部或外部命令&#xff0…

茶油生产加工MES质量溯源平台源码(spring boot+mybatis+easyui+mysql+h5)

一、生产加工MES&#xff08;Manufacturing Execution System&#xff0c;简称MES&#xff09;是一种面向车间的生产过程管理与实时信息系统。它主要负责监控生产过程&#xff0c;管理生产资源&#xff0c;优化生产流程&#xff0c;提高生产效率和质量。MES系统需要与ERP系统、…

【阻塞队列】阻塞队列DelayedWorkQueue源码详解

目录 一、前言 二、ScheduledThreadPoolExecutor线程池 三、DelayedWorkQueue延迟阻塞队列 四、工作原理 五、源码分析 5.1 定义 5.2 成员属性 5.3 构造函数 5.4 入队方法 5.4.1 offer添加元素 5.4.2 扩容grow() 5.4.3 向上堆化siftUp 5.5 出队方法 5.5.1 take()…

LangChain 基于 ChatGPT 构建本地知识库问答应用

一、使用本地知识库构建问答应用 上篇文章基于 LangChain 的Prompts 提示管理构建特定领域模型&#xff0c;如果看过应该可以感觉出来 ChatGPT 还是非常强大的&#xff0c;但是对于一些特有领域的内容让 GPT 回答的话还是有些吃力的&#xff0c;比如让 ChatGPT 介绍下什么是 L…

二重积分的解题技巧

计算方法 本节内容一般都应该先画图再思考后续内容较为直观 基本口诀是&#xff1a;后积先定限&#xff0c;限内画条线&#xff0c;先交写下限&#xff0c;后交写上限&#xff08;且下限必须小于上限&#xff09; 结合下图进行解释&#xff0c;后积先定限&#xff0c;对于X-型来…

Java基础-多线程JUC-多线程实现的三种形式

1. 第一种 继承Thread&#xff0c;重写run方法 public class demo1 {public static void main(String[] args) {/*** 多线程的第一种启动方式* 1. 定义一个类继承Thread* 2. 重写run方法* 3. 创建子类的对象&#xff0c;并启动线程*/MyThread myThread new MyThread();MyThrea…

受检异常和非受检异常

所谓的受检异常&#xff0c;表示在编译的时候强制检查的异常&#xff0c;这种异常需要显示的通过 try/catch 来捕捉&#xff0c;或者通过 throws 抛出去&#xff0c;否则从程序无法通过编译。 而非受检异常&#xff0c;表示在编译器可以不需要强制检查的异常&#xff0c;这种异…

Java基础---如何理解Java中的多态

目录 所谓多态 方法的重载与重写 重载和重写的区别 所谓多态 多态的概念比较简单&#xff0c;就是同一操作作用于不同的对象&#xff0c;可以有不同的解释&#xff0c;产生不同的执行结果如果按照这个概念来定义的话&#xff0c;那么多态应该是一种运行期的状态为了实现运行…

VScode 配置Orbslam debug调试环境(ubuntu18.04)

如果没有安装VScode的话&#xff0c;可以去点击官网下载 如果已经安装了VScode&#xff0c;可以直接把ORBSLAM的工程文件夹拖到VScode中&#xff0c;系统会提示是否添加C/C编译工具&#xff0c;直接安装即可&#xff0c;安装过程中也可以安装一下cmake 将ORBSLAM的工程文件夹拖…

obs编译

源码地址&#xff1a; GitHub - obsproject/obs-studio: OBS Studio - Free and open source software for live streaming and screen recording windows 编译&#xff1a; Build Instructions For Windows obsproject/obs-studio Wiki GitHub https://www.cnblogs.co…

app自动化测试(Android)--App 控件定位

客户端的页面通过 XML 来实现 UI 的布局&#xff0c;页面的 UI 布局作为一个树形结构&#xff0c;而树叶被定义为节点。这里的节点也就对应了要定位的元素&#xff0c;节点的上级节点&#xff0c;定义了元素的布局结构。在 XML 布局中可以使用 XPath 进行节点的定位。 App的布…

pytorch 迁移训练自己的数据集

1、pytorch 基础训练 上一节为基础 视频与AI&#xff0c;与进程交互(二) pytorch 极简训练自己的数据集并识别 接着上面一节&#xff0c;我们开始使用迁移学习&#xff0c;训练自己的数据集和保存网络&#xff0c;加载网络并识别。 2、 pytorch加载resnet18 RetNet网络的基础…

Vscode platformio Arduino开发STM32,点灯+串口调试

1.工具 USB-TTL(非常便宜&#xff0c;几块钱)STM32F103C8T6(几块钱) 2.引脚连线 USB-TTLSTM32TXPA10RXPA9VCC3.3VGNDGND 注意事项&#xff1a; 跳线帽位置&#xff1a;BOOT0接高电平(1)&#xff0c;BOOT1接低电平(0)每次上传程序前需要按一下复位键(之后&#xff0c;跳线帽…

互联网编程之基于 TCP 的单线程文件收发程序(CS架构)

目录 需求 服务端实现 客户端实现 测试 需求 可试着根据java编程课所学到的java socket编程技术&#xff0c;尝试编写一个基于 TCP 的单线程文件收发程序&#xff0c;需满足&#xff1a; 服务端程序预先定义好需要发送的文件并等待客户端的连接。 客户端连接成功后&…

ranger配置hive出錯:Unable to connect repository with given config for hive

ranger配置hive出錯&#xff1a;Unable to connect repository with given config for hive 我一開始我以為是我重啟了ranger-admin導致ranger有點問題&#xff0c;後面排查之後發現是我之前把hiveserver2關閉了&#xff0c;所以只需要重新開啟hiveserver2即可