【问题标题】:Converting Primitive int array to list将原始 int 数组转换为列表
【发布时间】:2011-09-23 14:35:34
【问题描述】:

我正在尝试解决以下问题。有两个大小为 n 的数组 A 和大小为 n+1 的 B。 A 和 B 的所有元素都相同。 B 有一个额外的元素。找到元素。

我的逻辑是将数组转换为列表并检查 B 中的每个元素是否存在于 A 中。

但是当我使用原始数组时,我的逻辑不起作用。如果我正在使用

Integer [] a ={1,4,2,3,6,5};
Integer [] b = {2,4,1,3,5,6,7};

我的代码运行良好。

public static void main(String [] args)
{
    int [] a ={1,4,2,3,6,5};
    int [] b = {2,4,1,3,5,6,7};     
    List<Integer> l1 = new ArrayList(Arrays.asList(a));
    List<Integer> l2 = new ArrayList(Arrays.asList(b));
    for(Integer i :l2)
    {
        if(!l1.contains(i))
        {
            System.out.println(i);
        }           
    }
}

而且我的逻辑是 O(n+1)。有没有更好的算法。

谢谢

【问题讨论】:

  • 您的逻辑是 n*m,基本上是平方 (n^2),因为对于您在第二个数组中搜索的数组的每个元素,在字典/地图搜索的情况下它会更快,但在您的列表的情况是 n^2

标签: java algorithm


【解决方案1】:

它不适用于原始数组的原因是 Arrays.asList 当给定一个 int[ ] 时返回一个 List 而不是 List

GuavaInts 类中有一个答案。 Is 有一个 asList 方法,该方法将采用 int[ ] 并返回一个 List

更新

int[] a = ...;
int[] b = ...;
List<Integer> aList = Ints.asList(a);
List<Integer> bList = Ints.asList(b);

以上将允许您的代码在 int[ ] 上正常工作,因为它适用于 Integer[ ]。

查看Ints API

【讨论】:

  • 我将代码修改为 List l1 = new ArrayList(Arrays.asList(a)); List l2 = new ArrayList(Arrays.asList(b)); for(Integer[] i :l2) { if(!l1.contains(i[0].intValue())) { System.out.println(i); } }
  • 已更新。请注意,我使用的是 Ints.asList 而不是 Arrays.asList。这是一个 Guava 库函数,因此您需要包含 guava jar。
  • 很好的发现。我过去用过这个,我花了很长时间才再次找到它。请记住,所有相应的类中都有类似的方法 - Longs、Floats、Doubles 等。
  • 太棒了!这就是我一直在寻找的。 :) 谢谢。
【解决方案2】:

计算每个数组的总和。 Sum(B) - Sum(A) 将为您提供 B 中的额外元素。

【讨论】:

  • 不错。这假设只有一个元素是不同的。但如果是这样的话,它工作得很好并且确实是 O(n)
  • 适用于整数和长整数,不一定适用于布尔、双精度、浮点数
  • @MatthewFarwell 布尔值也可以,无论是在“+ 是异或”解释还是“真为 1”解释中
【解决方案3】:

ArrayList 的 contains 方法实际上效率不高。这一个人的运行时间是 O(n),所以你的算法的运行时间是 O(n^2)。

我建议将一个数组放入 HashSet(包含 O(1) 的运行时)。您可以将另一个数组保持原样并直接遍历该数组。那么你的运行时间是 O(n)。

更新: 来自HashSet API doc

假设哈希函数将元素正确地分散在桶中,此类为基本操作(添加、删除、包含和大小)提供恒定的时间性能。

我认为默认的整数哈希函数可以满足要求。

【讨论】:

  • 真的是 O(n) 吗?由于 HashMaps conatins 方法不完全是 O(n)。 O-ness 取决于元素的数量与桶的数量。
  • @John B :我相信由于数组具有不同的值,因此不会创建存储桶
  • @venje 不一定正确。根据 equals / hashCode 合约,不同的值可能具有相同的 hashCode。虽然每个 int 值都有一个唯一的 hashCode(因为 hashCode)返回 int 可能是一个安全的假设,但对于 long 之类的东西来说这是不正确的,我认为这不是一个安全的假设。话虽如此,我不知道 O 因素真的是这里的问题。 :)
【解决方案4】:

只是为了兴趣,因为数组连接操作会有点复杂,但另一个操作需要O(n)

  1. 将两个数组放到一个数组中
  2. XOR物品
  3. 所有相同的项目将被自行删除,单个元素将是最后一个。

【讨论】:

    【解决方案5】:

    构造一个Set&lt;Integer&gt; 对象。既然一个Set不能有重复的元素,把A全部加起来,然后你就可以用Add函数在B中找到一个返回true的条目。很好,很简单。

    【讨论】:

      【解决方案6】:

      最快的方法是使用int[],使用Arrays.sort 并合并结果。我怀疑这是作业,所以我将把实际的解决方案留给自己。这是 O(n * log(n)) 但常数低于使用包装对象和集合。

      如果您知道值的范围是有限的,则可以使用 BitSet。这将检测到多个差异并且仍然是 O(n)

      如果您知道只有一个差异,请按照@rossum 的建议比较总和。

      【讨论】:

        【解决方案7】:

        您可以从您的两个数组中构造两个Set&lt;Integer&gt; 对象,然后使用removeAll() 查找额外的元素。

        附:你的方法不像你想象的那样O(n)。对于整个方法为O(n),循环的每次迭代都必须在恒定时间内执行;我把它作为一个练习让读者弄清楚是否是这种情况。

        【讨论】:

        • 那么 O 是什么?我在想 O(n^2) (n-squared)
        • @aix 我认为我的算法是 O(n)。因为我正在遍历 B 的所有元素一次。当它完成时,我们就完成了。我错了吗?
        • int [] a ={1,4,2,3,6,5}; int [] b = {2,4,1,3,5,6,7}; Set s1= new HashSet(); Set s2 = new HashSet(); s1.add(a); s2.add(b); s2.removeAll(s1);对象[] c = s2.toArray(); System.out.println(c[0]);
        • @ravi 它可能是 O(n^2),因为 contains() 本身可能是 O(n),例如如果使用 ArrayList
        【解决方案8】:

        仅适用于那些感兴趣的人,这是 rossum 逻辑的典型解决方案。但是如果我们有大数字,那么可能会出现一些溢出问题。

        算法很简单,我们从 w 零值开始,从一个数组中减去另一个数组,然后添加元素,最后添加 n+1 元素。

        这将在 O(n) 中工作(n 为 n+1)

        我假设数组 b 有更多元素。

        long result = 0;
        
        for(int i =0; i < a.length; i++) {
            result -= a[i];
            result += b[i];
        }
        
        result += b[a.length];
        

        在结果中,我们有所不同。

        编辑:

        harold 提出了更好的解决方案,我们无需担心内存问题。

        int result = 0;
        
        for(int i =0; i < a.length; i++) {
            result ^= a[i] ^ b[i];
        }
        
        result ^= b[a.length];
        

        【讨论】:

        • 溢出没关系,结果还是正确的——或者你可以用异或没有溢出
        【解决方案9】:

        如果要转换一个 int 数组(不是 Integer),请使用 IntStream:

        int[] arr = {15, 13, 7, 4, 1, 5, 19, 18, 7, 7, 12, 15};
        List<Integer> arrayList = IntStream.of(arr).boxed().collect(Collectors.toList());
        System.out.println(arrayList);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-01-27
          • 2013-06-19
          • 1970-01-01
          • 2013-08-25
          • 2010-10-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多