Java - 合并两个数组并去除重复元素(不允许使用库)

4

需要解决编程问题。

必须使用Java,不能使用任何库(例如Arraylist等)。

int[] a = {1, 2, 3, 4, 8, 5, 7, 9, 6, 0}
int[] b = {0, 2, 11, 12, 5, 6, 8}

需要在一个方法中创建一个对象来引用这两个数组,将它们合并,去重并排序。

目前已经有了排序的部分,但是合并两个数组和去重还有一些困难。

int lastPos;
int index;
int temp;

for(lastPos = a.length - 1; lastPos >= 0; lastPos--) {
    for(index = 0; index <= lastPos - 1; index++) {
        if(a[index] > a[index+1]) {
            temp = a[index];
            a[index] = a[index+1];
            a[index+1] = temp;
        }
    }
}

如果有重复项,您想要删除哪一个?另外,为什么不使用ArrayList?它是标准的Java SE库,因此永远不会出现无法访问它的情况。 - ostrichofevil
你可以将数组相加,对它们进行排序并删除任何连续的相同数字。 - Peter Lawrey
1
除了作业之外,@ostrichofevil ;) - Peter Lawrey
啊,说得有道理。好的,我会仔细考虑这个问题的。 - ostrichofevil
如果我在做这个,我可能会单独对数组进行排序 - 使用冒泡排序,它易于编写并可以原地修改数组(看起来非常接近所示的代码) - 然后合并遍历结果,这也保证已排序;这是先前提到的方法的变体。 - user2864740
6个回答

3
一个将它们合并、去除重复项并排序的方法。 我建议您将其拆分为辅助方法(并稍微调整操作顺序)。步骤1,合并这两个数组。例如:
static int[] mergeArrays(int[] a, int[] b) {
    int[] c = new int[a.length + b.length];
    for (int i = 0; i < a.length; i++) {
        c[i] = a[i];
    }
    for (int i = 0; i < b.length; i++) {
        c[a.length + i] = b[i];
    }
    return c;
}
步骤2,对新数组进行排序(您现有的排序算法很好)。例如:
static void sortArray(int[] a) {
    for (int lastPos = a.length - 1; lastPos >= 0; lastPos--) {
        for (int index = 0; index <= lastPos - 1; index++) {
            if (a[index] > a[index + 1]) {
                int temp = a[index];
                a[index] = a[index + 1];
                a[index + 1] = temp;
            }
        }
    }
}

最后,删除重复项。第三步a,计算unique(独特)值。假设它们是唯一的,通过计算相邻且相等的值来递减。比如说,

static int countUniqueValues(int[] c) {
    int unique = c.length;
    for (int i = 0; i < c.length; i++) {
        while (i + 1 < c.length && c[i] == c[i + 1]) {
            i++;
            unique--;
        }
    }
    return unique;
}
然后进行第3b步,对唯一计数进行处理,并使用之前的方法构建结果。例如:
public static int[] mergeDedupSort(int[] a, int[] b) {
    int[] c = mergeArrays(a, b);
    sortArray(c);
    int unique = countUniqueValues(c);
    int[] d = new int[unique];
    int p = 0;
    for (int i = 0; i < c.length; i++) {
        d[p++] = c[i];
        while (i + 1 < c.length && c[i] == c[i + 1]) {
            i++;
        }
    }
    return d;
}
然后,您可以使用您的数组进行测试,例如:
public static void main(String[] args) {
    int[] a = { 1, 2, 3, 4, 8, 5, 7, 9, 6, 0 };
    int[] b = { 0, 2, 11, 12, 5, 6, 8 };
    int[] c = mergeDedupSort(a, b);
    System.out.println(Arrays.toString(c));
}

我得到了

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12]

2

你应该像这样使用IntStream。

    int[] a = {1, 2, 3, 4, 8, 5, 7, 9, 6, 0};
    int[] b = {0, 2, 11, 12, 5, 6, 8};
    int[] merged = IntStream
        .concat(IntStream.of(a), IntStream.of(b))
        .distinct()
        .sorted()
        .toArray();
    System.out.println(Arrays.toString(merged));

我喜欢这个回答。Java 8很整洁-带来了我喜欢C#的一些东西。 - Michael Goldstein

2
合并两个数组并去重排序(不使用任何库)。使用对象实现。
public class MergeRemoveDupSort {    

public int[] mergeRemoveDupSortIt(int[] a, int[] b) {   
    int [] c = mergeIt(a,b);
    int [] d = removeIt(c);
    int [] e = sortIt(d);
    return e;
}

private int[] mergeIt(int[] a, int[] b) {   
    int[] c = new int[a.length + b.length];        
    int k=0;
    for (int n : a) c[k++]=n;        
    for (int n : b) c[k++]=n;   
    return c;
}

private int[] removeIt(int[] c) {  
    int len=c.length;
    for (int i=0;i<len-1;i++) 
        for (int j=i+1;j<len;j++)
            if (c[i] == c[j]) {
                for (int k=j;k<len-1;k++)
                    c[k]=c[k+1];
                --len;
            } 
    int [] r = new int[len];
    for (int i=0;i<r.length;i++)
        r[i]=c[i];
    return r;
}

private int[] sortIt(int[] a) {   
    for(int index=0; index<a.length-1; index++)
       for(int i=index+1; i<a.length; i++)
           if(a[index] > a[i]){
               int temp = a[index];
               a[index] = a[i];
               a[i] = temp;
           }
     return a;
}    

public void printIt(int[] a) {   
    System.out.print("[");
    for (int i=0;i<a.length;i++){
        System.out.print(a[i]);
        if (i!=a.length-1) System.out.print(",");
        else System.out.print("]");            
    }        
}

public static void main(String[] args) {
    int[] a = {1, 2, 3, 4, 8, 5, 7, 9, 6, 0};
    int[] b = {0, 2, 11, 12, 5, 6, 8};

    MergeRemoveDupSort array = new MergeRemoveDupSort();
    int [] r = array.mergeRemoveDupSortIt(a, b);
    array.printIt(r);        
}        
}

