剑指offer-Python3版(十一)

本文深入解析《剑指Offer》中三个经典算法题目:计算整数中1出现的次数,将数组排列成最小数值,及寻找第n个丑数。通过Python3实现,提供高效算法思路。

剑指offer-Python3版(十一)

整数中1出现的次数

Q: 输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。

例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。

思路

一开始只想到了这种,但运行很慢,力扣通不过,pass

class Solution:
    def countDigitOne(self, n: int) -> int:
        """
        输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。
        例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。
        :param n:
        :return:
        """
        one_count = 0
        for i in range(1, n + 1):
            while i > 1:
                j = i % 10
                if j == 1:
                    one_count += 1

                i = int(i / 10)
            if i == 1:
                one_count += 1
        return one_count

网上有这种算法

记n的第i位为ni,记ni " 为当前位,记为cur,左边的称为高位,记为high,右边的记为低位,记为low,10i称为位因子,记为digit

cur = 0 1出现的次数只由高位high决定 = high*dight

cur = 1 1出现的次数由high和low决定 = high*digit+low+1

cur >1 1出现的次数只由high决定 = (high+1)*digit

class Solution:
    def countDigitOne(self, n: int) -> int:
        """
        输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。
        例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。
        :param n:
        :return:
        """
        digit, res = 1, 0
        high, cur, low = n // 10, n % 10, 0
        while high != 0 or cur != 0:
            if cur == 0:
                res += high * digit
            elif cur == 1:
                res += high * digit + low + 1
            else:
                res += (high + 1) * digit
            low += cur * digit
            cur = high % 10
            high //= 10
            digit *= 10
        return res

把数组排成最小的数

Q:输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。

思路

class cmpSmaller(str):
    def __lt__(self, other):
        return self + other < other + self


class Solution:
    def minNumber(self, nums: [int]) -> str:
        res = sorted(map(str, nums), key=cmpSmaller)
        smallest = ''.join(res)
        return smallest

丑数

Q:我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。

class Solution:
    def nthUglyNumber(self, n: int) -> int:
        dp, a, b, c = [1] * n, 0, 0, 0
        for i in range(1, n):
            n2, n3, n5 = dp[a] * 2, dp[b] * 3, dp[c] * 5
            dp[i] = min(n2, n3, n5)
            # 3个if防止重复丑数
            if dp[i] == n2:
                a += 1
            if dp[i] == n3:
                b += 1
            if dp[i] == n5:
                c += 1
        return dp[-1]

n=3 程序流程

dp=[1, 1, 1] a=0,b=0,c=0
i=1
n2=2 n3=3 n5=5
i==1  dp[i]==2
a== 1
i=2
n2=4 n3=3 n5=5
i==2  dp[i]==3
b== 1
dp[n]= 3
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值