从另一个列表的连续元素动态创建新列表

时间:2013-10-24 02:02:47

标签: java

我正在研究一个问题,我有一个输入整数列表,如{0,3,6,9,12,18,21,24,27,33,39}。我需要通过分析原始列表来创建一个新列表,这样如果我找到一个3的倍数序列,那么该序列的第一个元素和最后一个元素都将被添加到该列表中。将不添加该序列的第一个和最后一个元素之间的元素。任何其他元素(没有连续的3的倍数)将被添加。因此,对于{0,3,6,9,12,18,24,27,30,39,45}的输入列表,我的输出应为[0,12,18,24,30,39,45]。请注意,我的第一个3的倍数序列是0,3,6,9,12;所以根据我的要求,新列表有0,12。由于18没有任何一方在任何一方有3的差异,所以它是这样添加的。同样,24,27,30被添加为24,30。此外,类似于18,39和45这样添加。以下是我的代码段:

int difference = 3;  
public static List<Integer> parseList(List<Integer> input, int difference) {
    List<Integer> output = new ArrayList<Integer> ();
    for (int i = 0; i < input.size()-1; i++) {
        // Check if subsequent element values differ by specific difference
        if ( (input.get(i+1) - input.get(i)) == difference) {
            output.add(input.get(i));
            output.add(input.get(i+1));

        }
        else {
            output.add(input.get(i));
        }

    }
    return output;
}

我的结果是:0 3 3 6 6 9 9 12 12 18 24 27 27 30 30 39 我的预期输出再次是:[0,12,18,24,30,39,45] 请注意,我不仅获得中间重复值,我也缺少最后一个值(即45)。

4 个答案:

答案 0 :(得分:1)

for (int i = 0; i < input.size()-1; i++)

这会导致您错过列表中的最后一个元素。

因此你应该在循环之后添加最后一个元素(因为最后一个元素应该总是出现在输出中)。

以下内容:

if ( (input.get(i+1) - input.get(i)) == difference) {
            output.add(input.get(i));
            output.add(input.get(i+1));

会导致重复的条目,因为每当遇到几个相差3的元素时,都会输入两个元素。

相反,当您发现差异为3时,您应该将某个标志设置为true,否则将其设置为false。只要标志为true,就不要将元素放在输出列表中。

我相信这样的事情可以解决问题:

public static List<Integer> parseList(List<Integer> input, int difference) {
    List<Integer> output = new ArrayList<Integer> ();
    boolean isSeq = false;
    for (int i = 0; i < input.size()-1; i++) {
        if ((input.get(i+1) - input.get(i)) == difference) {
            // add start of a sequence 
            if (!isSeq) {
                output.add(input.get(i));
                isSeq = true;
            }
        }
        else {
            isSeq = false;
            output.add(input.get(i));
        }

    }
    output.add(input.get(input.size()-1));
    return output;
}

答案 1 :(得分:1)

正如另一篇文章所述,你没有得到列表的最后一个元素,因为你的for循环终止于输入列表的倒数第二个元素。但是,如果您只调整for循环的结束条件,最终会得到IndexOutOfBoundsException,因为您的算法会在每个循环中检查i+1

我认为从索引1开始并简单地向后看数组就更简单了。根据您对问题的描述,我了解您将始终使用列表的第一个元素,因此我们可以从一开始就插入它(但这意味着您需要确保输入列表至少包含一个元素):< / p>

public static List<Integer> parseList(List<Integer> input, int difference) {
    List<Integer> output = new ArrayList<Integer> ();
    if (input.size() > 0) {
        // always use first element
        int indexToAdd = -1;
        output.add(input.get(0));
        for (int i = 1; i < input.size(); i++) {
            if ( (input.get(i) - input.get(i-1)) == difference) {
                if (i == input.size()-1) {
                    output.add(input.get(i));               
                }
                else { 
                    indexToAdd = i;
                }
            }
            else {
                if(indexToAdd != -1) {
                    output.add(input.get(indexToAdd));
                    indexToAdd = -1;
                }
                output.add(input.get(i));
            }
        }
    }
    return output;
}

答案 2 :(得分:1)

代码中的方法 parseList 不正确。这个方法有两个问题。 1.只要相邻数字相差3,就会添加数字。在这种情况下,当连续发生差异时,您将添加重复的数字。 例如,0,3,6,9,12 步骤1。当i = 0时,条件'相邻数字相差3'满足,将0和3加到输出列表中。 步骤#2当i = 1时,条件'相邻数字相差3'满足,yop将3和6加到输出列表中,看看是什么?重复的值被添加。对于索引i = 1 您在步骤#1和步骤#2 中将数字添加到输出列表。 这就是你输出列表中有重复数字的原因,例如0,3,3,6 ......

<强> 2。 parseList方法中的另一个问题是最后一个数字没有被处理,当最后两个数字没有相差3时会被忽略。这就是你无法在输出列表中看到它的原因。

您可以添加变量以检查是否发生连续数字,并添加逻辑以处理最后一个数字。

以下代码示例可以帮助您解决此问题。

enter image description here

答案 3 :(得分:1)

我花了一段时间来弄明白......然而,另一种编码方式是:

ArrayList<Integer> output = new ArrayList<Integer>();

int i = 0;
while (i < input.size()) {
    int start = input.get(i);
    output.add(start);
    int end = -1;
    int x = i+1;        

    while (x < input.size()) {
        if (input.get(x++) - input.get(i++) != 3) {
            end = input.get(i-1);
            break;
        }
    }           
    if (end > 0 && end != start) {
        output.add(end);
    }
    if (start == input.get(i)) break;
}
return output;