参考博客: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