LeetCode题解(2020-10-26)

继续开始做题,仍然选择简单的题目。经过前几天刷题,虽然归为简单的一类题目,但是实际做起来感觉并不简单,继续努力。

题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])

今天就这样吧~

猜你喜欢

转载自blog.csdn.net/u012848304/article/details/109284804