列表中具有频率的连续重复整数的计数

时间:2019-04-30 20:41:34

标签: java

我想计算一个字节列表中连续重复数字的数量,并将它们显示为两个整数数组:

  • 第一个数组包含非重复整数值。
  • 第二个数组包含随后的重复计数。

因此,对于这样的输入:

Byte[] bytes = new Byte[] {2, 2, 2, 0, 0, 0, 0, 2, 2, 0, 0, 2};

我期望这样的输出:

integers  -[2, 0, 2, 0, 2]
frequency -[3, 4, 2, 2, 1]

基本上,这是输入的压缩视图。输出显示整数2重复3次,然后是0,重复4次,然后是2重复2次,依此类推。

我写了下面的代码。

 List<Byte> integers = new ArrayList<>();
 List<Integer> frequencies = new ArrayList<>();

 for (int i=0; i < bytes.size() - 1; i++) {
     Byte current = bytes.get(i);
     Byte next = bytes.get(i+1);
     if (current == next) {
         count ++;
         // if all bytes are of the same type
         if (count == bytes.size() || i == bytes.size() - 2) {
             integers.add(current);
             frequencies.add(count);
         }
         continue;
         integers.add(current);
         frequencies.add(count);
         count = 1;
     }
 }
 System.out.println("integers " +  integers + " - frequency " + frequencies);

此代码适用于大多数情况。但是我缺少一些优势案例。就像示例输入一样,输出缺少到达最后一个元素2的值。我输入的代码输出是-

integers  -[2, 0, 2, 0]
frequency -[3, 4, 2, 2]

我要添加一堆if语句来涵盖所有极端情况,但我想知道是否有更清洁的解决方案?

4 个答案:

答案 0 :(得分:1)

我没有尝试在IDE上运行此代码,但我认为这足够了:

int count = 1;
int index = 0;

byte current = bytes[index];
while (index < bytes.length - 1) {
    index++;
    if (bytes[index] == current) {
        count++;
    } else {
        integers.add(current);
        frequencies.add(count);
        count = 1;
        current = bytes[index];
    }
}

integers.add(current);
frequencies.add(count);

答案 1 :(得分:0)

使用continue是一个问题。

for (int i=0; i < bytes.size() - 1; i++) {
     Byte current = bytes.get(i);
     Byte next = bytes.get(i+1);
     if (current == next) {
         count ++;
         // if all bytes are of the same type
         if (count == bytes.size() || i == bytes.size() - 2) {
             integers.add(current);
             frequencies.add(count);
         }
         continue;
         integers.add(current);
         frequencies.add(count);
         count = 1;
     }
 }

continue”表示它将立即转到for循环的顶部。因此,continue语句之后的几乎所有内容都是死代码-它永远不会执行,因为continue意味着“跳至for循环的下一个迭代”。因此,我们永远不会到达此代码:

integers.add(current);
frequencies.add(count);
count = 1;

话虽如此,您的逻辑也有一个缺陷。。它仅迭代到倒数第二个元素,因为它与下一个比较。也就是说,如果您输入的是[1、2、3],则迭代如下:

  1. 当前= 1,下一个= 2
  2. 当前= 2,下一个= 3

...就是这样。您将需要在循环外处理“最后一个数字”用例,或者更新循环以循环到最后(并适当地保护get(i+1)调用。)当然,这仅在以下情况下才有意义最后一个数字和倒数第二个不同;如果是这样,则最后一个数字将被“计数”为前一个数字的重复。

答案 2 :(得分:0)

您可以使用此功能:

Byte[] bytes = new Byte[]{2, 2, 2, 0, 0, 0, 0, 2, 2, 0, 0, 2};

List<Byte> integers = new ArrayList<>();
List<Integer> frequencies = new ArrayList<>();
for (Byte b : bytes) {
    if (integers.isEmpty() || !integers.get(integers.size() - 1).equals(b)) {
        integers.add(b);
        frequencies.add(0);
    }
    frequencies.set(frequencies.size() - 1, frequencies.get(frequencies.size() - 1) + 1);
}

结果将是:

integers [2, 0, 2, 0, 2]
frequency [3, 4, 2, 2, 1]

答案 3 :(得分:-2)

for中,您应该进行i < bytes.size()
我会详细说明:您只在最后一个元素之前运行,所以如果最后一个元素不同,那么您会错过他。

 for (int i=0; i < bytes.size(); i++) {
     Byte current = bytes.get(i);
     // If the last byte is a single byte - then it is added with current byte and count = 1, which reseted in the previous step
     // If it is consecutive value the count is correct from the increase in the previous step
     if (i == bytes.size() - 1) {
         integers.add(current);
         frequencies.add(count);
     } else {
       Byte next = bytes.get(i+1);
       if (current == next) {
         count++;
       } else {
         integers.add(current);
         frequencies.add(count);
         count = 1;
       }
     }
 }