- Pow(x, n),数值的整数次方 快速幂">Pow(x, n),数值的整数次方 快速幂
- 递归乘法">递归乘法
- 基本计算器">基本计算器
- 基本计算器 II">基本计算器 II
- 两整数之和">两整数之和
- 水壶问题">水壶问题
- 多数元素*(摩尔投票法)">多数元素*(摩尔投票法)
- 快乐数">快乐数
- 只出现一次的数字">只出现一次的数字
- 数组中数字出现的次数*">数组中数字出现的次数*
- 除自身以外数组的乘积,构建乘积数组">除自身以外数组的乘积,构建乘积数组
- 把数字翻译成字符串">把数字翻译成字符串
- 最小数">最小数
- 最大数">最大数
- 扑克牌中的顺子">扑克牌中的顺子
- 丑数">丑数
- 丑数 II">丑数 II
- 用两个栈实现队列">用两个栈实现队列
- 比较版本号">比较版本号
Pow(x, n),数值的整数次方 快速幂
实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。
输入:x = 2.00000, n = 10
输出:1024.00000
输入:x = 2.10000, n = 3
输出:9.26100
输入:x = 2.00000, n = -2
输出:0.25000
解释:2-2 = 1/22 = 1/4 = 0.25
class Solution(object):
def myPow(self, x, n):
if x == 0.0:
return 0.0
# 当n < 0 时:把问题转化至n≥0 的范围内,即执行x = 1/x,n = - n
if n < 0:
x = 1 / x
n = -n
res = 1
while n:
if n & 1:
res = res * x
x = x * x
n = n >> 1
# n = n // 2
return res
- 当x = 0.0时:直接返回0.0,以避免后续1除以0操作报错。分析:数字0的正数次幂恒为0;0的0次幂和负数次幂没有意义,因此直接返回0.0即可
- 初始化res = 1
- 当n < 0 时:把问题转化至n≥0 的范围内,即执行x = 1/x,n = - n
- 循环计算:当 x=0 时跳出
- 当n & 1 = 1时:将当前x乘入res(即 res = res * x )
- 执行x = x * x
- 执行n右移一位(即 n >>= 1)
-
递归乘法
递归乘法。 写一个递归函数,不使用 * 运算符, 实现两个正整数的相乘。可以使用加号、减号、位移,但要吝啬一些。
输入:A = 1, B = 10
输出:10
输入:A = 3, B = 4
输出:12class Solution(object):
def multiply(self, A, B):
# 将其中的B拆成2进制,那么每一位对应的就是2的幂,那么可以由A+=A得到
res = 0
while B:
# 当前位为奇数时,加一次 A
# 当前位为 偶数时,加两次 A
if B & 1:
res += A
# B 不断地向右移动一位计算,直至B为0
B = B >> 1
if B:
A += A
return res
基本计算器
给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。
输入:s = “1 + 1”
输出:2
输入:s = “ 2-1 + 2 “
输出:3
输入:s = “(1+(4+5+2)-3)+(6+8)”
输出:23class Solution(object):
def calculate(self, s):
# 用栈保存遇到左括号时前面计算好了的运算符
stack = [1]
# sign表示当前运算符
sign = 1
# res表示左边表达式除去栈内保存元素的计算结果
res = 0
i = 0
while i < len(s):
if s[i] == ' ':
i += 1
# 如果是+用sign记录下来
elif s[i] == '+':
sign = stack[-1]
i += 1
# 如果是-用sign记录下来
elif s[i] == '-':
sign = -stack[-1]
i += 1
# 如果是(,将当前sign记录到栈
elif s[i] == '(':
stack.append(sign)
i += 1
# 如果是),将sign剔除
elif s[i] == ')':
stack.pop()
i += 1
else:
# 为了解决可能出现连续的数字
num = 0
# 下标没越界且s[i]是数字
while i < len(s) and s[i].isdigit():
num = num * 10 + int(s[i])
i += 1
# num加上sign运算符更新到res中
res += num * sign
return res
基本计算器 II
注意:这个题一定要切到Python3提交,2过不了
给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。
整数除法仅保留整数部分。
输入:s = “3+2*2”
输出:7
输入:s = “ 3/2 “
输出:1
输入:s = “ 3+5 / 2 “
输出:5class Solution:
def calculate(self, s: str) -> int:
stack = []
pre_ops = '+'
num = 0
i = 0
while i < len(s):
if s[i].isdigit():
num = 10 * num + int(s[i])
if i == len(s) - 1 or s[i] in '+-*/':
if pre_ops == '+':
stack.append(num)
elif pre_ops == '-':
stack.append(-num)
elif pre_ops == '*':
stack.append(stack.pop() * num)
elif pre_ops == '/':
stack.append(int(stack.pop() / num))
pre_ops = s[i]
num = 0
i += 1
return sum(stack)
两整数之和
不使用运算符 + 和 - ,计算两整数 a 、b 之和。
输入: a = 1, b = 2
输出: 3
输入: a = -2, b = 3
输出: 1class Solution:
# 根本就不会
def getSum(self, a: int, b: int) -> int:
a &= 0xFFFFFFFF
b &= 0xFFFFFFFF
while b:
carry = a & b
a ^= b
b = ((carry) << 1) & 0xFFFFFFFF
# print((a, b))
return a if a < 0x80000000 else ~(a^0xFFFFFFFF)
水壶问题
有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水?
如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。
你允许:
装满任意一个水壶
清空任意一个水壶
从一个水壶向另外一个水壶倒水,直到装满或者倒空
输入: x = 3, y = 5, z = 4
输出: True
输入: x = 2, y = 6, z = 5
输出: Falseclass Solution:
def canMeasureWater(self, jug1Capacity, jug2Capacity, targetCapacity):
# 方法一:贝祖定理
x = jug1Capacity
y = jug2Capacity
z = targetCapacity
if z == 0:
return True
if x == 0:
if z == y:
return True
else:
return False
if y == 0:
if z == x:
return True
else:
return False
if z > x + y:
return False
# 而贝祖定理告诉我们,ax+by=z有解当且仅当z是x, y的最大公约数的倍数。因此我们只需要找到x,y的最大公约数并判断z是否是它的倍数即可。
if x > y:
x, y = y, x
if y % x == 0:
if z % x == 0:
return True
else:
return False
else:
if y % (y % x) == 0:
if z % (y % x) == 0:
return True
else:
return False
else:
return True
# 方法二:调包侠
x = jug1Capacity
y = jug2Capacity
z = targetCapacity
if x + y < z:
return False
if x == 0 or y == 0:
return z == 0 or x + y == z
return z % math.gcd(x, y) == 0
多数元素*(摩尔投票法)
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
输入:[3,2,3]
输出:3
输入:[2,2,1,1,1,2,2]
输出:2class Solution(object):
def majorityElement(self, nums):
count = 0
major = 0
for i in nums:
if count == 0:
major = i
if i == major:
count += 1
else:
count -= 1
return major
快乐数
编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」定义为:
对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果 可以变为 1,那么这个数就是快乐数。
如果 n 是快乐数就返回 true ;不是,则返回 false 。
输入:19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
输入:n = 2
输出:falseclass Solution(object):
def isHappy(self, n):
dicts = {}
while True:
n = sum(int(i) ** 2 for i in str(n))
if n == 1:
return True
if n in dicts:
return False
dicts[n] = 1
只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
输入: [2,2,1]
输出: 1
输入: [4,1,2,1,2]
输出: 4class Solution(object):
def singleNumber(self, nums):
# 异或,当同位相同时结果为0,不同结果为1
res = 0
for i in nums:
res ^= i
return res
数组中数字出现的次数*
一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]
输入:nums = [1,2,10,4,1,4,3,3]
输出:[2,10] 或 [10,2]class Solution(object):
def singleNumbers(self, nums):
res = 0 # 所有数字异或的结果
a = 0
b = 0
for i in nums:
res ^= i
# 找到第一位不是0的
h = 1
while(res & h == 0):
h <<= 1
for n in nums:
# 根据该位是否为0将其分为两组
if (h & n == 0):
a ^= n
else:
b ^= n
return [a, b]
除自身以外数组的乘积,构建乘积数组
给你一个长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。
输入: [1,2,3,4]
输出: [24,12,8,6]class Solution(object):
def productExceptSelf(self, nums):
# 根据表格的主对角线,可将表格分为 上三角 和 下三角 两部分。分别迭代计算下三角和上三角两部分的乘积
res = [1] * len(nums)
for i in range(1, len(nums)):
res[i] = res[i-1] * nums[i-1] # 下三角
tmp = 1
for j in range(len(nums) - 2, -1, -1):
tmp *= nums[j+1] # 上三角
res[j] *= tmp # 下三角 * 上三角
return res
把数字翻译成字符串
给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。
输入: 12258
输出: 5
解释: 12258有5种不同的翻译,分别是”bccfi”, “bwfi”, “bczi”, “mcfi”和”mzi”class Solution(object):
def translateNum(self, num):
# 方法一:从左向右遍历
s = str(num)
a = b = 1
for i in range(2, len(s) + 1):
# 如果当前值和前一个数字能组成10到25的数
if "10" <= s[i-2:i] <= "25":
c = a + b
else:
c = a
b = a
a = c
return a
最小数
输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
输入: [10,2]
输出: “102”
输入: [3,30,34,5,9]
输出: “3033459”class Solution(object):
def minNumber(self, nums):
if len(nums)==0:
return ""
# 将元素都转换成字符串
for i in range(len(nums)):
nums[i] = str(nums[i])
# 冒泡排序。。
for i in range(len(nums)):
for j in range(i+1, len(nums)):
if nums[i] + nums[j] > nums[j] + nums[i]:
nums[i], nums[j] = nums[j], nums[i]
return "".join(nums)
最大数
给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。
注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数。
输入:nums = [10,2]
输出:”210”
输入:nums = [3,30,34,5,9]
输出:”9534330”class Solution(object):
def largestNumber(self, nums):
# 方法一:堆排序
s = []
for i in nums:
tmp = (str(i)*10)[:10]
heapq.heappush(s, [-int(tmp), str(i)])
ans = ""
while s:
ans += heapq.heappop(s)[1]
return str(int(ans))
# 方法二:冒泡排序
for i in range(len(nums)):
for j in range(len(nums) - i - 1):
if str(nums[j]) + str(nums[j + 1]) > str(nums[j + 1]) + str(nums[j]):
nums[j], nums[j + 1] = nums[j + 1], nums[j]
s = ''
if nums[-1] == 0:
return('0')
for i in nums:
s = str(i) + s
return s
扑克牌中的顺子
从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。
输入: [1,2,3,4,5]
输出: True
输入: [0,0,1,2,5]
输出: Trueclass Solution(object):
# 排序后首先排除0,然后累加相邻元素差,这是为了在相邻元素差为0(即相邻元素相等)时,直接返回False,如果累加差值<5,则为顺子。
nums.sort()
count = 0
for i in range(4):
if nums[i] == 0:
continue
if nums[i+1] == nums[i]:
return False
count += nums[i+1] - nums[i]
if count < 5:
return True
return False
丑数
给你一个整数 n ,请你判断 n 是否为 丑数 。如果是,返回 true ;否则,返回 false 。
丑数 就是只包含质因数 2、3 和/或 5 的正整数。
输入:n = 6
输出:true
解释:6 = 2 × 3
输入:n = 8
输出:true
解释:8 = 2 × 2 × 2class Solution(object):
def isUgly(self, n):
if n <= 0:
return False
factors = [2, 3, 5]
for factor in factors:
while n % factor == 0:
n //= factor
return n == 1
丑数 II
给你一个整数 n ,请你找出并返回第 n 个 丑数 。
丑数 就是只包含质因数 2、3 和/或 5 的正整数。
输入:n = 10
输出:12
解释:[1, 2, 3, 4, 5, 6, 8, 9, 10, 12] 是由前 10 个丑数组成的序列。
输入:n = 1
输出:1
解释:1 通常被视为丑数。class Solution(object):
def nthUglyNumber(self, n):
if n < 0:
return 0
dp = [1] * n
index2, index3, index5 = 0, 0, 0
for i in range(1, n):
dp[i] = min(2 * dp[index2], 3 * dp[index3], 5 * dp[index5])
if dp[i] == 2 * dp[index2]:
index2 += 1
if dp[i] == 3 * dp[index3]:
index3 += 1
if dp[i] == 5 * dp[index5]:
index5 += 1
return dp[n - 1]
用两个栈实现队列
class CQueue:
def __init__(self):
self.A, self.B = [], []
def appendTail(self, value):
self.A.append(value)
def deleteHead(self):
if self.B: return self.B.pop()
if not self.A: return -1
while self.A:
self.B.append(self.A.pop())
return self.B.pop()
比较版本号
给你两个版本号 version1 和 version2 ,请你比较它们。
输入:version1 = “1.01”, version2 = “1.001”输出:0
解释:忽略前导零,”01” 和 “001” 都表示相同的整数 “1”
输入:version1 = “1.0”, version2 = “1.0.0”
输出:0
解释:version1 没有指定下标为 2 的修订号,即视为 “0”
输入:version1 = “0.1”, version2 = “1.1”
输出:-1
解释:version1 中下标为 0 的修订号是 “0”,version2 中下标为 0 的修订号是 “1” 。0 < 1,所以 version1 < version2
输入:version1 = “1.0.1”, version2 = “1”
输出:1 ```python class Solution: def compareVersion(self, version1, version2):# 方法一:补齐元素再比大小
nums1 = version1.split('.')
nums2 = version2.split('.')
# 补齐长度
if len(nums1) > len(nums2):
nums2 = nums2 + ['0'] * (len(nums1)-len(nums2))
if len(nums2) > len(nums1):
nums1 = nums1 + ['0'] * (len(nums2) - len(nums1))
# 分别比较两个版本号每一位的大小
for i in range(len(nums1)):
if int(nums1[i]) > int(nums2[i]):
return 1
elif int(nums1[i]) < int(nums2[i]):
return -1
else:
continue
return 0
class Solution: def compareVersion(self, version1, version2):
# 方法二:与方法一类似,只是不补齐,两个复杂度一样都不是最优解
nums1 = version1.split('.')
nums2 = version2.split('.')
for i in range(max(len(nums1), len(nums2))):
# 分别比较两个版本号每一位的大小
if i < len(nums1):
i1 = int(nums1[i])
else:
i1 = 0
if i < len(nums2):
i2 = int(nums2[i])
else:
i2 = 0
if i1 > i2:
return 1
elif i1 < i2:
return -1
else:
continue
return 0
<a name="lds2J"></a>
## 小数循环节
```python
def xun_huan_jie(a, b):
# 不再判断余数是否为0,而是把所有的小数都看为循环小数,0.5可以看为:0.5[0],这样就统一处理了
zheng = str(a // b) ## 商的整数部分
shang = "" ## 商的小数部分
yu = [a % b]
while True:
# 求商
x = (yu[-1] * 10) // b
# 求余
y = (yu[-1] * 10) % b
shang += str(x)
yu.append(y)
i = yu.index(yu[-1])
if i != len(yu) - 1:
shang = shang[:i] + "[" + shang[i:] + "]"
break
r = zheng + "." + shang
# 如果以[0]结尾,就删去
if r.endswith("[0]"):
r = r[:-3]
# 如果没有小数部分,小数点也删去
if r.endswith("."):
r = r[:-1]
return r
if __name__ == '__main__':
print(xun_huan_jie(100, 5))
print(xun_huan_jie(1, 8))
print(xun_huan_jie(1, 7))
print(xun_huan_jie(12345, 1700))
20
0.125
0.[142857]
7.26[1764705882352941]