(在我开始之前,让我们假设这是一个面试问题,我打算避免仅仅调用排序。)
我有这个有效的Python代码:
def merge_sorted_lists(left, right):
leftlen = len(left)
rightlen = len(right)
leftidx = 0
rightidx = 0
newlist = []
while leftidx < leftlen or rightidx < rightlen:
if rightidx == rightlen or left[leftidx] <= right[rightidx]:
newlist.append(left[leftidx])
leftidx += 1
elif leftidx == leftlen or right[rightidx] < left[leftidx]:
newlist.append(right[rightidx])
rightidx += 1
return newlist
我是一位长期从事C ++程序员的人,他最近学会了足够多的Python来了解这个&#34;闻起来&#34;与idx的大量使用非常非Pythonic。当迭代器的进步需要这个微调控件时,是否有更优雅的方法来遍历两个列表?
答案 0 :(得分:3)
def merge(left,right):
left = iter(left)
right = iter(right)
left_val = next(left)
right_val = next(right)
try:
while True:
if left_val <= right_val:
yield left_val
left_val = next(left) #left.next() in python2
else:
yield right_val
right_val = next(right)
except StopIteration: #I have exhausted one of the iterators
if left_val <= right_val:
#left list depleted
yield right_val
for i in right: yield i #or use yield from right, if your python is fancy enough
else:
#right list depleted
yield left_val
for i in left: yield i
In [2]: f = merge([0,4,17],[2,4,5,6,6,6])
In [3]: list(f)
Out[3]: [0, 2, 4, 4, 5, 6, 6, 6, 17]
答案 1 :(得分:2)
我知道您希望避免使用“已排序”,因为您需要一个更好地描述算法的解决方案,但老实说,我认为pythonic解决方案需要它。
def merge_sorted_lists(left,right):
return sorted(left+right)
对于非pythonic解决方案,在没有跟踪索引的情况下公开合理的算法,您可以尝试这种递归解决方案:
def merge_sorted_lists(left,right,acc=[]):
if not left:
return acc + right
if not right:
return acc + left
if left[0] < right[0]:
return merge_sorted_lists(left[1:],right,acc=acc+[left[0]])
else:
return merge_sorted_lists(left,right[1:],acc=acc+[right[0]])
这个比我的其他解决方案要长几行,而长输入可能会压倒堆栈。
答案 2 :(得分:0)
我可能会为此创建一个合并生成器:
def merge_generator(llist, rlist):
while len(llist) + len(rlist) > 0:
if len(llist) == 0:
yield rlist[0]
rlist = [1:]
elif len(rlist) == 0:
yield llist[0]
llist = [1:]
else:
if llist[0] < rlist[0]:
yield rlist[0]
rlist = rlist[1:]
else:
yield llist[0]
llist = llist[1:]
虽然它只是一个骨架,但你可以做得更好,例如通过分离循环等。