本专栏主要记录力扣的刷题记录,备战蓝桥杯,供复盘和优化算法使用,也希望给大家带来帮助,博主是算法小白,希望各位大佬不要见笑,今天要分享的是——《力扣刷题记录——697. 数组的度、728. 自除数 、821. 字符的最短距离》。
目录
697. 数组的度
题目描述
解题思路
解题代码
728. 自除数
题目描述
解题思路
解题代码
821. 字符的最短距离
题目描述
解题思路
解题代码
697. 数组的度
题目描述
给定一个非空且只包含非负数的整数数组
nums
,数组的 度 的定义是指数组里任一元素出现频数的最大值。你的任务是在
nums
中找到与nums
拥有相同大小的度的最短连续子数组,返回其长度。示例 1:
输入:nums = [1,2,2,3,1] 输出:2 解释: 输入数组的度是 2 ,因为元素 1 和 2 的出现频数最大,均为 2 。 连续子数组里面拥有相同度的有如下所示: [1, 2, 2, 3, 1], [1, 2, 2, 3], [2, 2, 3, 1], [1, 2, 2], [2, 2, 3], [2, 2] 最短连续子数组 [2, 2] 的长度为 2 ,所以返回 2 。示例 2:
输入:nums = [1,2,2,3,1,4,2] 输出:6 解释: 数组的度是 3 ,因为元素 2 重复出现 3 次。 所以 [2,2,3,1,4,2] 是最短子数组,因此返回 6 。
解题思路
这个题目的难点在于如果出现多个次数相同的元素,到底哪一个是最优解。首先给自己提个醒,如果涉及到列表中元素需要数个数,那么一定要先用set去除重复项,要不然很容易报超时错误!主要是用字典将元素及其属性相关联,根据值查找键所用的方法为[k for (k,v) in sic.items() if v == value],这样可以将所有最高项生成一个列表,然后遍历这个列表中的元素,index获取第一个出现的元素,将列表倒序,第一个出现的索引即为原列表该元素最后一次出现的索引。将这两个作差,最小值即为待求元素。最后就很简单了,做一个列表切割,返回最终结果就可以了。
解题代码
def findShortestSubArray(nums):
if len(nums) == 1:
return 1
# 问题的关键在于如果最高次出现了多项,怎么确定哪一项才是真正的最优解
num_dic = {}
# 元素作为键,出现次数作为值
set_dic_1 = {}
for i in list(set(nums)):
set_dic_1[i] = nums.index(i)
for i in list(set(nums)):
num_dic[i] = nums.count(i)
max_ci = max(list(num_dic.values()))
max_list = [k for (k,v) in num_dic.items() if v == max_ci]
temp = {}
for num in max_list:
for i in range(len(nums) - 1, 0, -1):
if nums[i] == num:
end = i
temp[end-set_dic_1[num]] = num
break
max_num = temp[min(list(temp.keys()))]
l_index = nums.index(max_num)
r_index = 0
for i in range(len(nums)-1,0,-1):
if nums[i]== max_num:
r_index = i
break
return len(nums[l_index:r_index+1])
728. 自除数
题目描述
自除数 是指可以被它包含的每一位数整除的数。
- 例如,
128
是一个 自除数 ,因为128 % 1 == 0
,128 % 2 == 0
,128 % 8 == 0
。自除数 不允许包含 0 。
给定两个整数
left
和right
,返回一个列表,列表的元素是范围[left, right]
内所有的 自除数 。示例 1:
输入:left = 1, right = 22 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 15, 22]示例 2:
输入:left = 47, right = 85 输出:[48,55,66,77]
解题思路
这题的关键在找到每位数,用字符串切片的方式会方便很多,然后就是while循环,以及判断最后一个,一定要注意边界问题。将目标元素添加到目标列表中,最终返回目标列表。
解题代码
def selfDividingNumbers(left: int, right: int):
result = [] #盛放结果的列表
for i in range(left,right+1):
count = 0
temp_str = str(i)
if "0" not in temp_str:
while count <= len(temp_str) - 1:
if i % int(temp_str[count]) != 0:
break
if count == len(temp_str)-1:
result.append(i)
count +=1
else:
pass
return result
821. 字符的最短距离
题目描述
给你一个字符串
s
和一个字符c
,且c
是s
中出现过的字符。返回一个整数数组
answer
,其中answer.length == s.length
且answer[i]
是s
中从下标i
到离它 最近 的字符c
的 距离 。两个下标
i
和j
之间的 距离 为abs(i - j)
,其中abs
是绝对值函数。示例 1:
输入:s = "loveleetcode", c = "e" 输出:[3,2,1,0,1,0,0,1,2,2,1,0] 解释:字符 'e' 出现在下标 3、5、6 和 11 处(下标从 0 开始计数)。 距下标 0 最近的 'e' 出现在下标 3 ,所以距离为 abs(0 - 3) = 3 。 距下标 1 最近的 'e' 出现在下标 3 ,所以距离为 abs(1 - 3) = 2 。 对于下标 4 ,出现在下标 3 和下标 5 处的 'e' 都离它最近,但距离是一样的 abs(4 - 3) == abs(4 - 5) = 1 。 距下标 8 最近的 'e' 出现在下标 6 ,所以距离为 abs(8 - 6) = 2 。示例 2:
输入:s = "aaab", c = "b" 输出:[3,2,1,0]
解题思路
这题可以从左到右遍历一遍再从右到左遍历一遍,如果i为c的话count就为0,否则count累加,将结果储存一下。两次遍历取最小值就可以了。注意开始的时候,如果s[0]就等于c的话,好办,直接开始遍历就可以了。如果不等于c要把开始到c第一次出现之间的count进行倒叙,再添加到列表中。从右到左列表需要[::-1]变为正序,最后遍历两个列表,取相应位置的最小值,添加到目标列表中,最终返回这个目标列表。
解题代码
def shortestToChar(s: str, c: str):
# 从左到右遍历一遍,再从右到左遍历一遍,比较对应位置,选择最小的最为最终结果
l_r = []
r_l = []
temp_1 = []
temp_2 = []
result = []
count = 0
if s[0]==c:
for i in s:
if i == c:
count = 0
else:
count += 1
l_r.append(count)
else:
for i in s[:s.index(c):]:
if i == c:
count = 0
else:
count += 1
temp_1.append(count)
l_r.extend(temp_1[::-1])
for i in s[s.index(c)::]:
if i == c:
count = 0
else:
count += 1
l_r.append(count)
s = s[::-1]
if s[0] == c:
for i in s:
if i == c:
count = 0
else:
count += 1
r_l.append(count)
else:
for i in s[:s.index(c):]:
if i == c:
count = 0
else:
count += 1
temp_2.append(count)
r_l.extend(temp_2[::-1])
for i in s[s.index(c)::]:
if i == c:
count = 0
else:
count += 1
r_l.append(count)
r_l = r_l[::-1] # 颠倒回来
for i in range(len(r_l)):
result.append(min(r_l[i],l_r[i]))
return result