计数未排序数组中的重复元素序列(java)

7lrncoxx  于 2021-07-03  发布在  Java
关注(0)|答案(2)|浏览(348)

我需要一个函数,它接收一个arraylist并返回一个相同大小的整数的新arraylist。他的元素将表示原始数组中索引i中值的重复序列数(出现次数)。
一次出现也将被视为一个序列。例如:arr[1,1,0,1]->元素“1”出现2次。
输入:它不必是排序数组。
保持数组内容在进程结束时的状态。
函数应该用java编写。
函数示例:
arr[3,0,1,2,1,1,1,3]▪︎ 输入:(arr)▪︎ 输出:newarray[2,1,2,1,2,2,2],因为“3”在序列中出现2次,“0”出现1次,依此类推。。。
arr[1,0,1,2,1,3]▪︎ 输入:(arr)▪︎ 输出:newarray[3,1,3,1,3,1]
arr[1,0,0,2,1,3,0]▪︎ 输入:(arr)▪︎ 输出:newarray[2,2,2,1,2,1,2]

i5desfxk

i5desfxk1#

您可以在时间复杂性中这样做:
步骤1使用变量“prev”检查前一个元素,并将其初始化为false/0。第2步每当您找到要检查的元素(比如x)时,在数组中移动,如果prev为false,则递增count,否则在数组中向前移动。

c9qzyr3d

c9qzyr3d2#

此任务类似于数组/列表中元素的常见计数频率,但是相邻元素(子序列)应计为1。也就是说,在计算频率时,如果前一个元素与当前元素相同,则增量为0。
要使用java流解决此任务,我们需要实现: Collector 类来累加最终值和索引列表,包括 merge 方法添加索引和频率。

static class CollectorList {
    int sum;
    List<Integer> indexes = new ArrayList<>();

    public CollectorList(List<Integer> h) {
        this.indexes.add(h.get(0));
        this.sum += h.get(1);
    }

    public CollectorList merge(CollectorList next) {
        this.sum += next.sum;
        this.indexes.addAll(next.indexes);
        return this;
    }
}

然后,获取自定义频率列表的方法可以实现如下:

public static List<Integer> getFrequencyList(int ... arr) {
    return new ArrayList<>(
        IntStream.range(0, arr.length)  // stream of indexes
                 .mapToObj(i -> Map.entry(
                     arr[i],            // key: current element
                     Arrays.asList(i, i > 0 && arr[i] == arr[i - 1] ? 0 : 1))) // store index and delta
                 .collect(Collectors.toMap(
                     Map.Entry::getKey, // for array elements
                     e -> new CollectorList(e.getValue()), // init collector of helper 
                     CollectorList::merge   // and merge
                 ))
                 .values() // get Collection<CollectorList>
                 .stream() // convert CollectorList back to index -> frequency
                 .flatMap(c -> c.indexes.stream().map(i -> Map.entry(i, c.sum)))
                 .collect(Collectors.toMap(
                     Map.Entry::getKey, 
                     Map.Entry::getValue, 
                     (i1, i2) -> i1, TreeMap::new // sort by index
                 ))
                 .values() // frequencies by index
        );
}

上面的代码使用Java9 Map.entry 为简洁起见,可将其替换为 new AbstractMap.SimpleEntry() 如果需要Java8兼容性。
测验:

int[][] tests = {
    {},
    {0},
    {1,2,1,2,1,3,1},
    {1,1,0,1},
    {3,0,1,2,1,1,1,3},
    {1,0,1,2,1,3},
    {1,0,0,2,1,3,0}
};
for (int[] arr : tests) {
    List<Integer> result = getFrequencyList(arr);
    System.out.println(Arrays.toString(arr) + " -> " + result);
}

输出

[] -> []
[0] -> [1]
[1, 2, 1, 2, 1, 3, 1] -> [4, 2, 4, 2, 4, 1, 4]
[1, 1, 0, 1] -> [2, 2, 1, 2]
[3, 0, 1, 2, 1, 1, 1, 3] -> [2, 1, 2, 1, 2, 2, 2, 2]
[1, 0, 1, 2, 1, 3] -> [3, 1, 3, 1, 3, 1]
[1, 0, 0, 2, 1, 3, 0] -> [2, 2, 2, 1, 2, 1, 2]

相关问题