繁体   English   中英

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

[英]Shifting elements in a 2D array - Java

我正在寻找一种方法来上下移动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对象数组,其状态是决定移位的因素。 我只是在寻找能够实现这一结果的基本算法。 是否有捷径可寻?

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

对第一个数组中的每个数组执行bubblesort并根据您的顺序对它们进行排序

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

实施bubblesort非常简单,你必须在你的作业中做一些事情

试试这个方法

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;
}

}

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

  • 创建用于保持移位元素/最终结果的新数组
  • 迭代数组
  • 复制一个元素,该元素将被移位(满足条件)到新数组中的最后一个空闲位置
  • 复制一个元素,该元素不会被移位(不符合条件)到数组中的下一个空闲位置

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

编辑

仅仅为了完整起见,这里是上述算法的实现

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

效率低下的版本:

  • 在商店中遍历所有非0项的数组(例如,使用队列 ,可以使用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)

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

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

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

从两个指针开始,一个位于数组的左上角,另一个位于右下角。 让我们分别调用这些第一和第二指针。 现在使用第一个指针行方式遍历数组。 当你找到一个要放到末尾的元素时(在这种情况下为'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;

            }
        }
    }

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM