刚听完一些算法课,但是自己是完全的代码小白,所以准备记录一下自己在leetcode上刷题的过程,还有自己的一些错误,主要针对的是剑指offer上的题目,从简单的开始。
leetcode上剑指offer 03:
这个问题主要是要求返回数组或列表中重复的任意一个元素
下面是自己第一次提交的代码,但是24个样例只通过了15个,报了错误。一开始没找到错误所在,后来检查了一下才发现在第二个for循环中我最后的范围错了,应该是len(nums)而不是len(nums)-1,因为这个是前包后不包的。
class Solution(object):
def findRepeatNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
for i in range(len(nums)-1):
for j in range(i+1, len(nums)-1):
if nums[i] == nums[j]:
return nums[i]
else:
return None
改正了代码之后提交,提醒我超出时间限制,对于我这个代码小白,最开始可能只能单纯的想到利用for循环来遍历,但我这里用了两层遍历,时间复杂度到了O(),对于非常长的列表复杂度太大。
然后我看了这个问题的题解,主要有两种方法:哈希表和原地置换。
哈希表方法主要是要初始化一个哈希表,然后遍历列表,如果哈希表中没有这个元素,则加进去,如果哈希表中存在当前遍历的元素,则说明重复,返回这个元素即可。代码如下:
class Solution:
def findRepeatNumber(self, nums: [int]) -> int:
dic = set() # 初始化一个空的哈希表,set()函数和初始化字典相似,但只有key没有value
for i in nums:
if i in dic:
return i
dic.add(i)
return -1
哈希表方法时间复杂度和空间复杂度都为O(n)
第二种方法是原地交换,一开始没看懂是怎么回事,后来看到题解中的大神利用萝卜和坑通俗的讲解大概知道了原理。由于题目中还给出了长度为n的数组所有元素都在0~n-1这一范围,说明可遍历数组并通过交换操作,使元素的索引与值一一对应。也就是nums[i] = i下面是该方法的代码:
class Solution:
def findRepeatNumber(self, nums: [int]) -> int:
i = 0
while i < len(nums):
if nums[i] == i: # 如果该索引值与值已经相等,则索引的指针后移一位
i += 1
continue
if nums[nums[i]] == nums[i]: # 此时说明找到重复元素,返回该元素即可
return nums[i]
nums[nums[i]], nums[i] = nums[i], nums[nums[i]]
return -1
其中,题解中大神提醒了一个注意点,是我之前不知道的,即:(这里直接复制大神原话)
Python 中, a, b = c, da,b=c,d 操作的原理是先暂存元组 (c, d)(c,d) ,然后 “按左右顺序” 赋值给 a 和 b 。
因此,若写为 nums[i], nums[nums[i]] = nums[nums[i]], nums[i]nums[i],nums[nums[i]]=nums[nums[i]],nums[i] ,则 nums[i]nums[i] 会先被赋值,之后 nums[nums[i]]nums[nums[i]] 指向的元素则会出错。
原地交换方法时间复杂度为O(n),额外空间复杂度为O(1)
看到题解中还有一位提出了一个解法,就是先将列表排序,遍历排序后的列表,如果存在前后元素一致的情况,则找到重复元素,返回该元素。代码如下:
class Solution:
def findRepeatNumber(self, nums: List[int]) -> int:
nums.sort() # 利用python内置的排序函数进行排序
for i in range(len(nums) - 1);
if nums[i] == nums[i + 1]:
return nums[i]
leetcode的题解中还有好多大神做的方法,不过我只看了这三种,其他的方法有时间可以再看一下。
这是第一次做代码题,也是我的第一篇博客,希望我这个基础都不太了解的代码小白可以继续加油,早日攻克代码!