对混合整数和字符串的 ArrayList 进行排序,同时保留字符串和整数的相对顺序

Posted

技术标签:

【中文标题】对混合整数和字符串的 ArrayList 进行排序,同时保留字符串和整数的相对顺序【英文标题】:Sorting an ArrayList of mixed integers and strings while preserving relative ordering of strings and integers 【发布时间】:2013-06-10 12:17:21 【问题描述】:

考虑下面给出的数组列表

unsortedList = 6,"ball",3,1,"apple","cat",4 

这需要排序

sortedList = 1,"apple",3,4,"ball","cat",6

按字母顺序对字符串进行排序。按升序对数字进行排序。但请注意以下条件:

无论在未排序列表中的何处存在整数,它都必须是已排序列表中的整数。 无论字符串在未排序列表中的何处,它都必须是已排序列表中的字符串。

请注意,在上面的例子中,所有的整数都按升序排序,所有的字符串都按升序排序,但整数和字符串的相对位置与之前没有变化。

【问题讨论】:

我很难弄清楚排序标准。 是什么让“苹果”> 1 和“球”> 4 ? @jterrace 什么都没有。他只想将整数保持在与未排序列表相同的位置(与字符串相同)。然后对整数与整数、字符串与字符串进行排序。 建议:将其拆分为 Integer/String 列表,对它们进行排序,然后根据原始列表中的类型将它们重新组合到新列表中(LinkedList#poll 很好)。跨度> 我明白了……必须保留数据类型顺序。 【参考方案1】:

这里的一个选项是执行以下操作:

创建一个包含原始列表中所有整数的新列表。 创建一个包含原始列表中所有字符串的新列表。 对每个列表进行排序。 遍历原始列表,执行以下操作: 如果元素存在整数,则从已排序的整数列表中写回下一个未写入的整数。 如果元素有字符串,则从已排序的字符串列表中写回下一个未写入的字符串。

这是非常有效的 - 你只需要做两种。这是它的一些代码:

public void relativeOrderSort(List<Object> list) 
    /* Create a list of just the integers and just the strings
     * from the original list.
     */
    List<Integer> intList = new ArrayList<Integer>();
    List<String> strList = new ArrayList<String>();
    for (Object obj: list) 
        if (obj instanceof Integer) 
            intList.add((Integer) obj);
         else if (obj instanceof String) 
            strList.add((String) obj);
         else 
            throw new IllegalArgumentException("List has a non-int, non-string member.");
        
    

    /* Sort the lists. */
    Collections.sort(intList);
    Collections.sort(strList);

    /* Merge the lists back together. */
    int intIndex = 0, strIndex = 0;
    for (int i = 0; i < list.size(); i++) 
        if (list.get(i) instanceof Integer) 
           list.set(i, intList.get(intIndex++));
         else 
           list.set(i, strList.get(strIndex++));
        
    

希望这会有所帮助!

【讨论】:

完美。在合并排序列表时,我错过了对原始列表的引用。 与输入/输出应该是数组的差异相同的解决方案被面试官称为“不是优雅的”。我想知道有人知道“优雅”的吗? 我会回答我的问题.... 可以使用修改后的 MergeSort。在这种情况下,您将不需要额外的 N 空间。 @AliakseiYatsau 合并排序的传统实现使用线性辅助存储空间在合并期间保存元素。从复杂性的角度来看,这会增加什么新东西吗? @templatetypedef 我不知道它在现实世界中是如何实现的。我有一个想法。这不是就地合并的想法,但至少可以在面试时做的事情是拥有辅助存储,但更小并且当它是全班次阵列时。 Alg 复杂度仍然是 NlogN,但它会增加额外的处理(移位)。我不认为它比原版更“优雅”,但说实话我已经没有“优雅”的想法......【参考方案2】:

伪代码:

Create a list of the indices pointing to integers (0,2,3,6 in your case - indxInt )
Sort the integers  (6,3,1,4 turns into 1,3,4,6)
Put them back at the locations given by the pointers:
  sorted(indxInt(0)) = 1;
  sorted(indxInt(1)) = 3;
  sorted(3) = 4; // indxInt(2) == 3
  sorted(6) = 6; // indxInt(3) == 6
Repeat for the strings

【讨论】:

以上是关于对混合整数和字符串的 ArrayList 进行排序,同时保留字符串和整数的相对顺序的主要内容,如果未能解决你的问题,请参考以下文章

如何对List集合中的对象进行排序?

如何按字典顺序对 ArrayList 进行排序?

使用与数组相同的算法对 ArrayList 进行排序

java - 如何对对象的arraylist进行排序?

对数字字符串的 ArrayList 进行排序

按长度对字符串的 ArrayList 进行排序