Python蓝桥杯训练:数组和字符串 Ⅱ
文章目录
一、题目[1]:反转字符串中的字符
实现一个算法来实现反转字符数组的功能。反转的要求如下:
- 将字符数组的字符进行反转,例如
['b', ' ', 'a', 'r']
变成['r', 'a', ' ', 'b']
。- 将字符数组替换为反转后的数组。
本次挑战中,你需要在
reverse_chars.py
文件中补充函数reverse
的空缺部分。
reverse
函数接受一个参数,chars
用于指定传入的字符数组;reverse
函数输出一个字符数组。你需要补充
reverse
函数,使reverse
函数可以对传入的chars
字符数组进行反转。要求如下:
- 对于传入的字符数组,将字符数组的字符进行反转和替换,并返回替换后的字符数组;
- 如果传入的字符数组是
None
或者空字符数组,返回None
或者空字符数组。
这一题我第一眼觉得解题思路就是切片,首先判断是否为None或者空字符数组,然后再通过切片返回反转字符串后的字符,我相信大部分的人都是这样想的,但是这样的话是通过不了的,题目中有一个隐藏条件就是讲字符数组替换为反转后的数组,我们直接使用切片的话是没有实现该功能的,所以我们可以换一种方式来实现,具体代码实现如下:
class ReverseString(object):
def reverse(self, chars):
if chars is None or chars == '':
return chars
l = 0
r = len(chars) - 1
while l < r:
chars[l], chars[r] = chars[r], chars[l]
l += 1
r -= 1
return chars
这样我们就在原数组上进行了替换操作就可以通过了,我们也给出的参考答案:
class ReverseString(object):
def reverse(self, chars):
if chars:
size = len(chars)
for i in range(size // 2):
chars[i], chars[size - 1 - i] = chars[size - 1 - i], chars[i]
return chars
两种方法都可以,参考答案的可能更容易理解,它采用的就是将字符数组从中一分为二,然后将左右两边数组进行相互替换,思路都差不多。
二、题目[2]:找到给定字符串中的不同字符
在不考虑字符排列的条件下,对于相差只有一个字符的两个字符串,实现一个算法来识别相差的那个字符。要求如下:
- 当传入的字符串为
'aad'
和'ad'
时,结果为'a'
。- 当传入的字符串为
'aaabccdd'
和'abdcacade'
时,结果为'e'
。本次挑战中,你需要在
diff.py
文件中补充函数find_diff
的空缺部分。
find_diff
函数接受两个参数,str1
,str2
用于指定传入的相差只有一个字符的两个字符串;find_diff
函数输出只有一个字符的字符串。你需要补充
find_diff
函数,使find_diff
函数可以识别传入的str1
,str2
之间相差的那个字符。要求如下:
- 对于传入的两个字符串,返回它们之间相差的那个字符;
- 如果传入的字符串有
None
,需要使用raise
语句显示TypeError
。
这个题目我们一般都会想到最简单的方法,那就是一个字符一个字符的去比较,这样方法效率太低,而且代码繁琐,我们可以想到另一个比较简单的方法,那就是异或操作^
,字符串是可以通过ord()
的方法转换成数字的,然后我们就可以通过异或操作找到不同的字符,然后最后再通过chr()
方法将数字转换为对应字符。
异或操作是对数字的二进制进行操作,对于相同的位,如果都为 0 或者都为 1,那么结果是0,否则结果是 1。例如对于 a
,b
转换为数字是 97,100,转换为二进制是 ‘0b1100001’,‘0b1100100’,进行异或操作后的结果是 ‘0b0000101’。将结果再与 a
也就是 ‘0b1100001’ 进行异或操作,结果是 ‘0b1100100’,也就是字符 b
。如果对两个字符串的所有字符进行异或操作,那么得到结果是,对于出现奇数次的 1,结果是1,对于出现偶数次的 1,那么结果是0。所以结果是两个字符串中出现偶数次的字符,通过异或操作变为了 0,消去了,只有出现了奇数次的那个字符保留了下来。将这个字符的数字转换为字符再输出就是最后的结果。
具体实现代码如下:
class Solution(object):
def find_diff(self, str1, str2):
if str1 is None or str2 is None:
raise TypeError('str1或者str2不能是None!')
result = 0
x = [ord(i) for i in str1]
for i in x:
result ^= i
y = [ord(i) for i in str2]
for i in y:
result ^= i
return chr(result)
参考答案比我的简洁一点:
class Solution(object):
def find_diff(self, str1, str2):
if str1 is None or str2 is None:
raise TypeError('str1 or str2 cannot be None')
result = 0
for char in str1:
result ^= ord(char)
for char in str2:
result ^= ord(char)
return chr(result)
三、题目[3]:查找两个总和为特定值的索引
给定一个数组,找到两个总和为特定值的索引。
- 例如给定数组
[1, 2, 3, -2, 5, 7]
,给定总和7
,则返回索引[1, 4]
。本次挑战中,你需要在
sum.py
文件中补充函数two_sum
的空缺部分。
two_sum
函数接受两个参数,nums
用于指定传入的数组,val
用于指定和的值;two_sum
函数输出含两个索引的数组,或者TypeError
、ValueError
。你需要补充
two_sum
函数,使two_sum
函数可以找到数组nums
中两个总和为val
的值的索引。要求如下:
- 对于传入的数组
nums
,返回总和为val
的两个值的索引;- 如果数组中没有和为目标值的元素,则返回
None
。- 如果传入的数组
nums
或者目标值val
为None
,需要使用raise
语句显示TypeError
。- 如果传入的数组为空数组,需要使用
raise
语句显示ValueError
。
这个题目相对比较简单,可以直接使用两层for循环遍历数组,然后再通过判断两个值相加是否等于给定值,然后返回对应索引值即可,具体实现代码如下:
class Solution(object):
def two_sum(self, nums, val):
if nums is None or val is None:
raise TypeError('nums或val不能为None!')
if not nums:
raise ValueError('nums不能为空!')
for i in nums:
for j in nums:
if i + j == val:
return [nums.index(i), nums.index(j)]
return None
参考答案如下:
class Solution(object):
def two_sum(self, nums, val):
if nums is None or val is None:
raise TypeError('nums or target cannot be None')
if not nums:
raise ValueError('nums cannot be empty')
cache = {}
for index, num in enumerate(nums):
cache_val = val - num
if num in cache:
return [cache[num], index]
else:
cache[cache_val] = index
return None
相比于参考答案我的解法更适合大部分人理解,不过我们还是要学会举一反三,针对一个题目也要学会使用多种方法解决,参考答案使用了enumerate()
函数,它用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。例如:
seq = ['one', 'two', 'three']
for i, element in enumerate(seq):
print(i, element)
结果为:
0 one
1 two
2 three
四、题目[4]:Fizz Buzz经典问题
给定一个整数
num
,从1
到num
按照下面的规则返回每个数:
- 如果这个数被
3
整除,返回'Fizz'
。- 如果这个数被
5
整除,返回'Buzz'
。- 如果这个数能同时被
3
和5
整除,返回'FizzBuzz'
。- 如果这个数既不能被
3
也不能被5
整除,返回这个数字的字符串格式。本次挑战中,你需要在
fizzbuzz.py
文件中补充函数fizz_buzz
的空缺部分。
fizz_buzz
函数接受一个参数,num
用于指定传入的整数;fizz_buzz
函数输出一个数组。你需要补充
fizz_buzz
函数,使fizz_buzz
函数可以识别从1
到num
中能被3
或5
整除的数。要求如下:
- 对于传入的整数
num
,返回长度为num
的数组,数组的每个值由Fizz Buzz
的规则构成;- 如果传入的数为
None
,需要使用raise
语句显示TypeError
。- 如果传入的整数小于
1
,需要使用raise
语句显示ValueError
。
这个题目比较简单,是一个基础的流程判断和数组添加的题目,使用``if…elif…else`语句判断即可,具体实现代码如下:
class Solution(object):
def fizz_buzz(self, num):
if num is None:
raise TypeError('num不能为None!')
if num < 1:
raise ValueError('num不能小于1!')
nums = []
for i in range(1, num + 1):
if i % 3 == 0 and i % 5 == 0:
nums.append('FizzBuzz')
elif i % 3 == 0:
nums.append('Fizz')
elif i % 5 == 0:
nums.append('Buzz')
else:
nums.append(str(i))
return nums
跟参考答案基本一致,在这里就不粘贴了。