题目
给你一个整型数组,其中有零和各种非零数字。请写一个函数或一段代码把非零成员都挪到数组前部,可以是任意顺序,并返回非零成员的数量。
要求:
- 请在原数组上进行操作,不要另新建数组副本。
- 尽可能地减少对数组的操作次数。
- 尽可能降低时间复杂度。
- 请提供一些test cases(测试用例)来测试你的代码。
例:[1, 0, 2, 0, 0, 3, 4, 0, 5]
经该函数调用后,返回值应为5,因为有5个非零成员。
数组经处理后可以接收的结果如 [4, 3, 1, 2, 5, 0, 0, 0, 0],[1, 2, 3, 4, 5, 0, 0, 0, 0] 或者 [2, 3, 5, 1, 4, 0, 0, 0, 0]等。所有非零成员被挪到了数组前部,对它们的顺序没有要求。
测试用例:
[1, 0, 2, 0, 0, 3, 4, 0, 5]
[1, 0, 2, 0, 0, 3, 4, 0, 5, 2]
[1, 0, 2, 0, 0, 3, 4, 0, 5,0]
[0, 1, 0, 2, 0, 0, 3, 4, 0, 5]
[0, 0, 1, 0, 2, 0, 0, 3, 4, 0, 5, 6]
[0, 1, 0, 2, 0, 0, 3, 4, 0, 5, 0]
[0, 1, 0, 2, 0, 0, 3, 4, 0, 5, 0, 0]
[0, 3, 6, 3, 2, 5, 1, 0, 2]
解答
头尾指针法
时间复杂度最好为n/2, 最坏为n,取为O(n)。
def test(arr):
i, j, z_count = 0, len(arr) - 1, 0
while i <= j:
if arr[i] != 0:
i += 1
else:
while i <= j:
if arr[j] == 0:
z_count += 1
j -= 1
else:
arr[i] = arr[j]
arr[j] = 0
i += 1
break
return arr, z_count
if __name__ == '__main__':
test_arr = [1, 0, 2, 0, 0, 3, 4, 0, 5, 0]
res, zero_count = test(test_arr)
print(res)
print(zero_count)
# input: [1, 0, 2, 0, 0, 3, 4, 0, 5]
# out: [1, 1, 2, 5, 3, 4, 0, 0, 0, 0, 0]
#
# input: [1, 0, 2, 0, 0, 3, 4, 0, 5, 2]
# out: [1, 2, 2, 5, 4, 3, 0, 0, 0, 0]
#
# input: [1, 0, 2, 0, 0, 3, 4, 0, 5, 0]
# out: [1, 5, 2, 4, 3, 0, 0, 0, 0, 0]
#
# input: [0,1, 0, 2, 0, 0, 3, 4, 0, 5]
# out: [5, 1, 4, 2, 3, 0, 0, 0, 0, 0]
#
# input: [0, 0, 1, 0, 2, 0, 0, 3, 4, 0, 5, 6]
# out: [6, 5, 1, 4, 2, 3, 0, 0, 0, 0, 0, 0]
#
# input: [0, 1, 0, 2, 0, 0, 3, 4, 0, 5, 0]
# out: [5, 1, 4, 2, 3, 0, 0, 0, 0, 0, 0]
#
# input: [0, 1, 0, 2, 0, 0, 3, 4, 0, 5, 0, 0]
# out: [5, 1, 4, 2, 3, 0, 0, 0, 0, 0, 0, 0]
#
# input: [0, 3, 6, 3, 2, 5, 1, 0, 2]
# out: [2, 3, 6, 3, 2, 5, 1, 0, 0]