4

我正在尝试遍历一个数组列表并每隔 3 个索引逐渐删除一个元素。一旦它到达数组列表的末尾,我想将索引重置回开头,然后再次遍历数组列表,再次每 3 个索引删除一个元素,直到数组列表中只剩下一个元素。

listOfWords 是一个长度为 3 的数组,之前已填充。

int listIndex = 0;

do
{           
    // just to display contents of arraylist    
    System.out.println(listOfPlayers);

    for(int wordIndex = 0; wordIndex < listOfWords.length; wordIndex++
    {
        System.out.print("Player");
        System.out.print(listOfPlayers.get(wordIndex));
        System.out.println("");
        listIndex = wordIndex;                                  
    }           

    listOfPlayers.remove(listOfPlayers.get(listIndex)); 
}
while(listOfPlayers.size() > 1);

我已经尝试实施了几个小时,但我仍然遇到问题。数组列表的元素会发生以下情况:

1, 2, 3, 4

1, 2, 4

1, 2

然后它在检查第三个元素(不再存在)时抛出“索引越界错误”异常。一旦它到达最后一个元素,我希望它环绕到第一个元素并继续遍历数组。我还希望它从停止的地方开始,而不是从数组列表中删除元素后从头开始。

4

7 回答 7

3

也许我刚刚错过了船,但这就是你想要的吗?

import java.util.ArrayList;
import java.util.Random;

public class Test {

    public static void main(String[] args) {

        ArrayList<Integer> numbers = new ArrayList<Integer>();
        Random r = new Random();

        //Populate array with ten random elements
        for(int i = 0 ; i < 4; i++){
            numbers.add(r.nextInt());
        }

        while(numbers.size() > 1){
            for(int i = 0; i < numbers.size();i++){
                if(i%3 == 0){//Every 3rd element should be true
                    numbers.remove(i);
                }
            }
        }
    }
}
于 2013-05-17T03:02:58.380 回答
1

您可以将每隔三个元素移动到一个临时列表中,然后List#removeAll(Collection)在完成每个循环时使用它来删除这些项目......直到主列表为空......

于 2013-01-13T02:47:32.297 回答
1

让我们备份并从算法上看问题。

  • 从第一个项目开始并开始计数。
  • 转到下一项并增加您的计数。如果没有下一项,则转到开头。
  • 如果计数为“3”,则删除该项目并重置计数。(或模数。)
  • 如果列表中还剩下一项,请停止。

让我们编写伪代码:

function (takes a list)
  remember what index in that list we're at
  remember whether this is the item we want to delete.

  loop until the list is size 1
    increment the item we're looking at.
    increment the delete count we're on

    should we delete?
      if so, delete!
      reset delete count

    are we at the end of the list?
      if so, reset our index

以这种方式来看,很容易将其立即转换为代码:

public void doIt(List<String> arrayList) {
  int index = 0;
  int count = 0;

  while(arrayList.size() != 1) {
    index = index + 1;
    count = count + 1; //increment count

    String word = arrayList.get(index);//get next item, and do stuff with it

    if (count == 3) {
      //note that the [Java API][1] allows you to remove by index
      arrayList.remove(index - 1);//otherwise you'll get an off-by-one error
      count = 0; //reset count
    }

    if (index = arrayList.size()) {
      index = 0; //reset index
    }
  } 
}

因此,您可以看到诀窍是逐步思考您在做什么,然后慢慢将其转化为代码。我认为您可能已经陷入了修复最初尝试的问题:永远不要害怕将代码扔掉。

于 2013-01-13T02:48:07.037 回答
1

试试下面的代码。它不断删除其中的每个nth元素,List直到留下一个元素。

    List<Integer> array = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
    int nth = 3;
    int step = nth - 1;
    int benchmark = 0;

    while (array.size() > 1) {
        benchmark += step;
        benchmark = benchmark > array.size() - 1 ? benchmark % array.size() : benchmark;
        System.out.println(benchmark);
        array.remove(array.get(benchmark));
        System.out.println(array);
    }
于 2017-12-06T11:04:57.050 回答
0

您可以使用一个int k不断递增 3 的计数器,例如k += 3. 但是,在使用该计数器作为索引来排除任何数组元素之前,请检查您是否已经超出,如果是,请从您的计数器中减去该数组的长度k。还要确保,break一旦你发现数组只剩下一个元素,就退出你的循环。

int k = -1;
int sz = list.length;
while (sz > 1)
{
    k += 3;
    if (k >= sz)
    {
        k -= sz;
    }
    list.remove(k);
    sz --;
}

这个例子表明你已经知道你将多久驱逐一个元素,即sz - 1次数。

顺便说一句,sz % 3只有三个可能的结果,0、1、2。用一张纸和一杯咖啡,您可以根据它找出幸存的元素是什么,根本不需要运行任何循环!

于 2013-01-13T02:35:11.567 回答
0

您可以尝试使用迭代器。已经很晚了,所以不要期望太多。

public removeThirdIndex( listOfWords ) {
    Iterator iterator = listOfWords.iterator
    while( iterator.hasNext() ){
        iterator.next();
        iterator.next();
        iterator.next();
        iterator.remove();
    }
}


@Test
public void tester(){
    // JUnit test > main
    List listOfWords = ... // Add a collection data structure with "words"

    while( listOfWords.size() < 3 ) {
        removeThirdIndex( listOfWords ); // collections are mutable ;(
    }

    assertTrue( listOfWords.size() < 3 );
}
于 2013-01-13T09:48:01.073 回答
0

我只需将删除的设置为空,然后在内循环中跳过空值。

boolean continue;
do {
   continue = false;
   for( int i = 2; i < list.length; i += 3 ){
      while( list.item(i++) == null &&  i < list.length );
      Sout("Player " + list.item(--i) );
      continue = true;
   }
} while (continue);

我会选择这个而不是不合理的数组改组。

( i++ 和 --i 可能看起来很难看,可能会很好地重写。)

于 2013-01-13T12:36:54.950 回答