classSolution:defreplaceSpace(self, s: str) -> str:
l = len(s)
nums = s.count(' ')
n_l = l + (nums << 1)#%20 替换原位置外,还需要加两倍的替换空间
arr = [''] * n_l
i = 0for char in s:
if char == " ":
arr[i] = '%'
arr[i + 1] = '2'
arr[i + 2] = '0'
i += 3else:
arr[i] = char
i += 1
print(char)
return''.join(arr)
# 测试代码
print(Solution().replaceSpace('hello wor ld !'))
3. 两个数组相对排序
from typing import List
classSolution:# 方法一 sort(key)defrelativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]:
ranks = {x: i for i, x in enumerate(arr2)}
arr1.sort(key=lambda x:(0,ranks[x]) if x in ranks else (1,x))
return arr1
# 方法二 计数排序法defrelativeSortArray2(self,arr1: List[int], arr2: List[int]) -> List[int]:
upper = max(arr1)
frequency = [0] * (upper + 1)
for x in arr1:
frequency[x] += 1
ans = list()
for x in arr2:
ans.extend([x] * frequency[x])
frequency[x] = 0for x in range(upper + 1):
if frequency[x] > 0:
ans.extend([x] * frequency[x])
return ans
# 通过sort()参数指定键排序
arr1,arr2 = [2,3,1,3,2,4,6,7,9,2,20,19,5,1],[2,4,3,6]
print(Solution().relativeSortArray(arr1,arr2))
4. Z字变换
# 将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列# 输入:s = "PAYPALISHIRING", numRows = 3# 输出:"PAHNAPLSIIGYIR"# 输入:s = "PAYPALISHIRING", numRows = 4# 输出:"PINALSIGYAHRPI"# 以 V 字型为一个循环, 循环周期为 n = (2 * numRows - 2)# 索引值i:计算 x = i % n , 行号y = min(x, n - x)classSolution:defconvert(self, s: str, numRows: int) -> str:if numRows == 1: return s
rows = [""] * numRows
n = 2 * numRows - 2for i, char in enumerate(s):
x = i % n
rows[min(x, n - x)] += char
return"".join(rows)
# 测试代码
print(Solution().convert('PAYPALISHIRING',4))
5. 移除K位数后的最小数字
classSolution:defremoveKdigits(self, num: str, k: int) -> str:
stack = []
n = len(num) - k
for digit in num:
while k and stack and stack[-1] > digit:
stack.pop()
k -= 1
stack.append(digit)
res = ''.join(stack[:n]).lstrip('0')
return res or'0'#UT
print(Solution().removeKdigits('1432219',3))
6. 顺时针打印矩阵(剥洋葱打印)
from typing import List
classSolution:defspiralOrder(self, matrix: List[List[int]]) -> List[int]:
res = []
while matrix:
res += matrix.pop(0)
matrix = list(zip(*matrix))[::-1]
return res
matrix = [[1,2,3],[4,5,6],[7,8,9]]
print(Solution().spiralOrder(matrix))
7. 杨辉三角
from typing import List
classSolution:defgenerate(self, numRows: int) -> List[List[int]]:
ret = []
for i in range(1, numRows + 1):
tmp = [1for _ in range(i)]
for j in range(1, len(tmp) - 1):
# i - 2
tmp[j] = ret[i - 2][j - 1] + ret[i - 2][j]
ret.append(tmp)
return ret
# UT
print(Solution().generate(5))
8. 整数反转
classSolution:defreverse(self, x: int) -> int:# 特殊情况0if x == 0: return0# 边界判断,既要判断输入还要判断输出def_f(x):if2**31 < x + 1or x < -(2**31) or x == 0:
return0else:
return1def_reverse(x):return str(x).strip("0")[::-1]
if x > 0:
k = int(_reverse(x))
else:
k = -int(_reverse(-x))
if _f(k):
return k
else:
return0# UT
print(Solution().reverse(-123))
9. 回文数验证
classSolution:# 方法一:转字符串defisPalindrome(self, s: int) -> bool:returnFalseif x < 0else (x == int(str(x)[::-1]))
# s = str(x)# l = len(s)# h = l//2# return s[:h] == s[-1:-h-1:-1] # 省一半空间# 方法二defisPalindrome2(self, x: int) -> bool:if x<0or (x%10==0and x!=0):
returnFalseelif x == 0:
returnTrue
ans = 0# 只需判断一半长度while x>ans:
ans = ans*10 + x%10# 答案*10+新末尾数
x //= 10# 新末尾数 = 原数字的最后一位return x==ans or x==(ans//10)
# UT
print(Solution().isPalindrome2(101))
10. 回文串验证(忽略标点/空格符)
classSolution:# 筛选判断:O(N) O(N)defisPalindrome(self, s: str) -> bool:
sgood = "".join(ch.lower() for ch in s if ch.isalnum())
return sgood == sgood[::-1]
# 双指针原地判断:O(N) O(1)defisPalindrome2(self, s: str) -> bool:
n = len(s)
left, right = 0, n - 1while left < right:
while left < right andnot s[left].isalnum():
left += 1while left < right andnot s[right].isalnum():
right -= 1if left < right:
if s[left].lower() != s[right].lower():
returnFalse
left, right = left + 1, right - 1returnTrue
11. 回文串排列(是否存在)
# 位元算
a, b = 1<<2, 1<<4
c = a ^ b # c必然不是2的N次方
print(a&a-1,b&b-1,c&c-1) # 判断是否是2的N次方# 是否存在回文排列(思路和是否存在单独的奇数次一样)classSolution:# 方法一:异或(思路:2的N次方)defcanPlalindrome(self, s: str) -> bool:
n = 0for i in s:
n ^= 1<<ord(i) # 2的i次方# 如果存在多个异或未抵消的数,1<<ord(A) ^ 1<<ord)(B)肯定不是2的n次方return n & n - 1 == 0# 二进制判断是否是2的n次方(n & n - 1)# 方法二:Counter(奇数次数数量<=1)defcanPlalindrome2(self, s: str) -> bool:import collections
return sum(1for k, v in collections.Counter(s).items() if v % 2 != 0) <= 1# 方法三:Set(与方法二一样)defcanPlalindrome3(self, s: str) -> bool:
my_set = set()
for ch in s:
if ch in my_set:
my_set.remove(ch)
else:
my_set.add(ch)
return len(my_set) <= 1# UT
print(Solution().canPlalindrome2('aba'))
12. 有效括号
defisValid(s: str) -> bool:if len(s) % 2 == 1:
returnFalse
dic = {")": "(","]": "[","}": "{"}
stack = []
for i in s:
if stack and i in dic: # 如果栈不空,且i为有效右括号if stack[-1] == dic[i]: # 如果栈顶为对应的左括号,则弹出
stack.pop()
else:
returnFalse# 如果栈顶不是对应的左括号,则不匹配else:
stack.append(i) # 如果i为左括号(非右括号都会),入栈returnnot stack
defisValid2(s: str) -> bool:
arr = ['{}', '[]', '()']
l = len(s) // 2
print(l)
i = 0while i < l:
s = s.replace(arr[0], '').replace(arr[1], '').replace(arr[2], '')
i += 1return len(s) == 0# UT
s = '({()[]})'
print(isValid(s))
13. 罗马数字转整数
defroman2int(s: str) -> int:
dic = {'I': 1, 'IV': 4, 'V': 5, 'IX': 9, 'X': 10, 'XL': 40, 'L': 50,
'XC': 90, 'C': 100, 'CD': 400, 'D': 500, 'CM': 900, 'M': 1000}
su = []
i = 0while i < len(s):
v = s[i:i+2]
if v in dic:
su.append(dic[v])
i += 2else:
su.append(dic[s[i]])
i += 1return sum(su)
# UT
print(roman2int('MCMXC'))
14. 删除有序列表中重复元素后的新列表长度
from typing import List
defremoveDuplicates(nums: List[int]) -> int:ifnot nums:
return0
i = 0for j in range(1, len(nums)):
if nums[i] != nums[j]:
i += 1
nums[i] = nums[j]
return i + 1
a = [0,1,1,2,3,3,4]
print(removeDuplicates(a))
15. 列表中移除某元素
from typing import List
defremoveElement(nums: List[int], val: int):# 倒序遍历,避免pop()后取值索引-1导致的取值问题for i in range(len(nums) - 1, -1, -1):
if nums[i] == val:
nums.pop(i)
return len(nums)
# UT
nums, val = [3, 2, 2, 3, 5, 7], 3
print(removeElement(nums, val))
16. 矩阵转置
from typing import List
classSolution:deftranspose(self, arr: List[List[int]]) -> List[List[int]]:return [(i) for i in zip(*arr)]
arr = [[1, 2, 3], [4, 5, 6]]
print(Solution().transpose(arr)) # [(1, 4), (2, 5), (3, 6)]