如何对一些元素进行排序并将其他元素留在Java中?

时间:2017-08-16 12:57:08

标签: java arrays sorting lambda

我希望对数组中的某些元素进行排序,但排除其他元素。

对于一个简单的例子,一个包含整数的数组,我想对奇数进行排序,但是将它们保持原样。

到目前为止,我有以下内容:

public class MyClass {
    public static void main(String args[]) {
        int temp;
        int array[] = {5, 3, 2, 8, 1, 4};

        int[] sortedArray = new int[array.length];
        for (int j = 0; j < array.length - 1; j++) {
            for (int x = 0; x < array.length - 1; x++) {
                if (array[x] > array[x + 1] && array[x] % 2 != 0 && array[x + 1] % 2 !=0) {
                    temp = array[x];
                    array[x] = array[x + 1];
                    array[x + 1] = temp;
                    sortedArray = array;
                }
            }
        }
        for (int i: sortedArray) {
            System.out.println(i);
        }

    }
}
  

给定整数数组: 5,3,2,8,1,4

     

代码输出: 3,5,2,8,1,4

     

预期输出: 1,3,2,8,5,4

无法弄清楚在原始数组中偶数之前出现较低奇数的情况所需的逻辑。

4 个答案:

答案 0 :(得分:20)

一个简单的蛮力解决方案:

  • 迭代输入数组,并检索所有奇数
  • 以新的较小数组收集奇数
  • 对该数组进行排序
  • 现在再次走初始数组:每当你找到一个奇数时,你选择&#34; next&#34;从奇数阵列进入

以上可能不是最佳解决方案(因为在第二个阵列上浪费内存,花费时间复制前后值) - 但它应该超级简单记下并测试。

理论上,你也可以做到这一点&#34;到位&#34;。含义:您可以创建一个包含int数组的类 - 但是为其用户提供视图,只显示奇数整数的数组。

示例实现(感谢Daniel Foerster):

public static int[] sortFiltered(int[] src, IntPredicate predicate) {
  int[] filtered = IntStream.of(src).filter(predicate).sorted().toArray();
  int[] dst = new int[src.length];
  for (int i = 0, j = 0; i < src.length; i++) {
    dst[i] = predicate.test(src[i]) ? filtered[j++] : src[i];
  }
  return dst;
}

使用奇数过滤器调用:

sortFiltered(array, (n) -> n % 2 != 0);

如您所见,此算法不依赖于特定谓词或数组/列表类型。但由于它使用IntStreamLambda Expressions,因此需要使用Java 8或更新版本。

答案 1 :(得分:1)

您已经实施了某种(非超高效)冒泡排序。您的代码的问题在于它排除了排序中的两个元素,即使只有一个是偶数。根据您的解决方案,您可以按如下方式调整代码:

public class MyClass {
    public static void main(String args[]) {
        int temp;
        //odd numbers are sorted, even number stay where they are
        //Expected output: 1, 3, 2, 8, 5, 4
        int array[] = {5, 3, 2, 8, 1, 4};
        int[] sortedArray = new int[array.length];
        for (int j = 0; j < array.length - 1; j++) {
            for (int x = 0; x < array.length - 1; x++) {

                while(array[x] % 2 == 0 && x < array.length-1){
                    x++;
                }

                int y = x+1;

                if(y < array.length) {
                    while (array[y] % 2 == 0 && y < array.length - 1) {
                        y++;
                    }

                    if (array[x] > array[y] && array[y] % 2 == 1 && array[x] % 2 == 1) {
                        temp = array[x];
                        array[x] = array[y];
                        array[y] = temp;
                        sortedArray = array;
                    }
                }
            }
        }
        for (int i: sortedArray) {
            System.out.println(i);
        }
    }
}

这导致:

  

1 3 2 8 5 4

答案 2 :(得分:1)

您的代码是一种冒泡类型,但您只需要比较每个直接邻居。这是使用2 for循环并在适当位置工作的工作代码。它不一定要比较直接邻居,而是查找下一个奇数以与当前奇数进行比较。

此外,将array复制到sortedArray时出现了一点错误,因为您执行此操作:sortedArray = array;在您的循环中只复制数组引用。在下面的工作代码中,我选择了您的解决方案并进行了更改。我也只是在排序开始之前复制数组,以便源数组不变。

内部for循环以外部for循环的索引加1开始。此外,内部循环只循环直到结束前的一个元素。在最糟糕的情况下,它需要n-1 * n/2 = n^2/2 - n/2次操作,这会导致 O(n^2) ,就像常规的冒泡排序一样。

代码和working example on ideone

public class MyClass
{
   public static void main(String args[])
   {
      int array[] = {5, 3, 2, 8, 1, 4};

      int[] sortedArray = new int[array.length];
      System.arraycopy(array, 0, sortedArray, 0, array.length);

      for (int i = 0; i < sortedArray.length - 1; i++)
      {
         /* is current odd, if so search next odd */
         if (sortedArray[i] % 2 != 0)
         {
            /* search for next odd and compare */
            for (int j = i + 1; j < sortedArray.length; j++)
            {
               if ((sortedArray[j] % 2 != 0) && (sortedArray[i] > sortedArray[j]))
               {
                  int temp = sortedArray[i];
                  sortedArray[i] = sortedArray[j];
                  sortedArray[j] = temp;
               }
            }
         }
      }
      for (int i: sortedArray)
      {
         System.out.println(i);
      }
   }
}

<强>输出:

  

1
  3
  2
  8
  5
  4

答案 3 :(得分:1)

给出未排序的数组A:按顺序创建2个包含数组的奇数和偶数元素的向量实例O和E. (所有代码示例都是伪代码。&#34;直到&#34;在循环中意味着根据标准数组绑定编号,不包括限制的右侧)

for i in 0 up to A.length: if A[i] is odd, append it to O, else append it to E

创建一个单独的布尔B数组,如下所示:

for i in 0 up to A.length: if A[i] is odd, B[i] = true, else B[i] = false

将O排序为新的Vector S(按升序排列)。我建议使用Java的内置排序,因为它比其他答案声称你正在使用的冒泡排序更有效。

S = ascendingSort(O)

定义一个操作 pop ,它返回Vector中的第一个项目,然后将其从Vector中删除。

创建一个新的空Vector R,然后实现以下伪代码:

for i in 0 up to B.length: if B[i] is true, then append pop(S) to R, else append pop(E) to R.

返回R作为结果。

为什么会这样:

首先,将平均值与平均值分开,以保持平均值,保持原始顺序(向量O和E)。保持原始数组中奇数/偶数项的位置(向量B)。

对赔率进行排序(向量S)。

排序后,按顺序缝合均匀和整理的赔率,保持平均的原始顺序。通过向量B读取,从向量E和S开始按顺序获取元素。这保持了均匀的顺序,因为它们首先按顺序放入向量E中,然后按顺序放回。