我希望对数组中的某些元素进行排序,但排除其他元素。
对于一个简单的例子,一个包含整数的数组,我想对奇数进行排序,但是将它们保持原样。
到目前为止,我有以下内容:
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
无法弄清楚在原始数组中偶数之前出现较低奇数的情况所需的逻辑。
答案 0 :(得分:20)
一个简单的蛮力解决方案:
以上可能不是最佳解决方案(因为在第二个阵列上浪费内存,花费时间复制前后值) - 但它应该超级简单记下并测试。
理论上,你也可以做到这一点&#34;到位&#34;。含义:您可以创建一个包含int数组的类 - 但是为其用户提供视图,只显示奇数整数的数组。
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);
如您所见,此算法不依赖于特定谓词或数组/列表类型。但由于它使用IntStream和Lambda 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)
,就像常规的冒泡排序一样。
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中,然后按顺序放回。