继续开始做题,仍然选择简单的题目。经过前几天刷题,虽然归为简单的一类题目,但是实际做起来感觉并不简单,继续努力。
题1:所有奇数长度子数组的和
题目描述
给你一个正整数数组 arr ,请你计算所有可能的奇数长度子数组的和。
子数组 定义为原数组中的一个连续子序列。
请你返回 arr 中 所有奇数长度子数组的和 。
示例 1:
输入:arr = [1,4,2,5,3]
输出:58
解释:所有奇数长度子数组和它们的和为:
[1] = 1
[4] = 4
[2] = 2
[5] = 5
[3] = 3
[1,4,2] = 7
[4,2,5] = 11
[2,5,3] = 10
[1,4,2,5,3] = 15
我们将所有值求和得到 1 + 4 + 2 + 5 + 3 + 7 + 11 + 10 + 15 = 58
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sum-of-all-odd-length-subarrays
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
感觉这题对我来说挺难的,主要考察的应该是列表切片的问题,总是感觉很快能做出来了,但是实际还是很难完整的写出来,下面的答案参考了别人的思路。
提交代码
class Solution:
def sumOddLengthSubarrays(self, arr: List[int]) -> int:
odd = 0
for j in range(1, len(arr)+1, 2):
for i in range(len(arr) - j + 1):
odd = odd + sum(arr[i:i+j])
return odd
提交情况
思考
变量j是为了获取奇数切片,变量i是切片的初始位置,len(arr) - j + 1是为了保证索引时不要超过arr列表的长度。
理是这么个理,不过理清楚还是挺困难的。
这种算法的时间复杂度应该是O(N^2),我想应该还有效率更高的解法,我试图计算每个数字会出现的次数,可惜没能想明白,不然时间复杂度应该会降低不少。
题2:错误的集合
题目描述
集合 S 包含从1到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个元素复制了成了集合里面的另外一个元素的值,导致集合丢失了一个整数并且有一个元素重复。
给定一个数组 nums 代表了集合 S 发生错误后的结果。你的任务是首先寻找到重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。
示例 1:
输入: nums = [1,2,2,4]
输出: [2,3]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/set-mismatch
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路1
乍一看这题挺简单,结果难度出乎意料之外,先看看我的提交情况
当然我并没有这么水,前面几次都是没理解题目的意思出的错,中间因为有别的事情,就去干活了,中间有一次是对的,就是超出时间限制的那次。
先说我的解题思路,我压根就没想到位运算上面去,因为平时很少用到。第一步,先生成一个和nums具有一样长度的、从1开始的顺序列表arr,遍历arr,找到不在nums中的元素,这个就是后面的那个数字;第二步,用count函数计算nums中出现两次的数据,这个就是前面那个数。
看看我的代码:
class Solution:
def findErrorNums(self, nums: List[int]) -> List[int]:
arr = list(range(1,len(nums)+1))
r = []
for i in range(len(nums)):
if nums.count(nums[i]) == 2:
wrong = nums[i]
if arr[i] not in nums:
right = arr[i]
r = [wrong, right]
return r
我觉得没问题,而且时间复杂度并不复杂,不过还是超出了时间限制,肯定不可取。后来想了一下,应该在计算前面那个数字时出现了问题,于是把wrong的计算方法改了一下,如下:
class Solution:
def findErrorNums(self, nums: List[int]) -> List[int]:
arr = list(range(1,len(nums)+1))
nums.sort()
w = sum(nums) - sum(set(nums))
for i in range(len(nums)):
if arr[i] not in nums:
r = arr[i]
return [w, r]
这样就对了,但提交的情况不太理想
解题思路2
正确的方法应该是用位预算
看看别人怎么写的
class Solution:
def findErrorNums(self, nums: List[int]) -> List[int]:
a = sum(nums)-sum(set(nums)) # a为重复数字,b为缺失数字
c = 0
for i, num in enumerate(nums, 1): # 从1开始计数
c ^= (i^num)
b = c^a
return [a, b]
我只能说位运算果然牛逼
学习了。
思考
温习一下位运算,比较两个数据的二进制数据,如果相同位都是0或者1,就取0,不同就取1,如5的二进制是101,6的二进制是110,那么5^6的二进制就是011,换成10进制就是3,也就是说5 ^6=3。
题3:反转字符串中的单词 III
题目描述
给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。
示例:
输入:“Let’s take LeetCode contest”
输出:“s’teL ekat edoCteeL tsetnoc”
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-words-in-a-string-iii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
总是遇到个正常点的题目了,还是考察列表切片
提交代码
class Solution:
def reverseWords(self, s: str) -> str:
news = s.split(' ')
b = []
for n in news:
n = n[::-1]
b.append(n)
rs = ' '.join(b)
return rs
提交结果
同样肯定不是最优解,看了别人写的题解,可以先反转字符串,再反转列表,这样挺好的
class Solution(object):
def reverseWords(self, s):
return " ".join(s[::-1].split(" ")[::-1])
今天就这样吧~