Python经典算法(小白入门系列)------合并有序数组

1.题目要求

如下2个有序列表,通过算法合并到一起,按照从下到大的顺序排列


arr1 = [1, 3, 4, 6, 10]
arr2 = [2, 5, 8, 12]

具体实现合并的效果,可以有很多种方式,但是本篇博文主要将的是一种算法的思想



2.拆分步骤

把key的值,插入到数组内的合适位置,最终数组满足升序要求


arr1 = [1, 3, 6, 8, 10]
key = 5
index_arr1 = 0
temp = arr1.copy()

while index_arr1 < len(arr1):
    print("index_arr1------", index_arr1)
    
    if key <= arr1[index_arr1]:
        temp.insert(index_arr1, key)
        
        print("------->", temp)
        break
    else:
        index_arr1 += 1
print("====================", temp)


index_arr1------ 0
index_arr1------ 1
index_arr1------ 2
-------> [1, 3, 5, 6, 8, 10]
==================== [1, 3, 5, 6, 8, 10]



3.特殊情况

1).特殊情况展示


arr1 = [1, 3, 6, 8, 10]
key = 12					# key = 12, 比数组的最后一个值都大
index_arr1 = 0
temp = arr1.copy()

while index_arr1 < len(arr1):
    print("index_arr1------", index_arr1)
    if key <= arr1[index_arr1]:
        temp.insert(index_arr1, key)
        print("------->", temp)
        break
    else:
        index_arr1 += 1
print("====================", temp)


index_arr1------ 0
index_arr1------ 1
index_arr1------ 2
index_arr1------ 3
index_arr1------ 4
==================== [1, 3, 6, 8, 10]

  • 按照以上的方式,最终12不会插入到列表中
  • 如上代码都循环完了,如果key的值有列表最后一个值小的,能插入的都插入了。没有插入的,可以理解为肯定是比列表最后一个值大的。


2).优化方案


arr1 = [1, 3, 6, 8, 10]
key = 12
index_arr1 = 0
temp = arr1.copy()

while index_arr1 < len(arr1):
    print("index_arr1------", index_arr1)
    if key <= arr1[index_arr1]:
        temp.insert(index_arr1, key)
        print("------->", temp)
        break
    else:
        index_arr1 += 1
else:
    temp.append(key)			# 其实只是添加一行,else,while 执行完之后,执行else的方案
print("====================", temp)


index_arr1------ 0
index_arr1------ 1
index_arr1------ 2
index_arr1------ 3
index_arr1------ 4
==================== [1, 3, 6, 8, 10, 12]

如果添加的while 和 else的妙处是,while在搜索一遍之后,发现没有需要插入的内容,然后再执行else



4.用for循环注意事项

1).常规情况下—没问题

如果key的值比列表最后一个值小,如下情况使用for循环没问题


arr1 = [1, 3, 6, 8, 10]
key = 5
index_arr1 = 0
temp = arr1.copy()

n = len(arr1)
for i in range(n):
    if key <= temp[i]:
        print("-----", key, arr1[i])
        temp.insert(i, key)
        print("-----", temp)
        break
    print(temp)
print("=====", temp)


[1, 3, 6, 8, 10]
[1, 3, 6, 8, 10]
----- 5 6
----- [1, 3, 5, 6, 8, 10]
===== [1, 3, 5, 6, 8, 10]

2).特殊情况下—特殊手段

如果key的值比列表最后一个值大,使用for循环就没办法实现了,不过我又优化了一下

arr1 = [1, 3, 6, 8, 10]
key = 12
index_arr1 = 0
temp = arr1.copy()

n = len(arr1)
insert = False
for i in range(n):
    if key <= temp[i]:
        print("-----", key, arr1[i])
        temp.insert(i, key)
        print("-----", temp)
        insert = True
        break
if not insert:
    temp.append(key)
print("=====", temp)


===== [1, 3, 6, 8, 10, 12]

3).最终使用使用2个for循环的结果


arr1 = [1, 3, 6, 8, 10]
arr2 = [5, 12]
index_arr1 = 0
temp = arr1.copy()

n = len(arr1)
for m in range(len(arr2)):
    insert = False
    for i in range(n):
        if arr2[m] <= temp[i]:
            print("-----", arr2[m], arr1[i])
            temp.insert(i, arr2[m])
            print("-----", temp)
            insert = True
            break
    if not insert:
        temp.append(arr2[m])
    print("=====", temp)


----- 5 6
----- [1, 3, 5, 6, 8, 10]
===== [1, 3, 5, 6, 8, 10]
===== [1, 3, 5, 6, 8, 10, 12]

  • 以上方法中,核心需要主要的问题是,在内部for循环之后,判断下是否有数据的插入到列表arr1;
  • 只要这个需要插入的数,哪怕比arr1列的一个数小,那么内部for循环就会有数据的插入。
  • 如果没有插入,那么对应的需要插入的元素,肯定就是比arr1的最后一个元素要大。那直接在内部的for循环外面,把这个元素appen到temp列表最后即可。


5.完整代码–合并有序数组


arr1 = [1, 3, 4, 6, 10]
arr2 = [2, 5, 8, 12]
index_arr1 = 0										
temp = arr1.copy()
for i in range(0, len(arr2)):
    while index_arr1 < len(arr1):					# 内部循环,解决的是遍历的条件
        print("index_arr1---", index_arr1)
        if arr2[i] <= arr1[index_arr1]:				# 这个才是内部循环核心的地方,需要找到arr2列表中比arr1某个位置的值,小的位置
            temp.insert(index_arr1 + i, arr2[i])	# 此处注意,插入的索引是index_arr1 + i,表示上次索引的位置加上这次内部又循环几次
            print("------->", temp)
            break
        else:
            index_arr1 += 1							# index_arr1在外部定义的,这样能保证,外部每次循环一次之后,下次就从上次的外部比较的索引位置开始比较,没必要每次都从头开始比较
            print("index_arr1--->", index_arr1)
        print("====================", temp)
    else:
        temp = temp + arr2[i:]

print(temp)



index_arr1---index_arr2---- 0 0
index_arr1---> 1
============================ [1, 3, 4, 6, 10]		# 循环一次分割线


index_arr1---index_arr2---- 1 0						# index_arr1在外循环外部设置的,表示每次内循环开始的位置,是上一次外循环结束的位置
-------> [1, 2, 3, 4, 6, 10]
index_arr1---index_arr2---- 1 1
index_arr1---> 2
============================ [1, 2, 3, 4, 6, 10]	# 循环一次分割线



index_arr1---index_arr2---- 2 1
index_arr1---> 3
============================ [1, 2, 3, 4, 6, 10]


index_arr1---index_arr2---- 3 1
-------> [1, 2, 3, 4, 5, 6, 10]
index_arr1---index_arr2---- 3 2
index_arr1---> 4
============================ [1, 2, 3, 4, 5, 6, 10]


index_arr1---index_arr2---- 4 2
-------> [1, 2, 3, 4, 5, 6, 8, 10]
index_arr1---index_arr2---- 4 3
index_arr1---> 5
============================ [1, 2, 3, 4, 5, 6, 8, 10]


[1, 2, 3, 4, 5, 6, 8, 10, 12]


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hello-alien

您的鼓励,是我最大的支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值