运行-长度编码在java

Run-length encoding in java

如何以“nxw”形式打印出特定数字的编号以及数字本身。 n是数字的频率,w是数字本身。

因此,例如,如果用户的输入是 1 1 1。输出将是 3x1。

如果用户在第一行输入1 1 1,在第二行输入7 7 1 1 0。输出将为 3x1.2x7.2x1.1x0。没有空格。

注:

因此,例如,输入可以是第一行的 1 1 1 第二行的 7 7 1 1 0 ...等等

到目前为止,这是我的代码。但我知道这不是真的。

import java.util.*;

public class LaufLaengenKodierung {

public static void main(String[] args) {
        
    Scanner sc = new Scanner(System.in);
        
    int freq = 0;
    int oldNum = 0;
    int num = 0;
    boolean first = true;
        
    while(sc.hasNextInt()) {
            
        int i = sc.nextInt();
            
        if(i == oldNum) {
                
            freq++;
            num = i;
                
        } else if(i != oldNum) {
                
            freq = 1;
            oldNum = i;
            num = i;
                
            if(first) {
                    
                first = false;
                num = i;
                freq = 1;
                    
            }
        }
    }
        
    System.out.print(freq + "x" + num + ".");
    sc.close();
}
        
}

您必须保存每个数字的计数。您可以通过为数字 09 创建大小为 10 的 int 数组来实现。然后是一个简单的循环,比如

while(sc.hasNextInt()) {
        
    int i = sc.nextInt();
    
    countArray[i]++;
}

之后检查数组中的每个元素并输出数字的计数,当它大于 0 时。它可以是这样的:

for (int i=0; i<countArray.length; i++) {
    if (countArray[i] > 0) {
        System.out.printf("%dx%d.", countArray[i], i);
    }
}

请记住,您必须检查用户输入的数字是否在 0 到 9 的范围内,否则您 运行 进入 ArrayIndexOutOfBoundsExceptions。

现有代码需要稍微重构以在相同值的子序列结束时立即打印频率和整数值。

static void printRLE(String input) {
    Scanner sc = new Scanner(input);
    int freq = 0;
    int oldNum = 0;
    boolean first = true;
        
    while(sc.hasNextInt()) {
            
        int i = sc.nextInt();
        
        if (i != oldNum || first) {
            if (first)
                first = false;
            else // integer value changed
                System.out.printf("%dx%d.", freq, oldNum);
            oldNum = i;
            freq = 1;
        } else {
            freq++;
        }
    }
    if (!first)    
        System.out.printf("%dx%d.%n", freq, oldNum);
    else 
        System.out.println("No integer found"); // or print 0x0 if it's correct
    sc.close();    
}

测试:

String[] tests = {
    "",
    "abc.",
    "11 11 11",
    "1 1 1\n7 7 1 1 0",
    "0 0 0",
};    

for (String test: tests) {
    System.out.println("test=[" + test + "]");
    printRLE(test);
    System.out.println("--------");
}

输出:

test=[]
No integer found
--------
test=[abc.]
No integer found
--------
test=[11 11 11]
3x11.
--------
test=[1 1 1
7 7 1 1 0]
3x1.2x7.2x1.1x0.
--------
test=[0 0 0]
3x0.
--------

更新 如果单独的数字只需要计算(而不是整数),例如输入 11 11 11 应转换为 6x1. 而不是如上所示的 3x11. ,应重构该方法以处理数字内的数字:

static void printRLEDigits(String input) {
    Scanner sc = new Scanner(input);
    int freq = 0;
    int oldNum = 0;
    boolean first = true;
        
    out: while(sc.hasNext()) {
            
        String s = sc.next(); // getting "number" delimited with whitespaces
        for (char c: s.toCharArray()) {
            if (!Character.isDigit(c)) {
                break out;
            }
            int i = c - '0';
            if (i != oldNum || first) {
                if (first)
                    first = false;
                else // digit changed
                    System.out.printf("%dx%d.", freq, oldNum);
                oldNum = i;
                freq = 1;
            } else {
                freq++;
            }
        }
    }
    if (!first)    
        System.out.printf("%dx%d.%n", freq, oldNum);
    else 
        System.out.println("No integer found");
    sc.close();    
}

测试输出:"11 11 11", "112 223", "1 1 1\n7 7 1 1 0", "0 0 0"

test=[11 11 11]
6x1.
--------
test=[112 223]
2x1.3x2.1x3.
--------
test=[1 1 1
7 7 1 1 0]
3x1.2x7.2x1.1x0.
--------
test=[0 0 0]
3x0.
--------

Online demo of both methods printRLE and printRLEDigits