剑指 Offer 03. 数组中重复的数字
这一题我首先看到数组里的数字小于数组长度我首先想到的是哈希表,设一个长度为n的hashtable能够极大地提高对重复元素的查询效率,但是牺牲了空间。
下面是代码
class Solution:
def findRepeatNumber(self, nums: List[int]) -> int:
n = len(nums)
hashtable = [0]*n
for i in nums:
hashtable[i] += 1
if hashtable[i] > 1:
return i
然后看了大佬的想法,可以用原地算法将空间复杂度降低为O(1)
class Solution:
def findRepeatNumber(self, nums: List[int]) -> int:
n = len(nums)
for i in range(n):
while i != nums[i]:
if nums[i] == nums[nums[i]]:
return nums[i]
tem = nums[i]
nums[i],nums[tem]= nums[tem],nums[i]
刷题心得:这里有一个python的小细节, 使用nums[i],nums[tem]= nums[tem],nums[i]不需要中间临时变量即可直接调换两个值,该方法同样适用于多个值
>>>a = 1
>>>b = 2
>>>c = 3
>>>a,b,c = c,b,a
>>>a,b,c
3,2,1
其中还有一个坑就是我们在交换时用到了临时变量tem,为什么不能直接用nums[i], nums[nums[i]] = nums[nums[i]], nums[i] 呢,因为在python交换中并不是同时交换,系统先把左边 nums[i] = nums[nums[i]] 交换,此时nums[i]已经改变所以右边自然无法交换成功。python, 交换列表中的两个值遇到的坑
可以改为以下代码,就能成功
nums[nums[i]], nums[i] = nums[i], nums[nums[i]]
剑指 Offer 53 - I. 在排序数组中查找数字
这道题首先想到的是双指针的解法
class Solution:
def search(self, nums: List[int], target: int) -> int:
right = len(nums) - 1
left = 0
while left<=right:
if nums[left] == target and nums[right] == target:
return right-left+1
elif nums[left] != target :
left += 1
elif nums[right] != target:
right -= 1
return 0
但是其实这道题考查的是二分法,要求时间复杂的为O(logn)
这是我自己写的二分法,有很多判断边界,所以没什么参考价值,但还是贴出来让大家引以为戒
class Solution:
def search(self, nums: List[int], target: int) -> int:
if nums==[]:
return 0
n = len(nums)
left = 0
right = n
while left < right:
mid = (left+right)//2
if nums[mid]>target:
right = mid
elif nums[mid]=0:
if nums[mid_left] == target:
num+=1
mid_left -= 1
else:
break
if mid_right=0 and mid_right
参考大佬的做法应用两次二分法
class Solution:
def search(self, nums: [int], target: int) -> int:
def helper(tar):
i, j = 0, len(nums) - 1
while i <= j:
m = (i + j) // 2
if nums[m] <= tar: i = m + 1
else: j = m - 1
return i
return helper(target) - helper(target - 1)
剑指 Offer 53 - II. 缺失的数字 LCOF
本题依然使用二分法
class Solution:
def missingNumber(self, nums: List[int]) -> int:
if nums==[]:
return 0
n = len(nums)
left = 0
right = n
while left
具体思路是如果nums[mid]==mid说明前半部分是按顺序的,left==mid+1,如果nums[mid]!=mid说明前半部分确实相应值,right==mid。
大佬做法,直接膜拜。
class Solution:
def missingNumber(self, nums: List[int]) -> int:
return sum(range(len(nums) + 1)) - sum(nums)