《剑指offer》 Day1
数组中重复的数字
题目一:找出数组中重复的数字
在一个长度为n的数组里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数组。例如,如果输出长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3
思路:
1,可以先排序,然后从排序后的序列中找到重复的数字
2,建立一个哈希表,判断哈希表中是否出现了数组中的数字
3, 通过不断的调整每一个下标索引对应的数字,来查找重复的数字。
def duplicate1(nums):
if not nums or len(nums) <= 1:
return False
# 判断数组中的元素是不是在0~n-1范围内
n = len(nums)
for i in range(n):
if (nums[i] < 0) or (nums[i] > n-1):
return False
nums.sort() # 这里直接用python内部函数排序
for i in range(1, n):
if nums[i-1] == nums[i]:
return True
return False
'''使用额外的存储空间建立哈希表,来判断是不是有重复的元素存在'''
def duplicate2(nums):
hash_value = []
if not nums:
return False
n = len(nums)
for i in range(n):
if (nums[i] < 0) or (nums[i] > n-1):
return False
for num in nums:
if num in hash_value:
return True
else:
hash_value.append(num)
return False
# 交换下标元素,判断是不是有重复的数字
def duplicate3(nums):
if not nums:
return False
n = len(nums)
for i in range(n):
if (nums[i] < 0) or (nums[i] > n-1):
return False
for i in range(n):
while nums[i] != i:
if nums[i] == nums[nums[i]]:
return True
tmp = nums[i]
nums[i] = nums[tmp]
nums[tmp] = tmp
return False
题目二:不修改数组找出重复的数字
在一个长度为n+1的数组里的所有数字都在1~n的范围内,所以数组中至少有一个数字是重复的。请找出数组中任意重复的数字,但不能修改输入的数字。例如,如果输入长度为8的数字{2,3,5,4,3,2,6,7},那么对应的输出是重复的数字2或者3
'''
创建辅助数组来记录每一个元素,相当于把元素存入一个哈希表中,然后判读是否有重复的元素
空间复杂度:O(n)
时间复杂度:O(n)
'''
def find_num(nums):
hash_value = []
if not nums:
return -1
for num in nums:
if num in hash_value:
return num
else:
hash_value.append(num)
return -1
'''
二分查找,统计左右两个区间的元素数,根据统计元素的数量来判读重复的数字落在那个区间里面
空间复杂度为 O(1)
时间复杂度为 O(nlogn)
'''
def find(nums, length):
start = 1
end = length-1
if (not nums) or (length <= 0):
return -1
while end >= start:
middle = start + ((end - start) >> 1)
count = count_range(nums, length, start, middle)
if start == end:
if count > 1:
return start
else:
break
if count > (middle - start + 1):
end = middle
else:
start = middle+1
return -1
# 统计元素的个数
def count_range(nums, length, start, end):
if not nums:
return -1
count = 0
for i in range(length):
if (nums[i] >= start) and (nums[i] <= end):
count += 1
return count
二维数组中的查找
题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
分析二维数组的规律,从左到右递增,从上到下也是递增,那么为了避免重复搜索,我们可以选择从右上角或者左下角开始搜索,这样就可以每一列或者每一行的排出数据
# 从右上角开始搜索
def find(matrix, target):
if not matrix[0]:
return False
cols = len(matrix)
rows = len(matrix[0])
# 右上角
col = 0
row = rows-1
while (col < cols) and (row >= 0):
if matrix[col][row] == target:
return True
elif matrix[col][row] > target:
row -= 1
else:
col += 1
return False
# 从左下角开始搜索
def find2(matrix, target):
if not matrix[0]:
return False
cols = len(matrix)
rows = len(matrix[0])
# 左下角
col = cols-1
row = 0
while (col >= 0) and (row < rows):
if matrix[col][row] == target:
return True
elif matrix[col][row] > target:
col -= 1
else:
row += 1
return False
替换空格
题目:请实现一个函数,把字符串中的每一个空格替换成"%20"。例如,输入"We are happy.",则输出"We%20are%20happy."。
使用python的内置函数,先按照空格的位置分割字符出,然后再通过’%20’把它们连起来
还有python的replace函数,可以直接替换,还可以使用切片的形式
def replace_blank1(string):
if not string:
return None
return '%20'.join(string.split(' '))
def replace_blank2(string):
if not string:
return None
return string.replace(' ', '%20')
def replace_blank3(string):
if not string:
return None
cnt = 0
target = string[:]
n = len(string)
for i in range(n):
if string[i] == ' ':
cnt += 1
target = target[:i+(cnt-1)*2] + '%20' + target[(i+1)+(cnt-1)*2:]
return target
使用双循环的方法是,外循环来判断是不是有空格,内循环就开始在当前位置添加’%20’,并把其余的位置后移,这样的话时间复杂度比较高。
使用双指针的方法,先计算总长度记为一个指针,再计算加上’%20’后的长度,记为另一个指针,两个指针都往前走,等到他们相遇的时候,表示结束。
def replaceBlank(string):
if not string:
return None
original_length = 0
number_blank = 0
for i in range(len(string)):
original_length += 1
if string[i] == ' ':
number_blank += 1
new_length = original_length + number_blank*2
new_string = list(string) + number_blank*2*[None]
index_of_original = original_length-1
index_of_new = new_length-1
while (index_of_original >= 0) and (index_of_new > index_of_original):
if string[index_of_original] == ' ':
new_string[index_of_new-2:index_of_new+1] = ['%', '2', '0']
index_of_new -= 3
else:
new_string[index_of_new] = string[index_of_original]
index_of_new -= 1
index_of_original -= 1
return ''.join(new_string)