算法题:将一维数组中的非零元素移动到数组前端(后端)

1. 题目

现有一个一维数组 a = [ 1 , 0 , 2 , 7 , 0 , 0 , 0 , 5 , 0 , − 3 ] a = [1, 0, 2, 7, 0, 0, 0, 5, 0, -3] a=[1,0,2,7,0,0,0,5,0,3],你需要将数组中非零元素移动到数组的前端,零元素在数组的后端。

1.1. 输入

一个一维数组 a = [ 1 , 0 , 2 , 7 , 0 , 0 , 0 , 5 , 0 , − 3 ] a = [1, 0, 2, 7, 0, 0, 0, 5, 0, -3] a=[1,0,2,7,0,0,0,5,0,3]

1.2. 输出

a = [ 1 , 2 , 7 , 5 , − 3 , 0 , 0 , 0 , 0 , 0 ] a = [1, 2, 7, 5, -3, 0, 0, 0, 0, 0] a=[1,2,7,5,3,0,0,0,0,0]

2. 算法一

2.1. 分析

看到题目的第一想法就是,用另外一个和 a a a 等长度的数组来保存这些非零元素。

2.2. 代码

public class Solution
{
	/**
	 * 一维数组中的非零元素前移.
	 *
	 * @param array 一维数组.
	 * @return 非零元素前移后的一维数组.
	 */
	public static int[] nonZeroElementsMoveForward(int[] array)
	{
		// 边界检查
		if (array == null || array.length == 0)
			return array;
		// 创建一个和 array 等长的数组,自动初始化为 0.
		int[] changedArray = new int[array.length];
		// 非零元素 array[i] 放入 changedArray 中的第 j 个位置.
		for (int i = 0, j = 0; i < array.length; ++i)
			if (array[i] != 0)
				changedArray[j++] = array[i];
		return changedArray;
	}
	
	/**
	 * 程序的入口.
	 * 
	 * @param args 接收系统的参数
	 */
	public static void main(String[] args)
	{
		int[] array = {1, 0, 2, 7, 0, 0, 0, 5, 0, -3};
		System.out.println(Arrays.toString(array));
		array = nonZeroElementsMoveForward(array);
		System.out.println(Arrays.toString(array));
	}
}

2.3. 结果

在这里插入图片描述

3. 算法二

能不能不创建新的数组,直接在原数组上进行操作呢?

3.1. 分析

在此基础上进行分析:
输入中的元素 2,向前移动了 1 位,占据的是第一个 0 的位置(0 元素的位置是空闲的);
输入中的元素 7,向前移动了 1 位,占据的是上一个元素 2 空出来的位置(因为元素 2 向前移动了 1 位,所以这个位置空了出来);
输入中的元素 5,向前移动了 4 位,占据的是上一个元素 7 空出来的位置(因为元素 7 向前移动了 1 位,所以这个位置空了出来);
……

好像有一点点规律了。
当遍历到数组中的非零元素的时候,假如知道上一个空闲位置就好了!!!

额外的一个指针就可以实现这样的功能。

遍历数组的指针 i,指向空闲位置的指针为 j。
初始化,i = 0,j = 0。
i 往后遍历,当 a[i] != 0 时,将 a[i] 放入 j 指示的位置上,即 a[j] = a[i],然后 j 自增 1,指向下一个空闲位置。
不过需要注意的是,当 i 完成遍历时,j 到 i 之间的元素,需要置为零。
……

这种解法就是典型的双指针法

3.2. 代码

public class Solution
{
	/**
	 * 一维数组中的非零元素前移.
	 *
	 * @param array 一维数组
	 */
	public static void nonZeroElementsMoveForward(int[] array)
	{
		// 边界检查
		if (array == null || array.length == 0)
			return;
		// i 遍历数组,j 指示下一个空闲位置
		int i, j;
		// 将非零的元素 array[i] 放入 j 指示的位置中.
		for (i = 0, j = 0; i < array.length; ++i)
			if (array[i] != 0)
				array[j++] = array[i];
		// i 结束遍历时,j 之后的元素需要置为 0.
		Arrays.fill(array, j, i, 0);
	}
	
	/**
	 * 程序的入口.
	 *
	 * @param args 接收系统的参数
	 */
	public static void main(String[] args)
	{
		int[] array = {1, 0, 2, 7, 0, 0, 0, 5, 0, -3};
		System.out.println(Arrays.toString(array));
		nonZeroElementsMoveForward(array);
		System.out.println(Arrays.toString(array));
	}
}

3.3. 结果

在这里插入图片描述

4. 非零元素移动到数组后端

思想和非零元素移动到数组前端一致,只需要将 i 和 j 从数组尾部进行遍历即可。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值