【LeetCode笔记】剑指Offer 43. 1~n 整数中1出现的次数(Java、数位dp、偏数学)

打卡第九天啦~

题目描述

思路 && 代码

  • 主体思路:从低到高,计算出每一位出现的1的个数。
  • 三种情况:n的当前位为0、为1、为其他值。
  • 这里和数位dp的思想相关(但是博主没怎么看= =,有兴趣可以去了解了解)
  • 仔细想想确实是dp的理,初始化、状态转移方程与最优子结构都很明显。
class Solution {
    // 思路:逐位计算,计算每一位的1的次数
    public int countDigitOne(int n) {
        // 位数、结果
        int digit = 1, res = 0;
        // 高位、当前位、低位(高、低位都不一定只有一位)
        int high = n / 10, cur = n % 10, low = 0;
        while(high != 0 || cur != 0) {
            // Case 1: 当前位为0,只需根据高位判断
            if(cur == 0) {
                res += high * digit;
            }
            // Case 2: 当前位为1,多加一个对应的低位个数(low + 1)
            else if(cur == 1) {
                res += high * digit + low + 1;
            }
            // Case 3: 当前位为2 ~ 9,直接根据高位判断即可,相对 cur = 0,多让high + 1
            else {
                res += (high + 1) * digit;
            }

            // 维护 low cur high digit
            low += cur * digit;
            cur = high % 10;
            high /= 10;
            digit *= 10;
        }
        return res;
    }
}

二刷

  • 核心思路
    1. 数字分三部分:高、当前、低
    2. 每位计算:三种公式,根据当前位的值判断
class Solution {
    public int countDigitOne(int n) {
        int digit = 1, res = 0;
        int high = n / 10, cur = n % 10, low = 0;
        while(high != 0 || cur != 0) {
            if(cur == 0) {
                res += high * digit;
            }
            else if(cur == 1) {
                res += high * digit + low + 1;
            }
            else {
                res += (high + 1) * digit;
            }

            low += cur * digit;
            digit *= 10;
            cur = high % 10;
            high /= 10;
        }
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
给定一个整数数组 nums 和一个目标值 target,要求在数组找出两个数的和等于目标值,并返回这两个数的索引。 思路1:暴力法 最简单的思路是使用两层循环遍历数组的所有组合,判断两个数的和是否等于目标值。如果等于目标值,则返回这两个数的索引。 此方法的时间复杂度为O(n^2),空间复杂度为O(1)。 思路2:哈希表 为了优化时间复杂度,可以使用哈希表来存储数组的元素和对应的索引。遍历数组,对于每个元素nums[i],我们可以通过计算target - nums[i]的值,查找哈希表是否存在这个差值。 如果存在,则说明找到了两个数的和等于目标值,返回它们的索引。如果不存在,将当前元素nums[i]和它的索引存入哈希表。 此方法的时间复杂度为O(n),空间复杂度为O(n)。 思路3:双针 如果数组已经排序,可以使用双针的方法来求解。假设数组从小到大排序,定义左针left向数组的第一个元素,右针right向数组的最后一个元素。 如果当前两个向的数的和等于目标值,则返回它们的索引。如果和小于目标值,则将左针右移一位,使得和增大;如果和大于目标值,则将右针左移一位,使得和减小。 继续移动针,直到找到两个数的和等于目标值或者左针超过了右针。 此方法的时间复杂度为O(nlogn),空间复杂度为O(1)。 以上三种方法都可以解决问题,选择合适的方法取决于具体的应用场景和要求。如果数组规模较小并且不需要考虑额外的空间使用,则暴力法是最简单的方法。如果数组较大或者需要优化时间复杂度,则哈希表或双针方法更合适。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值