ArrayList:查找第n次出现的整数

时间:2015-09-08 15:01:27

标签: java arraylist sublist

在ArrayList中找到第n个数字的最佳方法是什么?

我已经知道了什么?

  1. 要查找lastIndexOf数字,List接口中有方法,该方法在ArrayList类中实现。
  2. 要找到第一次出现,有indexOf方法。
  3. 我在解决什么问题?

    在一个问题中,有一个包含不同数字的列表,我必须返回两个数字的索引,其总和等于目标数字。 例如:List = (1,2,1) & target = 2; 现在1 + 1 =2和答案将是前1和后1的索引。

      

    注意:我已经解决了这个问题&我需要回答这个问题   顶端。 Check Solution

    我做了什么?

      public static void main(String[] args)
      {
        List<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(2);
        list.add(1);
        int length = list.size();
        int firstIndex = list.indexOf(1) + 1;
        int secondIndex = firstIndex + list.subList(firstIndex, length).indexOf(1) + 1;
        System.out.println(firstIndex);
        System.out.println(secondIndex);
      }
    

7 个答案:

答案 0 :(得分:2)

&#34;一个包含所有相同数字的列表&#34; - &GT; {N,N,...,N,N}。

&#34;我必须返回前两个数字的索引,其总和等于目标数字&#34;我们假设target = x。 由于您的列表中的数字相等,如果x / 2 = n,则索引ll为0和1,如果x / 2!= n,则不会有任何匹配

问题版之后

    int length=10;
    int target=100;
    int[] tab1= new int[length];
    Object[] tab2= new Object[length];
    Object[] tab2Sorted= new Object[length];

    for (int i = 0; i < tab2Sorted.length; i++) {
        for (int j = i; j < tab2Sorted.length; j++) {
            if(tab2Sorted[i]+tab2Sorted[j]==target){
                //do what you want on objects to get back indexes
            }

        }
        //As tab3 is sorted you dont have to read all the array
        if(tab2Sorted[i]>target/2){
            break;
        }
    }

您只需将tab2和tab2Sorted类型从Object更改为自定义类型,从第一个选项卡中保存int及其索引

答案 1 :(得分:1)

假设你的列表不是一个列表,而是一个数组(一旦你完成插入这些东西,一个arraylist基本上就是一个数组)。

假设你并不想找到总和为X的前两个num的索引,而只想找到两个nums(如果有的话)。

有一个简单的解决方案需要花费O(n ^ 2)的时间,你可以用它后面的所有数字迭代每个数字,并检查总和。

更好的方法是对数组进行排序(采用O(n * logn))。现在,您可以为每个数字在数组中进行二进制搜索以获得其补码,即,如果求和,则数字将导致X.这需要n(每个数字)* log n(二进制搜索其补码)

但我们无法排序,因为我们想要索引!或者我们不能吗?

如果我们创建一个数组的副本,而不仅仅是值,则存储一对值+ originalPosition:

class PosAndValue {
  public final int value;
  public final int pos;
  public PosAndValue(int v, int p) {
    value = v;
    pos = p;
  }
} 

我们现在可以通过它的值对这些PosAndValue的数组进行排序,执行刚刚提到的算法,然后检索原始位置(即索引),所有这些都在n * logn时间复杂度(和n空间复杂度)中。

我非常有信心,就复杂性而言,你可以做得更快,更快。#34;请注意,这并不意味着代码在任何情况下都会更快,而是对于足够大的输入(即&#34;足够大的&#34;数组),它将是!对于小输入,作为你的例子,所有这些开销实际上可能使代码变慢!

如果您知道输入的范围有限,然后在值上做一个布尔位图O(n),你可以做得更好,但这是一个未指定的约束!

答案 2 :(得分:1)

你可以建立这样的东西

List<Integer> numbers = new ArrayList<>(); // your list of numbers. Let's say it's {1, 1, 4, 5, 4}
numbers.add(1);
numbers.add(1);
numbers.add(4);
numbers.add(5);
numbers.add(4);
SparseArray<Set<Integer>> occurrences = new SparseArray<>();
for (int i = 0; i < numbers.size(); i++) {
    if (occurrences.indexOfKey(numbers.get(i)) < 0) {
        occurrences.put(numbers.get(i), new HashSet<Integer>());
    }
    Set<Integer> ints = occurrences.get(numbers.get(i)); // get current set
    ints.add(i); // add your new found one
    occurrences.put(numbers.get(i), ints); // put it back into your occurrences set
}

