数组的一些相关题目

参考博客:https://www.jianshu.com/p/ef07ef2aa8d1

代码实现(python):

'''
数组问题
'''
#打印转圈数组
#nums = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
def rotate_print(nums):
    '''
    nums = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    '''
    if not  nums or not nums[0]:
        return -1
    m, n = len(nums), len(nums[0])
    res = []
    up, down, left, right = 0, m-1, 0, n-1
    while True:
        #从左至右
        for j in range(left, right+1):
            res.append(nums[up][j])
        up += 1
        if up > down:
            break
        #从上至下
        for j in range(up, down+1):
            res.append(nums[j][right])
        right -= 1
        if right < left:
            break
        #从右至左
        for j in range(right, left-1, -1):
            res.append(nums[down][j])
        down -= 1
        if down < up:
            break
        #从下至上
        for j in range(down, up-1, -1):
            res.append(nums[j][left])
        left += 1
        if left > right:
            break
    return res

#矩阵顺时针旋转90度
def rotate_90(nums):
    '''
    nums = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    '''
    n = len(nums)
    res = []
    nums.reverse()
    for i in range(n):
        res.append(list(map(lambda x:x[i], nums)))
    return res

#无序数组中最小的K个数
nums = [-3, 5, 4, 7, 2, -8, -12, 112, 224, -1185, 0]
def heapify(nums, head_idx, size):
    min_idx = head_idx
    left = min_idx * 2 + 1
    right = min_idx * 2 + 2
    if left < size and nums[left] < nums[min_idx]:
        min_idx = left
    if right < size and nums[right] < nums[min_idx]:
        min_idx = right
    if head_idx != min_idx:
        nums[min_idx], nums[head_idx] = nums[head_idx], nums[min_idx]
        heapify(nums, min_idx, size)
def min_heap(nums, size):
    for i in list(reversed(range(size))):
        heapify(nums, i, size)

def k_smallest(nums, k):
    '''
    堆排序
    '''
    size = len(nums)
    for i in range(size):
        min_heap(nums, size-i)
        nums[0], nums[size - i - 1] = nums[size - i - 1], nums[0]
    return nums[-k:]

#需要排序的最短子数组长度
def shortest_subarr(nums):
    '''
    需要排序的最短子数组长度:nums = [1,5,3,4,2,6,7]
    '''
    if not nums:
        return 0
    #找到右边需要排序的位置
    noMinIndex = - 1
    min_val = nums[-1]
    for i in range(len(nums)-1, -1, -1):
        if nums[i] > min_val:
            noMinIndex = i
        else:
            min_val = min(min_val, nums[i])
    if noMinIndex == -1:
        return 0
    print(noMinIndex)
    
    #找到左边需要排序的位置
    noMaxIndex = -1
    max_val = nums[0]
    for i in range(0, len(nums)):
        if nums[i] < max_val:
            noMaxIndex = i
        else:
            max_val = max(max_val, nums[i])
    if noMaxIndex == -1:
        return 0
    return nums[noMinIndex:noMaxIndex+1]


#在数组中找到出现次数n/k的数
def find_half(nums, k):
    half_time = len(nums) // k
    import collections
    for key, val in collections.Counter(nums).items():
        if val >= half_time:
            return int(key)
    return -1

#二元组
def two_tuples(nums, k):
    '''
    和为k的升序二元组:nums = [-8,-4,-3,0,1,2,4,5,8,9], k=10
    '''
    left = 0
    right = len(nums) - 1
    nums.sort()
    res = []
    while left < right:
        if nums[left] + nums[right] == k:
            if left == 0 or nums[left] != nums[left-1]:
                res.append((nums[left], nums[right]))
            left += 1
            right -= 1
        elif nums[left] + nums[right] < k:
            left += 1
        else:
            right -= 1
    return res

#三元组        
def three_tuples(nums, k):
    '''
    遍历每个值,变成二元组问题:nums = [-8,-4,-3,0,1,2,4,5,8,9], k=10
    '''
    if not nums or len(nums) < 3:
        return -1
    nums.sort()
    n = len(nums)
    res = []
    for i in range(n - 2):
        tmp_val = k - nums[i]
        left = i + 1
        right = n - 1
        while left < right:
            if nums[left] + nums[right] == tmp_val:
                if left == i+1 or nums[left] != nums[left-1]:
                    res.append((nums[i], nums[left], nums[right]))
                left += 1
                right -= 1
            elif nums[left] + nums[right] < tmp_val:
                left += 1
            else:
                right -= 1
    return res

