难度指数:⭐⭐⭐⭐⭐
知识点:滑窗
【华为OD机试真题2023B卷 JAVA&JS】根据某条件聚类最少交换次数
通用一般算法
【华为OD统一考试B卷 】根据某条件聚类最少交换次数 python
先计算出符合条件的数字个数,再以该数字为滑窗宽度去遍历,计算窗口内不符合条件的数字个数。
def min_swich(nums,k):
list_index, window = [], []
for i in range(len(nums)):
window.append(i)
if int(nums[i]) < k:
list_index.append(i)
len_num = len(list_index)
max_num = 0
for index in list_index:
num = len(set(list_index) & set(window[index:index + len_num]))
if num > max_num:
max_num = num
min = len_num - max_num
return min
创新算法
idea
将符合条件的数字的下标用一个list存储,遍历获得首尾数字差首次不大于K,其中K=len(list),计算此时len(list)-(首尾索引差+1),该值最小。
Note:为了避免滑窗失效的情况,需要设置所求最小值的最大值,max(K-1)。
代码实现
def min_swich0(list0,k):
listk=[]
for i in range(len(list0)):
if list0[i]<k:
listk.append(i)
K=len(listk)
count=K
for i in range(K):
for j in range(K-1,i,-1):
if listk[j]-listk[i]+1<=K:
temp=K-(j-i+1)
count=min(count,temp)
break
if(listk[K-1]-listk[i]+1<=K):
break
return min(max(0,K-1),count)
对比验证
耗时对比:
import random
from time import time
def min_swich(nums,k):
list_index, window = [], []
for i in range(len(nums)):
window.append(i)
if int(nums[i]) < k:
list_index.append(i)
len_num = len(list_index)
max_num = 0
for index in list_index:
num = len(set(list_index) & set(window[index:index + len_num]))
if num > max_num:
max_num = num
min = len_num - max_num
return min
def min_swich0(list0,k):
listk=[]
for i in range(len(list0)):
if list0[i]<k:
listk.append(i)
K=len(listk)
count=K
for i in range(K):
for j in range(K-1,i,-1):
if listk[j]-listk[i]+1<=K:
temp=K-(j-i+1)
count=min(count,temp)
break
if(listk[K-1]-listk[i]+1<=K):
break
return min(max(0,K-1),count)
T=10
while T:
list0=[random.randint(-100,100) for i in range(random.randint(5,100))]
k=random.randint(-100,100)
t1=time()
print(min_swich(list0,k))
t2=time()
print(min_swich0(list0,k))
t3=time()
T-=1
print(t2-t1,t3-t2)