如何用缺少的整数替换 ArrayList 中的重复整数

How can i replace duplicate integers in an ArrayList with the missing integers

我想用缺失的整数替换大小为 n 的 ArrayList 中的重复整数。例如:

import java.util.ArrayList;

public class Main {

  public static void main(String[] args) {

    ArrayList<Integer> myNumbers = new ArrayList<Integer>();
    myNumbers.add(1);
    myNumbers.add(2);
    myNumbers.add(1);
    myNumbers.add(3);
    myNumbers.add(1);
   
  }
}

arraylist 有 5 个元素,所以它应该包含数字 1 ,2 ,3 ,4, 5(不按特定顺序排列)。 (如果大小为99,则1到99之间应该没有重复的数字)。

它应该从 [1,2,1,3,1] 到 [1,2,4,3,5] 或 [1,2,5,3,4]。它必须适用于任何尺寸,并且可以有多个副本。

目前我只能使用集合去除重复项,但我不知道用缺失的元素替换它们。

  1. 先找出缺失值
  2. 遍历您的列表并检查当前值是否重复。如果 true 替换为缺失值之一

假设您使用的是 java 8 或更高版本,下面的内容可能是一个起点:

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Test {

    public static void main(String[] args) {
        List<Integer> myNumbers = new ArrayList<>();
        myNumbers.add(1);
        myNumbers.add(2);
        myNumbers.add(1);
        myNumbers.add(3);
        myNumbers.add(1);
        System.out.println("original: " + myNumbers);
        List<Integer> missing = IntStream.rangeClosed(1,myNumbers.size())
                .filter(i -> !myNumbers.contains(i))
                .boxed().collect(Collectors.toList());
        System.out.println("missing: " + missing);

        Set<Integer> unique = new HashSet<>();
        Iterator<Integer> misIterator = missing.iterator();
        for(int i = 0; i < myNumbers.size(); i++){
            if(!unique.add(myNumbers.get(i))){
                myNumbers.set(i, misIterator.next());
            }
        }
        System.out.println("modified" + myNumbers);
    }
}

这是我对question/problem语句的理解:

  • 您的输入是可能重复的数字 1 - n 的列表,其中 n 永远不会大于列表的大小。
  • 迭代列表时数字的第一个实例(非重复)应保留在其当前索引处。
  • 在迭代列表时发现的每个后续重复数字都应替换为“缺失集”中的数字。
  • “缺失集”包含所有数字 1 - n,其中 n 是删除了现有集(来自输入列表)的列表的大小。
  • 最终结果列表应该包含所有数字 1 - listSize,没有重复,并且任何数字的第一个实例(从列表的开头迭代时)留在与输入列表相同的索引处。

如果上面的陈述听起来正确,这是一种方法(尽管可能有更优化的方法):

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class ReplaceDuplicateIntegersRunner {
    private static ArrayList<Integer> sampleIntegerList = new ArrayList<>();

    public static void main(String[] args) {
        addRandomIntegersToList(3,7);
        System.out.println("List Before: " + sampleIntegerList);
        replaceDuplicatesWithContinuedCount();
        System.out.println("List After: " + sampleIntegerList);

    }

    public static void addRandomIntegersToList(Integer maxValue, Integer numOfIntegers) {
        Random randomGen = new Random();
        for (int num = 0; num < numOfIntegers; num++) {
            sampleIntegerList.add(1 + randomGen.nextInt(maxValue));
        }
    }

    public static void replaceDuplicatesWithContinuedCount() {
        // generate a set of integers 1 - length of sampleIntegerList
        Set<Integer> integerSetToAdd = IntStream.rangeClosed(1, sampleIntegerList.size())
                .boxed().collect(Collectors.toSet());
        // remove the integers which already exist in the target sample list
        integerSetToAdd.removeAll(new HashSet<>(sampleIntegerList));
        ArrayList<Integer> integersToReplaceDuplicates = new ArrayList<>();
        integersToReplaceDuplicates.addAll(integerSetToAdd);
        int indexOfIntegersToAdd = 0;
        HashSet<Integer> duplicatesInList = new HashSet<>();
        for (int index = 0; index < sampleIntegerList.size(); index++) {
            // if our duplicate set doesn't already have this number, we don't have a duplicate, add it to the set
            // and continue on
            Integer integerAtIndex = sampleIntegerList.get(index);
            if (duplicatesInList.contains(integerAtIndex) == false) {
                duplicatesInList.add(integerAtIndex);
            } else {
                // otherwise we've found a duplicate and need to replace it with the next one to replace
                sampleIntegerList.set(index, integersToReplaceDuplicates.get(indexOfIntegersToAdd));
                indexOfIntegersToAdd++;
            }
        }
    }
}

从上面传入的参数的一些示例输出:

List Before: [3, 2, 3, 3, 1, 1, 1] List After: [3, 2, 4, 5, 1, 6, 7]

List Before: [2, 3, 2, 2, 3, 2, 1] List After: [2, 3, 4, 5, 6, 7, 1]

如果您想获得一个数字序列不按特定顺序,您可以创建它并替换旧的:

List<Integer> list = IntStream
        // from 1 to 5 inclusive
        .rangeClosed(1, 5)
        // Stream<Integer>
        .boxed()
        .collect(Collectors.toList());

// random order
Collections.shuffle(list);

System.out.println(list); // [2, 4, 3, 1, 5]