题目汇总
能完成: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;
pythonclass 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
pythonclass 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
pythonclass 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^b
对 1337
取模,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次
pythonclass 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