【问题标题】:Find the largest unduplicated number in an ArrayList [closed]在 ArrayList 中查找最大的不重复数 [关闭]
【发布时间】:2015-01-17 04:43:30
【问题描述】:

我需要一个算法来找到在ArrayList 中只出现一次的最大数字。

例如,假设我有一个带有元素的ArrayList<Integer>

[3, 3, 3, 6, 7, 8, 8, 9, 9, 9].

在这里,我需要的算法将产生数字7,因为它是列表中最大的不重复数字。

前提条件:

  • 输入列表保证排序。

  • 输入列表始终包含至少一个非重复数字。

【问题讨论】:

  • 输入列表总是排序的吗?如果列表完全由重复的元素组成,即[1,1,1,2,2,2],返回应该是什么?
  • 输入列表并不总是排序的。它总是至少有一个不重复的数字。
  • 使用Map,其中键是列表元素,值是它被看到的次数。

标签: java algorithm sorting for-loop compare


【解决方案1】:

如果我们假设输入列表已排序,我们应该能够在O(N) 中执行此操作,而无需额外的空间。

public static Integer maxUnduplicatedVal(ArrayList<Integer> lst){
    if(lst == null || lst.isEmpty()) 
        return null;
    if(lst.size() == 1) return lst.get(0);

    if(! lst.get(lst.size() - 1).equals(lst.get(lst.size() - 2))) 
        return lst.get(lst.size() - 1);

    for(int i = lst.size() - 2; i > 0; i--){
        Integer next = lst.get(i + 1);
        Integer here = lst.get(i);
        Integer prev = lst.get(i - 1);
        if(! next.equals(here) && ! prev.equals(here)) return here;
    }

    if(! lst.get(0).equals(lst.get(1))) return lst.get(0);
    return null; //All duplicates
}

如果不总是排序,最快的方法是创建列表的副本,然后删除重复项,然后调用Collections 中的max 函数。制作副本是一个非常好的主意 - getter 真的不应该更改他们收到的集合。 (这包括对给定集合进行排序)。

private static List<Integer> getUniques(List<Integer> list) {
    HashMap<Integer, Boolean> flagMap = new HashMap<>();

    //Total Loop: O(N)
    for(Integer i : list){
        if(flagMap.containsKey(i)) flagMap.put(i, false); //O(1)
        else flagMap.put(i, true); //O(1)
    }

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

    //Total Loop: O(N)
    for(Integer i : list){
        if(flagMap.get(i)) result.add(i); //O(1)
    }
    return result;
}

public static Integer maxUnduplicatedVal(ArrayList<Integer> lst){
    List<Integer> lstCopy = getUniques(lst);
    return Collections.max(lstCopy);
}

这仍然是O(N),但需要一些额外的空间。

【讨论】:

  • 即使 i+1 是 i 的副本,您的初始代码也会打印 left(i-1) 不相同的元素。基本上,如果数组有超过 1 个不同的数字,它总是会打印最大数字。
  • 啊哈,好收获。正在修复...
  • 据我所知,如果不使用 O(n) 额外空间,除非对它们进行排序,否则无法在 O(n) 中完成此类问题
  • 我相信我已经修复了它,现在应该可以工作了。
  • 我觉得我已经涵盖了所有内容。 1 - 不同的最大值是最后一个元素,2 - 不同的最大值是第一个元素,3 - 不同的元素在中间(在 [1 ... size - 2] 之间,4 - 没有不同的最大值。我还缺少什么?
【解决方案2】:

Collections.frequency 可能在这里有用...

    Integer[] myArr = {3, 3, 3, 6, 7, 8, 8, 9, 9, 9}; // sample array
    ArrayList<Integer> myList = new ArrayList<Integer>(Arrays.asList( myArr ) );

    // creating a set from an ArrayList will remove any duplicate elements
    HashSet<Integer> mySet = new HashSet<Integer>(myList);

    /* Make sure list isn't empty or null here, etc. */

    Integer largest = null;

    // iterate through the set, ensuring you don't examine duplicates
    for ( Integer i : mySet ) {

        // if the frequency of that element is 1, we can compare it
        if ( Collections.frequency(myList, i) == 1 )
        {
            if ( largest == null )
            {
                largest = i; // base case
            } else if ( i > largest ) {
                largest = i;
            }
        }
    }

    System.out.println( "The largest non-duplicate is " + largest );
    // or return, etc.

【讨论】:

    【解决方案3】:

    这是算法

    1) 如果列表尚未排序,则首先执行 Collections.sort(list)

    2)从最后一个开始,因为它是最大的数字,并得到它的索引

    3)检查该索引处的数字是否等于索引1处的数字,如果是,则它是最大的重复数字,否则对索引1重复此步骤

    【讨论】:

      【解决方案4】:

      最好的方法是在元素列表的排序数组中找到不重复的元素。因此,通过这样做,我们可以分离出不重复元素的列表,然后我们可以在获得的列表中找到最大的。

      建议参考以下链接了解更多详情。

      Find the unduplicated element in a sorted array

      -布鲁斯

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-06-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-20
        • 1970-01-01
        相关资源
        最近更新 更多