然后会给你一个原始数字的SparseArray和这些数字的集合,从你原来的arraylist中出现索引。

{1=[1, 0], 4=[4, 2], 5=[3]}

答案 3 :(得分:1)

这应该是最有效的。它使用数组的排序版本(保持对原始偏移的引用)和Collections.binarySearch,它应该提供最佳性能。

private Integer[] addsUp(List<Integer> numbers, int value) {
    // Hold the value and it's original offset.
    class No implements Comparable<No> {

        final int n;
        final int o;

        public No(int n, int o) {
            this.n = n;
            this.o = o;
        }

        public No(int n) {
            this(n, -1);
        }

        @Override
        public int compareTo(No o) {
            return Integer.compare(n, o.n);
        }

        @Override
        public String toString() {
            return "{" + n + " @ " + o + "}";
        }
    };
    // Build my list.
    List<No> myNumbers = new ArrayList(numbers.size());
    for (int i = 0; i < numbers.size(); i++) {
        myNumbers.add(new No(numbers.get(i), i));
    }
    // Start sorted.
    Collections.sort(myNumbers);
    // Upper limit of my search.
    int max;
    // Find the value in the numbers.
    No no = new No(value);
    int spot = Collections.binarySearch(myNumbers, no);
    // Did we find it?
    if (spot < 0) {
        // Not found - but this number is nearest to value.
        max = -spot - 1;
    } else {
        // Found ! No number higher than that is relevant.
        max = spot;
    }
    // For each start number.
    for (int first = 0; first < max; first++) {
        No remainder = new No(value - myNumbers.get(first).n);
        // Does that number appear in the list.
        int second = Collections.binarySearch(myNumbers, remainder);
        if (second >= 0) {
            // Found second number! Return original offsets.
            return new Integer[]{myNumbers.get(first).o, myNumbers.get(second).o};
        }
    }
    return null;
}

public void test() {
    List<Integer> numbers = Arrays.asList(1, 2, 1);
    Integer[] two = addsUp(numbers, 2);
    System.out.println("two = " + Arrays.toString(two));
    Integer[] three = addsUp(numbers, 3);
    System.out.println("three = " + Arrays.toString(three));
}

答案 4 :(得分:0)

对于标题中的问题,您可以将一个循环与List的子列表方法一起使用:

public static void main(String[] args)
{
    List<Integer> list = new ArrayList<Integer>();
    list.add(1);
    list.add(1);
    list.add(1);

    int n = 2;
    int index = -1;
    List<Integer> subList = list;

    for( int i = 0; i < n; i++)
    {
        index = subList.indexOf( 1);

        if( index == -1)
            break;

        System.out.println( i + "th index: " + index);
        subList = subList.subList( index+1, subList.size());
    }
}

对于真正的问题,找到列表中数字的第n个出现并不是一种可行的方法,你假设重复的数组元素是目标数的除数。

答案 5 :(得分:0)

public static int nthIndexOf(List<Integer> list, int needle, int n){
    for (int i = 0; i < list.size(); i++) {
        if (list.get(i) == needle) {
            n--;
            if (n == 0) {
                return i;
            }
        }
    }
    return -1;
}

支持Jon Skeet

答案 6 :(得分:0)

  public static void main(String[] args)
  {
    Integer[] numbersList = {1,2,3,4,5,6,7,8,9,10}; //Load your Array here
    List<Integer> list = Arrays.asList(numbersList);
    int targetNumber = 8;  //Load your targetNumber here

    int currrentVal = 0;
    int nextVal = 0;
    int i = 0;
    int j = 0;
    boolean found = false;
    for(i=0;i<list.size();i++) {
        currrentVal = list.get(i);          
        for(j=currrentVal+1;j<list.size();j++) {
            nextVal = list.get(j);              
            if(targetNumber == currrentVal+nextVal) {
                found = true;
                break;
            }
        }
        if(found) {
            break;
        }
    }
    if(found) {
        System.out.println("firstIndex  : "+i);
        System.out.println("secondIndex : "+j);
    } else {
        System.out.println(" No match found");
    }
  }