有序数组的交集和并集

先看下交集

Integer[] intersection(int[] a, int[] b) {
    if (a == null || b == null || a.length == 0 || b.length == 0) {
        return new Integer[0];
    }
    List list = new LinkedList<>();
    int i = 0, j = 0, alen = a.length, blen = a.length;
    while (i < alen && j < blen) {
        if (a[i] == b[j]) {
            list.add(a[i]);
            while (++i < alen && a[i] == a[i - 1]) ;
            while (++j < blen && b[j] == b[j - 1]) ;
        } else if (a[i] < b[j]) {
            while (++i < alen && a[i] == a[i - 1]) ;
        } else {
            while (++j < blen && b[j] == b[j - 1]) ;
        }
    }
    return list.toArray(new Integer[0]);
}

再看并集,这个要复杂一些。容易想到的算法是,将两个数组merge,得到一个新的有序数组,然后去重即可。但后来发现,在merge的时候就可以去重了。

Integer[] union(int[] x, int[] y) {
    int[] a = x == null ? new int[0] : x;
    int[] b = y == null ? new int[0] : y;

    LinkedList list = new LinkedList<>();
    int i = 0, j = 0, alen = a.length, blen = b.length;
    while (i < alen || j < blen) {
        if (i < alen && j >= blen) {
            if (list.isEmpty() || a[i] > list.getLast()) {
                list.add(a[i]);
            }
            while (++i < alen && a[i] == a[i - 1]) ;
        } else if (j < blen && i >= alen) {
            if (list.isEmpty() || b[j] > list.getLast()) {
                list.add(b[j]);
            }
            while (++j < blen && b[j] == b[j - 1]) ;
        } else {
            if (a[i] < b[j]) {
                list.add(a[i]);
                list.add(b[j]);
            } else if (a[i] > b[j]) {
                list.add(b[j]);
                list.add(a[i]);
            } else {
                list.add(a[i]);
            }
            while (++i < alen && a[i] == a[i - 1]) ;
            while (++j < blen && b[j] == b[j - 1]) ;
        }
    }
    return list.toArray(new Integer[0]);
}

首先注意一个技巧,int[] a = x == null ?new int[0] : x ,将null转换成空数组,这样就是用下面的代码,不然要专门写一段逻辑。

这里的merge和归并排序的merge有几点不同:
由于重复元素,i 和 j 的递增使用while循环。
当一个数组遍历完毕后,还需要考虑重复元素。

上面的代码略显啰嗦,可以简化:

Integer[] union(int[] x, int[] y) {
    int[] a = x == null ? new int[0] : x;
    int[] b = y == null ? new int[0] : y;

    LinkedList list = new LinkedList<>();
    int i = 0, j = 0, alen = a.length, blen = b.length;
    while (i < alen || j < blen) {
        if (j >= alen || (i < alen && a[i] <= b[j])) {
            if (list.isEmpty() || a[i] > list.getLast()) {
                list.add(a[i]);
            }
            //i++;
            while (++i < alen && a[i] == a[i - 1]) ;
        } else {
            if (list.isEmpty() || b[j] > list.getLast()) {
                list.add(b[j]);
            }
            //j++;
            while (++j < blen && b[j] == b[j - 1]) ;
        }
    }
    return list.toArray(new Integer[0]);
}

其中注释那行可以和while那行互换。
现在看来,没有必要非要使用链表,使用ArrayList也可以快的查看。
2019-03-20阅:
无论是在面试中还是工作中,都不要写过于复杂的代码,因为成本高、易出错。简简单单就是好的。

    Integer[] intersection(int[] a, int[] b) {
        if (a == null || b == null || a.length == 0 || b.length == 0) {
            return new Integer[0];
        }

        Deque deque = new LinkedList<>();
        int i = 0, j = 0, alen = a.length, blen = a.length;
        while (i < len && j < len) {
            if (a[i] > b[j]) {
                j++;
            } else if (a[i] < b[j]) {
                i++;
            } else {
                if (deque.isEmpty() || deque.getLast() != a[i]) {
                    deque.add(a[i]);
                }
                i++;
                j++;
            }
        }
        return deque.toArray(new Integer[0]);
    }

    Integer[] union(int[] x, int[] y) {
        int[] a = x == null ? new int[0] : x;
        int[] b = y == null ? new int[0] : y;
        Deque deque = new LinkedList<>();
        int i = 0;
        int j = 0;
        int alen = a.length;
        int blen = b.length;
        int key;
        while (i < alen || j < blen) {
            if (j >= blen || (i < alen && a[i] <= b[j])) {
                key = a[i++];
            } else {
                key = b[j++];
            }
            if (deque.isEmpty() || deque.getLast() != key) {
                deque.add(key);
            }
        }
        return deque.toArray(new Integer[0]);
    }

这次已经使用了Deque,比LinkedList要优雅些。

你可能感兴趣的:(有序数组的交集和并集)