在2D数组中移动元素 - Java

时间:2013-04-09 11:04:59

标签: java multidimensional-array

我正在寻找一种方法来将2D数组中的所有元素向上和向上移位,以便满足特定条件的元素留在数组的末尾。我的意思的简化示例:

一个二维整数数组,用1填充,四个零。

1 1 1 1 1  
1 1 1 1 0  
1 1 1 0 1  
1 1 1 1 1  
0 0 1 1 1 

我想要做的是通过移动其他元素来填充孔(零),在末尾留下零。期望的结果是:

1 1 1 1 1  
1 1 1 1 1  
1 1 1 1 1  
1 1 1 1 1  
1 0 0 0 0

在我的项目中,我正在处理2D对象数组,其状态是决定移位的因素。我只是在寻找能够实现这一结果的基本算法。有一个简单的方法吗?

7 个答案:

答案 0 :(得分:2)

迭代数组并计算零。每次你发现零加1到你的计数器并将零替换为1.然后从数组的末尾开始到它的开头,用N替换0,其中N是零的总数。

答案 1 :(得分:0)

对第一个数组中的每个数组进行冒泡排序,并按照您的顺序对它们进行排序

for (i=0; i<array1.length; i++){
   yourBubblesort(array1[i]);
}

实施冒泡排序非常简单,你必须在你的家庭作业中做点什么

答案 2 :(得分:0)

尝试这种方法

public void shiftZeros(int[] arr )
{
int count;
for(int j=0;j<arr.length-1;j++)
{
  if(arr[j]=0)
   {
    arr[j]=1;
    count++;
   }
}

for(int j=arr.length-1,i=1;i<count;i++,j--)
{
   arr[j]=0;
}

}

答案 3 :(得分:0)

这是一种使用复制到新数组的方法

  • 创建用于保存已转换元素/最终结果的新数组
  • 迭代数组
  • 复制一个要移位(满足条件)的元素 新数组中的自由位置
  • 复制一个不被转移的元素(不符合 条件)到阵列中的下一个自由位置

当元素即将满足处理结束时,将不会重叠。

修改

仅为了完整性,这里是上面算法的实现

private E[][] shift(E[][] input) {
    int maxLen = get2DMaxLen(input);
    int i_next = 0, j_next = 0;
    int i_least = input.length-1, j_least = maxLen-1;
    E[][] actual = new E[input.length][maxLen];
    for(int i = 0; i < input.length; i++) {
        for(int j = 0; j < input[i].length; j++) {
            if(meetsCondition(input[i][j])) {
                actual[i_least][j_least--] = input[i][j];
                if(j_least == -1) {
                    j_least = maxLen-1;
                    i_least--;
                }
            } else {
                actual[i_next][j_next++] = input[i][j];
                if(j_next == input[i].length) {
                    j_next = 0;
                    i_next++;
                }
            }
        }
    }
    return actual;
}

测试输入

0 1 1 0 1 
0 1 1 1 0 
1 0 1 0 1 
1 1 0 1 1 
0 0 1 1 1 

输出

1 1 1 1 1 
1 1 1 1 1 
1 1 1 1 1 
1 0 0 0 0 
0 0 0 0 0

答案 4 :(得分:0)

效率低下的版本:

  • 在商店中迭代所有非0项(例如queue,可以使用LinkedList进行模拟)。

  • 再次迭代,只需将存储的项目逐个拉入数组

迭代器通过类似的东西:

for (int i = 0; i < arr.length; i++)
for (int j = 0; j < arr[i].length; j++)
  ...

更多(空间)效率版本:

同时迭代数组两次,读取每个值并将它们放在正确的位置。

伪代码:(希望足够可读)

while ahead.hasNext
  // skip all 0s
  do
    i = ahead.next
  while i == 0
  behind.writeNext(i)

// the rest must all be 0
while behind.hasNext
  behind.writeNext(0)

我不能给你代码,因为我不能为你做所有的工作。

答案 5 :(得分:0)

为什么不对列进行排序,然后对每行进行排序?有很多算法可以做到这一点。

答案 6 :(得分:0)

对于上面的确切问题,解决方案可以是:

从两个指针开始,一个位于数组的左上角,另一个位于右下角。让我们分别调用这些第一和第二指针。现在使用第一个指针行方式遍历数组。当你找到一个要放到末尾的元素时(在这种情况下为'0'),检查第二个元素指向的元素。如果第二个元素是0,则递减第二个指针指向2-d数组中的倒数第二个元素。现在检查这个元素,如果这也是'0'再次递减第二个指针,依此类推,直到你达到'1'(一个必须在数组开头的元素)。然后交换这两个元素。在指针相互交叉的任何时间点,阵列都按要求排序。

以下java代码将执行此操作: 最初变量endi和endj指向最后一个元素(第二个指针),变量i和j指向第一个元素(第一个指针)。数组大小为m X n。

for(i=0;i<m;i++)
    {
        for(j=0;j<n;j++)
        {
            if(a[i][j]==0)
            { 
                while(a[endi][endj]!=1 && i*m+j<endi*m+endj) //second part of the condition checks if i,j and endi,endj haven't crossed over
                {
                    endj--;
                    if(endj==-1)
                    {
                        endj=n-1;
                        endi--;
                        if(endi==-1)
                        {
                            disparr(a,m,n);
                            System.exit(0);
                        }
                    }
                }
                if(!(i*m+j<endi*m+endj))//if the pointer have crossed over
                {
                    disparr(a,m,n);
                    System.exit(0);
                }    
                int t=a[i][j];
                a[i][j]=a[endi][endj];
                a[endi][endj]=t;

            }
        }
    }

对于例如上述代码的其他改进是可能的。删除用于递减函数指针并调用它的代码。但代码可以正常工作。