谢谢您的帮助!我将它们都挤在一个方法里,并进行了一些调整,但是您的协助真的很棒!感谢! - BDelta
如果这篇回答对您有帮助的话,请考虑将其标记为有效答案。谢谢。 - SkyMaster

1
假设数组 a 和数组 b 已经排序,下面的代码将把它们合并到第三个数组 merged_array 中,并且不包含重复元素:
public static int[] get_merged_array(int[] a, int[] b, int a_size, int b_size)
{

  int[] merged_array = new int[a_size + b_size];


  int i = 0 , j = 0, x = -1;

  for(; i < a_size && j < b_size;)
  {
      if(a[i] <= b[j])
      {
          merged_array[++x] = a[i];

          ++i;
      }
      else          
      {
          if(merged_array[x] != b[j])
          {
              merged_array[++x] = b[j]; // avoid duplicates
          }

          ++j;
      }
  }

  --i; --j;

  while(++i < a_size)
  {
       merged_array[++x] = a[i];
  }

  while(++j < b_size)
  {
      merged_array[++x] = b[j];
  }

  return merged_array;
}
希望这能帮到你,祝一切顺利 :)

0
    try{
    int[] a = {1, 2, 3, 4, 8, 5, 7, 9, 6, 0};
    int[] b = {0, 2, 11, 12, 5, 6, 8};
    int[] c = new int[a.length+b.length];
    int[] final = new int[a.length+b.length];
    int i = 0;
    for(int j : final){
        final[i++] = -1;
    }
    i = 0;
    for(int j : a){
        c[i++] = j;
    }
    for(int j : b){
        c[i++] = j;
    }
    boolean check = false;
    for(int j = 0,k = 0; j < c.length; j++){
        for(int l : fin){
            if( l == c[j] )
                check = true;
        }
        if(!check){
            final[k++] = c[j];
        } else check = false;
    }

} catch(Exception ex){
    ex.printStackTrace();
}

我建议您在这种情况下使用Hashset,因为它不允许重复项,并且在Java 8中有另一种方法可以用于arraylist以删除重复项。在将所有元素复制到c后,请按照以下代码操作:

List<Integer> d = array.asList(c);
List<Integer> final = d.Stream().distinct().collect(Collectors.toList());
final.forEach(System.out::println());

这段代码比之前的好多了,你可以像这样再次将最终结果转换为数组

int array[] = new int[final.size()];              
    for(int j =0;j<final.size();j++){
      array[j] = final.get(j);
    }
希望我的工作能有所帮助。

-1

让我重申你的问题。

你想要一个程序,它可以取两个任意数组,合并它们并删除任何重复项,然后对结果进行排序。

首先,如果你可以访问任何数据结构,有更好的方法来实现这个。理想情况下,你会使用像 TreeSet这样的东西。

然而,假设你只能访问数组,那么你的选择就更加有限了。我会假设每个数组最初都没有重复项。

让我们假设第一个数组的长度为m,第二个数组的长度为n。

int[] array1; // length m
int[] array2; // length n

首先,让我们对两个数组进行排序。

Arrays.sort(array1);
Arrays.sort(array2);

假设您可以访问标准Java集合框架的一部分,其中包括Arrays类。如果没有,任何合理的合并实现(如MergeSort)都可以解决问题。

大多数良好的排序实现将花费O(n log n + m log m)的时间。

接下来,让我们合并这两个已排序的数组。首先,我们需要分配一个足够大以容纳所有元素的新数组。

int[] array3 = new int[size];
现在,我们需要按顺序插入array1array2的元素,注意不要插入任何重复项。
int index=0, next=0, i=0, j=0;
int last = Integer.MAX_INT;
while(i < m || j < n) {
    if(i == m)
        next = array2[j++];
    else if(j == n)
        next = array1[i++];
    else if(array1[i] <= array2[j])
        next = array1[i++];
    else
        next = array2[j++];

    if(last == next)
        continue;

    array3[index++] = next;
}
现在,你已经有了数组。只有一个问题 - 它可能在末尾有无效元素。最后一次复制应该解决这个问题...
int[] result = Arrays.copyOf(array3, index + 1);

插入操作和最终的复制都需要O(n + m)的时间,所以算法的整体效率应该是O(n log n + m log n)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,