【Leetcode】数与位

题目汇总

能完成:7/168/172/191/263/326/405/461/492/507/693

要优化:231/258/400

不会做:50/372

基础操作总结

转二进制:bin(n).replace('0b','') #因为bin生成的二进制字符串会带有'0b'的前缀

基础数学知识

乘法在取模的意义下满足分配律 即: (a*b) % m = (a%m * b%m) % m

完全数:所有的真因子(即除了自身以外的约数)之和恰好等于它本身 32位内只有5位完全数{6, 28, 496, 8128, 33550336}

数根 :将一正整数的各个位数相加(即横向相加),若加完后的值大于10的话,则继续将各位数进行横向相加直到其值为个位数为止; 数根=对9取余的结果

优化思路
231

给你一个整数 n,请你判断该整数是否是 2 的幂次方。如果是,返回 true ;否则,返回 false

进阶:不使用循环/递归

思路一:转二进制后判断是否有且仅有一个1 return n > 0 and bin(n).count('1') == 1

trick :**binary&(binary-1)**return n > 0 and (n & (n-1)) == 0

若只有1个1,则(binary-1)会出现退位,该位置的1消失,进行按位与操作只能得到0

若有2个及以上的1,则(binary-1)会出现退位,但高位的1仍保持不变,进行按位与操作不能得到0

258

给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数。返回这个结果。

进阶:不使用循环或者递归,时间复杂度 O(1)

数学推导:1.写出某个整数的求和表示;

2.用添1的方法凑出各个位上的数字和;

3.观察发现10^i-1都是9的倍数,故该整数对9的取余结果即为所需返回值;

特殊情况:取余结果为0:1.该数为0,返回0;2.该数不为0,返回9;

python 复制代码
class Solution(object):
    def addDigits(self, num):
        """
        :type num: int
        :rtype: int
        """
        return ((num-1)%9)+1 if num else 0

        #除开0后还需要输出的范围[1,9],而对9取余结果范围[0,8],故需要+1
400

给你一个整数 n ,请你在无限的整数序列 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...] 中找出并返回第 n位上的数字

分析:1-9:9 // 10-99:90x2 // 100-999:900x3 // 1000-9999:9000x4

|----|-----|-------|---------|-----------|-----|--------------------------|
| 数字 | 1-9 | 10-99 | 100-999 | 1000-9999 | ... | ------ |
| 长度 | 9 | 90x2 | 900x3 | 9000x4 | ... | 900000000x9(>2**31-1) |

假设 n = 11:

1.根据长度可以判断是在几位数的范围里; 9<11<9+90x2 两位数

2.减去前一区间的长度总和再与当前位数相除就可以得到当前区间的相对位置; (11-9)//2=1

3.与前一区间的终点值相加得到其绝对数值; 9+1=10

4.根据余数判断在数值的哪一位; (11-9)%2=0 '0'

余数为0对应绝对数值的最后一位;余数为i则对应下一数值的第i位;

假设数值为123456:

取第一位:123456//100000=1

取第二位:123456//10000=12%10=2

...取第n位:123456//10**(len-n)%10

python 复制代码
class Solution(object):
    def largestPalindrome(self, n):
        """
        :type n: int
        :rtype: int
        """
        a, b = 1, 9
        while n > a*b:
            n = n - a*b
            a, b = a+1, b*10
        m = n//a + 10**(a-1) -1            #a为位数        
        return (m+1)//10**(a-n%a)%10 if n%a else m%10
解题思路
50

实现 pow(x,n) ,即计算 x 的整数 n 次幂函数(即,x^n

思路:n^1=n;n^2=n^1 * n;n^3=n^2 * n... 因此只需要一次循环实现连乘即可;

处理指数为负:去掉负号进循环,返回时若是负数则返回1.0/out

优化点:若求n^2m = n^m * n^m,若求n^(2m+1) = n^m * n^m * n

python 复制代码
class Solution(object):
    def myPow(self, x, n):
        """
        :type x: float
        :type n: int
        :rtype: float
        """

        return 1.0/self.poww(x,-n) if n < 0 else self.poww(x,n)   #处理符号
        
    def poww(self, x, n):                                         #处理正幂
        if n == 0: return 1.0
        else:
            m = self.poww(x, n//2)
            return m*m*x if n%2 else m*m
372

你的任务是计算 a^b1337 取模,a 是一个正整数,b 是一个非常大的正整数且会以数组形式给出。

分析:处理以数组形式给出的b = [m, n] ,令 f(a,x) = a^x % k

f(a, mn) = [ a^(m*10)*a^n ] % k = [ f(a,m*10) * f(a,n) ] % k,而f(a,m*10) = (a^m)^10 % k = f(a^m, 10)

通过观察发现需要需要编写一个计算f(i,j)的函数poww(i,j),其中j-[0,10],

当j=0时,结果为1;

当j=1时,结果为a^k;

当j-[2,10]时,结果为 f(j) = [ f(j-1) * f(1) ] % k 需要循环j-1次

python 复制代码
class Solution(object):
    def superPow(self, a, b):
        """
        :type a: int
        :type b: List[int]
        :rtype: int
        """
        if a == 1: return 1                                  #直接结束
    
        if len(b)==1: return self.poww(a,b[-1])              #不需要拆分b
        else:
            out1 = self.superPow(a,b[-1:])                   #fn
            out2 = self.poww(self.superPow(a,b[:-1]),10)     #fm*10
            return (out1 * out2) % 1337

    def poww(self, a, b):     #计算a^b % k
        if b==0: return 1
        elif b==1:return a % 1337
        else: 
            out = f1 = a % 1337
            for _ in range(b-1): out = (out * f1) % 1337   #b-1次循环
            return out

#测试用时较长,内存占用较多

优化点:在求幂时用快速幂 50

相关推荐
阿Y加油吧4 分钟前
两道中等 DP 题拆解:打家劫舍 & 完全平方数
算法·leetcode·动态规划
七颗糖很甜6 分钟前
python实现全国雷达拼图数据的SCIT风暴识别
python·算法·scipy
参.商.1 小时前
【Day49】236.二叉树的最近公共祖先
leetcode·golang
B325帅猫-量子前沿技术研究所1 小时前
PSD和FFT的关系
人工智能·算法
闻缺陷则喜何志丹1 小时前
【排序】P6149 [USACO20FEB] Triangles S|普及+
c++·算法·排序·洛谷
avocado_green1 小时前
【LeetCode】90. 子集 II
算法·leetcode
tankeven2 小时前
HJ178 【模板】双指针
c++·算法
君义_noip2 小时前
信息学奥赛一本通 4131:【GESP2506六级】学习小组 | 洛谷 P13015 [GESP202506 六级] 学习小组
算法·动态规划·gesp·信息学奥赛
6Hzlia2 小时前
【Hot 100 刷题计划】 LeetCode 300. 最长递增子序列 | C++ 动态规划 & 贪心二分
c++·leetcode·动态规划
6Hzlia2 小时前
【Hot 100 刷题计划】 LeetCode 72. 编辑距离 | C++ 经典 DP 增删改状态转移
c++·算法·leetcode