笔试刷题必备------ 数学问题
笔试刷题必备------ 数学问题
Fizz Buzz
写一个程序,输出从 1 到 n 数字的字符串表示。
1. 如果 n 是3的倍数,输出“Fizz”;
2. 如果 n 是5的倍数,输出“Buzz”;
3.如果 n 同时是3和5的倍数,输出 “FizzBuzz”。
示例:
n = 15,
返回:
[
“1”,
“2”,
“Fizz”,
“4”,
“Buzz”,
“Fizz”,
“7”,
“8”,
“Fizz”,
“Buzz”,
“11”,
“Fizz”,
“13”,
“14”,
“FizzBuzz”
]
class Solution(object):
def fizz_buzz(self,n):
res = []
for i in range(1,n+1):
if i % 3 == 0 and i % 5 == 0:
res.append("FizzBuzz")
elif i % 3 == 0:
res.append("Fizz")
elif i % 5 == 0:
res.append("Buzz")
else:
res.append(str(i))
return res
if __name__ == "__main__":
solu = Solution()
print(solu.fizz_buzz(15))
计数质数
暴力算法(会超时)
import math
class Solution(object):
def count_primes(self,n):
res = 0
for i in range(n+1):
if self.is_prime(i):
res += 1
return res
def is_prime(self,num):
if num <= 3:
return num < 1
sqrt = int(math.sqrt(num))
for i in range(2,sqrt+1):
if num % i == 0:
return False
return True
if __name__ == "__main__":
solu = Solution()
print(solu.count_primes(15))
3的幂
给定一个整数,写一个函数来判断它是否是 3 的幂次方。
示例 1:
输入: 27
输出: true
示例 2:
输入: 0
输出: false
示例 3:
输入: 9
输出: true
示例 4:
输入: 45
输出: false
进阶:
你能不使用循环或者递归来完成本题吗?
循环:
class Solution(object):
def isPowerOfThree(self,n):
while n > 0:
if n % 3 == 0:
n /=3
else:
break
return True if n == 1 else False
不使用循环或者递归
#不使用循环或者递归
class Solution2():
def isPowerOfThree(self,n):
# 3^19=1162261467是小于2^31最大的3的倍数
return n > 0 and 3**19 % n == 0
罗马数字转整数
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。
示例 1:
输入: "III"
输出: 3
示例 2:
输入: "IV"
输出: 4
示例 3:
输入: "IX"
输出: 9
示例 4:
输入: "LVIII"
输出: 58
解释: L = 50, V= 5, III = 3.
示例 5:
输入: "MCMXCIV"
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.
class Solution(object):
def roman_to_int(self,s):
d = {'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000}
res = 0
i = 0
while i < len(s)-1:
if d[s[i]] >= d[s[i+1]]:
res += d[s[i]]
i += 1
else:
temp = d[s[i+1]] - d[s[i]]
res += temp
i += 2
if i == len(s)-1:
res += d[s[i]]
return res if 1 <= res <= 3999 else False
直线上最多的点数
给定一个二维平面,平面上有 n 个点,求最多有多少个点在同一条直线上。
示例 1:
输入: [[1,1],[2,2],[3,3]]
输出: 3
解释:
^
|
| o
| o
| o
+------------->
0 1 2 3 4
示例 2:
输入: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
输出: 4
解释:
^
|
| o
| o o
| o
| o o
+------------------->
0 1 2 3 4 5 6
穷举,算出每个点和其他各个点的斜率(若两个点和同一个点的斜率相同,那么这三个点在同一条直线上),计算不同斜率点的个数(别忘了把当前点加上),还要注意和当前点重合的,以及斜率为无穷的。
在这里插入代码片
缺失数字
给定一个包含 0, 1, 2, …, n 中 n 个数的序列,找出 0 … n 中没有出现在序列中的那个数。
示例 1:
输入: [3,0,1]
输出: 2
示例 2:
输入: [9,6,4,2,3,5,7,0,1]
输出: 8
说明:
你的算法应具有线性时间复杂度。你能否仅使用额外常数空间来实现?
方法一:利用枚举(Python特性)
class Solution(object):
def missingNumber(self,nums):
nums = sorted(nums)
for i,j in enumerate(nums):
if i != j:
return i
方法二:利用等差数列求和
class Solution2(object):
def missingNumber(self,nums):
return ((1+len(nums))*len(nums)//2)-sum(nums)
方法三:^位运算
class Solution(object):
def missingNumber(self,nums):
"""
:type nums: List[int]
:rtype: int
"""
bit = 0
for i,j in enumerate(nums):
bit ^= i ^ j
return bit^len(nums)
分数到小数
给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以字符串形式返回小数。
如果小数部分为循环小数,则将循环的部分括在括号内。
示例 1:
输入: numerator = 1, denominator = 2
输出: "0.5"
示例 2:
输入: numerator = 2, denominator = 1
输出: "2"
示例 3:
输入: numerator = 2, denominator = 3
输出: "0.(6)"
class Solution(object):
def fractionToDecimal(self, numerator, denominator):
"""
:type numerator: int
:type denominator: int
:rtype: str
"""
if numerator == 0:
return '0'
elif denominator == 0:
return ''
else:
isNegative = (numerator < 0) ^ (denominator < 0)
numerator = abs(numerator)
denominator = abs(denominator)
res = ''
res += '-' if isNegative else ''
res += str(numerator//denominator)
numerator %= denominator
if numerator == 0:
return res
else:
res +='.'
dic = {}
while numerator:
if numerator in dic:
start = dic[numerator]
end = len(res)
res = res[:start] + '(' + res[start:end] + ')'
return res
dic[numerator] = len(res)
res += str(numerator*10//denominator)
numerator = numerator*10%denominator
return res
if __name__ == "__main__":
solu = Solution()
print(solu.fractionToDecimal(1,3))
位1的个数
编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。
示例 1:
输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。
示例 2:
输入:00000000000000000000000010000000
输出:1
解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 '1'。
示例 3:
输入:11111111111111111111111111111101
输出:31
解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 '1'。
class Solution(object):
def hammingWeight(self, n):
if n == 0:
return 0
sum = 0
while n > 0:
sum += n&1
#依次右移
n = n >> 1
return sum
if __name__ == "__main__":
solu = Solution()
print(solu.hammingWeight(0o0000000000000000000000000001011))
颠倒二进制位
颠倒给定的 32 位无符号整数的二进制位。
示例 1:
输入: 00000010100101000001111010011100
输出: 00111001011110000010100101000000
解释: 输入的二进制串 00000010100101000001111010011100 表示无符号整数 43261596,
因此返回 964176192,其二进制表示形式为 00111001011110000010100101000000。
示例 2:
输入:11111111111111111111111111111101
输出:10111111111111111111111111111111
解释:输入的二进制串 11111111111111111111111111111101 表示无符号整数 4294967293,
因此返回 3221225471 其二进制表示形式为 10101111110010110010011101101001。
提示:
请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。
在 Java 中,编译器使用二进制补码记法来表示有符号整数。因此,在上面的 示例 2 中,输入表示有符号整数 -3,输出表示有符号整数 -1073741825。
进阶:
如果多次调用这个函数,你将如何优化你的算法?
class Solution:
# @param n, an integer
# @return an integer
def reverseBits(self, n):
res = 0
count = 32
while count:
res <<= 1 # 取出 n 的最低位数加到 res 中
res += n&1
n >>= 1
count -= 1
return res
阶乘后的零
给定一个整数 n,返回 n! 结果尾数中零的数量。
示例 1:
输入: 3
输出: 0
解释: 3! = 6, 尾数中没有零。
示例 2:
输入: 5
输出: 1
解释: 5! = 120, 尾数中有 1 个零.
说明: 你算法的时间复杂度应为 O(log n)
class Solution(object):
def trailingZeroes(self,n):
r = 0
while n >= 5:
n = n//5
r += n
return r
快乐数
编写一个算法来判断一个数是不是“快乐数”。
一个“快乐数”定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是无限循环但始终变不到 1。如果可以变为 1,那么这个数就是快乐数。
示例:
输入: 19
输出: true
解释:
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 111
class Solution(object):
def is_happy(self,n):
temp = []
while True:
n = self.get_add(n)
if n == 1:
return True
#出现死循环就退出,并返回False
elif n in temp:
return False
else:
temp.append(n)
def get_add(self,n):
res = 0
while n != 0:
g = n %10
res += g**2
n = n//10
return res
if __name__ == "__main__":
solu = Solution()
print(solu.is_happy(19))
Excel表列序号
给定一个Excel表格中的列名称,返回其相应的列序号。
例如,
A -> 1
B -> 2
C -> 3
...
Z -> 26
AA -> 27
AB -> 28
...
示例 1:
输入: "A"
输出: 1
示例 2:
输入: "AB"
输出: 28
示例 3:
输入: "ZY"
输出: 701
class Solution(object):
def titleToNumber(self,s):
res = 0
for letter in s:
res += res*26 + ord(letter) - ord('A')+1
return res
if __name__ == "__main__":
solu = Solution()
print(solu.titleToNumber("ZY"))
Pow(x, n)
实现 pow(x, n) ,即计算 x 的 n 次幂函数。
示例 1:
输入: 2.00000, 10
输出: 1024.00000
示例 2:
输入: 2.10000, 3
输出: 9.26100
示例 3:
输入: 2.00000, -2
输出: 0.25000
解释: 2-2 = 1/22 = 1/4 = 0.25
说明:
-100.0 < x < 100.0
n 是 32 位有符号整数,其数值范围是 [−231, 231 − 1] 。
class Solution(object):
def myPow(self,x,n):
if not n:
return 1
if n < 0:
return 1/self.myPow(x,-n)
if not n & 1:
return self.myPow(x * x, n >> 1)
else:
return self.myPow(x,n-1)*x
if __name__ == "__main__":
solu =Solution()
print(solu.myPow(2.1,3))
x 的平方根
实现 int sqrt(int x) 函数。
计算并返回 x 的平方根,其中 x 是非负整数。
由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
示例 1:
输入: 4
输出: 2
示例 2:
输入: 8
输出: 2
说明: 8 的平方根是 2.82842…,
由于返回类型是整数,小数部分将被舍去。
class Solution(object):
def mySqrt(self, x):
"""
:type x: int
:rtype: int
"""
if x <= 1:
return x
else:
left = 1
right = x
mid = (left+right)//2
while (right-left) >=2:
if mid*mid == x:
return mid
elif mid*mid < x:
left = mid
mid = (left+right)//2
else:
right = mid
mid = (left+right)//2
return mid
两数相除
给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend 除以除数 divisor 得到的商。
示例 1:
输入: dividend = 10, divisor = 3
输出: 3
示例 2:
输入: dividend = 7, divisor = -3
输出: -2
说明:
被除数和除数均为 32 位有符号整数。
除数不为 0。
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231 − 1]。本题中,如果除法结果溢出,则返回 231 − 1。
class Solution:
def divide(self, dividend, divisor):
result = 0
pointer = 0
if (dividend >= 0 and divisor < 0) or (divisor >= 0 and dividend < 0):
pointer = 0
else:
pointer = 1
dividend = abs(dividend)
divisor = abs(divisor)
while dividend >= divisor:
temp, i = divisor, 1
while dividend >= temp:
dividend -= temp
result += i
i <<= 1
temp <<= 1
if pointer == 0: result = -result
return min(max(result, -2 ** 31), 2 ** 31 - 1)
多数元素
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入: [3,2,3]
输出: 3
示例 2:
输入: [2,2,1,1,1,2,2]
输出: 2
排序法:
class Solution(object):
def majorityElement(self, nums):
nums = sorted(nums)
return nums[len(nums)//2]
投票法:
class Solution(object):
def majorityElement(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
count = 0
candi = 0
for i in nums:
if i == candi:
count += 1
else:
if count ==0:
candi = i
count = 1
else:
count -= 1
return candi
逆波兰表达式求值
根据逆波兰表示法,求表达式的值。
有效的运算符包括 +, -, *, / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
说明:
整数除法只保留整数部分。
给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
示例 1:
输入: ["2", "1", "+", "3", "*"]
输出: 9
解释: ((2 + 1) * 3) = 9
示例 2:
输入: ["4", "13", "5", "/", "+"]
输出: 6
解释: (4 + (13 / 5)) = 6
示例 3:
输入: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"]
输出: 22
解释:
((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22
class Solution:
def evalRPN(self, tokens):
"""
:type tokens: List[str]
:rtype: int
"""
import operator
stack = []
ops = { "+": operator.add, "-": operator.sub, "*": operator.mul, "/": operator.truediv}
for char in tokens:
if char in ops:
t1 = int(stack.pop())
t2 = int(stack.pop())
stack.append(ops[char](t2,t1))
else:
stack.append(char)
return int(stack.pop())
if __name__ == "__main__":
solu = Solution()
tokens = ["4", "13", "5", "/", "+"]
solu =Solution()
print(solu.evalRPN(tokens))