《剑指offer》 Day1

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/EngineerHe/article/details/100034467

《剑指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)

猜你喜欢

转载自blog.csdn.net/EngineerHe/article/details/100034467