#未排序数组中累加和为给定值的最长子数组长度
def unsorted_longest_sum_subarr_v1(nums, k):
    '''
    数组元素全为正:nums = [1, 2, 1, 1, 1], k = 3, res = 3;
    设置两个指针left和right,指针都从index=0的位置开始,指针的位置代表left-right的
    子数组的和,如果当前的和小于目标值,right++,如果大于目标值,则left++;
    '''
    n = len(nums)
    left, right, max_len, sum_val = 0, 0, 0, nums[0] 
    while right < n:
        if sum_val == k:
            max_len = max(max_len, right - left + 1)
            sum_val -= nums[left]
            left += 1
        elif sum_val < k:
            right += 1
            if right == n:
                break
            sum_val += nums[right]
        else:
            sum_val -= nums[left]
            left += 1
    return max_len


def unsorted_longest_sum_subarr_v2(nums, k):
    '''
    数组元素可正可负:nums = [-1,1,2,0,1,1,1], k = 3, res = 4
    '''
    if not nums:
        return False
    n = len(nums)
    sum_val, max_len = 0, 0
    dict_sum_idx = {}
    for i in range(n):
        sum_val += nums[i]
        if sum_val - k in dict_sum_idx.keys():
            max_len = max(max_len, i - dict_sum_idx.get(sum_val-k))
        if sum_val not in dict_sum_idx.keys():
            dict_sum_idx[sum_val] = i
    return max_len

#子数组最大累积和
def max_sum(nums):
    '''
    连续的子数组,nums = [1,-2,3,5,-2,6,-1], [3, 5, -2, 6], 12
    '''
    max_cur = nums[0]
    max_sofar = nums[0]
    for i in range(1, len(nums)):
        max_cur = max(nums[i], max_cur + nums[i])
        max_sofar = max(max_cur, max_sofar)   
    return max_sofar

#子矩阵的最大累积和问题
def max_submatrix_sum(matrix):
    '''
    子矩阵的最大累加和:矩阵按列相加,转换为一维数组求子数组最大累积和的问题
    matrix = [[-90, 48, 78], [64, -40, 64], [-81, -7, 66]], res = 209
    说明:按照题目给的例子,https://www.jianshu.com/p/ef07ef2aa8d1,实质上
    要求了每行都取得一样的列;
    '''
    if not matrix or not matrix[0]:
        return 0
    tmp = []
    #按列相加
    for i in range(len(matrix[0])):
        tmp_val = 0
        for j in range(len(matrix)):
            tmp_val += matrix[j][i]
        tmp.append(tmp_val)
    max_cur = tmp[0]
    max_sofar = tmp[0]
    for i in range(len(tmp)):
        max_cur = max(tmp[i], tmp[i] + max_cur)
        max_sofar = max(max_sofar, max_cur)
    return max_sofar
#matrix = [[-90, 48, 78], [64, -40, 64], [-81, -7, 66]]
#print(max_submatrix_sum(matrix))

#数组中子数组的累乘积
nums = [-2.5,4,0,3,0.5,8,-1]
def max_mul_subarr(nums):
    '''
    维护两个值,一个是以i位置结尾的子数组最大乘积,一个是以i位置结尾的子数组最小乘积
    subarr = [3, 0.5, 8], res = 12
    '''
    n = len(nums)
    max_val, min_val, res = nums[0], nums[0], nums[0]
    for i in range(1, n):
        if nums[i] > 0:
            max_val = max(nums[i], nums[i] * max_val)
            min_val = min(nums[i], nums[i] * min_val)
        else:
            max_val = max(nums[i], nums[i] * min_val)
            min_val = min(nums[i], nums[i] * max_val)
        res = max(res, max_val)
    return res

#不包含本位置的累乘数组,要求时间复杂度O(N),空间复杂度O(1),不适用除法
nums = [2, 3, 1, 4]
def no_curnum_mul(nums):
    '''
    维护两个数组,left和right,left[i]表示数组从0到i-1位置的累乘,
    right[i]表示数组从i+1位置到数组结束的累乘值
    '''
    if not nums:
        return False
    n = len(nums)
    left, right = [0] * n, [0] * n
    left[0], right[n-1] = 1, 1
    for i in range(1, n):
        left[i] = left[i-1] * nums[i-1]
    for i in range(n-2, -1, -1):
        right[i] = right[i+1] * nums[i+1]
    res = []
    for i in range(n):
        res.append(left[i] * right[i])
    return res

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值