【问题标题】:sorting an array and keep the index [duplicate]对数组进行排序并保留索引[重复]
【发布时间】:2017-04-28 00:37:57
【问题描述】:

使用Arrays.sort( array ); 是一种对数组进行排序的非常简单的方法。但有一个问题。对于每个未排序的数组,都有一个索引指向其他数据结构中的对象。对数组进行排序(使用上述代码或任何其他类似方式)时,每个值的索引都会更改。有没有为每个值分配索引的解决方案?

编辑

使用HashMap<Key, Value> 不会有用,因为数组中有很多相同的值。

【问题讨论】:

  • 也许你需要一个<Key, Value> 数据结构?
  • @Thrasher 有很多相同的值,因此键的值将被覆盖。我的意思是,如果您指的是 HashMap。

标签: java arrays sorting indexof


【解决方案1】:

并行排序两个数据结构。

或者将引用索引(用来引用其他数据结构)作为每个元素的内部字段,这样即使元素的顺序被排序改变了,每个元素也能保持相同的“引用索引”。

或者更好的是,只需给每个元素一个内部字段,该字段只是另一个数据结构中元素的直接引用变量。 (除非您出于某种原因需要原始索引本身,而不仅仅是对关联对象/值的引用)

例如:this SO Q&A

【讨论】:

    【解决方案2】:

    首先,拥有两个具有相应索引元素的并行数组表示您可能希望将数据结构更改为单个数组,其中包含两个字段的容器对象。然后,此容器对象将实现 Comparable 接口。

    但是,坚持你所说的,一种方法可能是:

    /**
     * Sorts parallel arrays in-place.  Sorted by the first array and updating
     * all other arrays to match.
     * Uses the natural sorting of the objects.
     * All arrays must be the same length.
     *
     * @param  keys         the values used to sort, may be duplicate
     *
     * @param  otherArrays  the arrays to have reordered to match the sorting of
     *                      the keys array.
     *
     * @exception  IllegalArgumentException  if any of otherArrays have a length
     *                      different that the keys array.
     */
    public static <E extends Comparable<? super E>> void sortParallelArrays(
        E[] keys,
        Object[] ... otherArrays
    ) {
        int numKeys = keys.length;
        int numOtherArrays = otherArrays.length;
        for(Object[] otherArray : otherArrays) {
            if(otherArray.length != numKeys) {
                throw new IllegalArgumentException("Mismatched array lengths");
            }
        }
        // A list of all indexes per key
        // This also does the sorting within the TreeMap using natural ordering
        SortedMap<E, List<Integer>> originalIndexesByKey = new TreeMap<E, List<Integer>>();
    
        // Populate the map
        for(int i = 0; i < numKeys; i++) {
            E key = keys[i];
            List<Integer> originalIndexes = originalIndexesByKey.get(key);
            if(originalIndexes == null) {
                // Optimization for the non-duplicate keys
                originalIndexesByKey.put(key, Collections.singletonList(i));
            } else {
                if(originalIndexes.size() == 1) {
                    // Upgrade to ArrayList now that know have duplicate keys
                    originalIndexes = new ArrayList<Integer>(originalIndexes);
                    originalIndexesByKey.put(key, originalIndexes);
                }
                originalIndexes.add(i);
            }
        }
    
        // Store back to keys and sort other arrays in a single traversal
        Object[][] sortedOtherArrays = new Object[numOtherArrays][numKeys];
        int pos = 0;
        for(Map.Entry<E, List<Integer>> entry : originalIndexesByKey.entrySet()) {
            E key = entry.getKey();
            for(int index : entry.getValue()) {
                keys[pos] = key;
                for(int ooIndex = 0; ooIndex < numOtherArrays; ooIndex++) {
                    sortedOtherArrays[ooIndex][pos] = otherArrays[ooIndex][index];
                }
                pos++;
            }
        }
        assert pos == numKeys : "Arrays should be full";
    
        // Copy back to original arrays for in-place sort
        for(int ooIndex = 0; ooIndex < numOtherArrays; ooIndex++) {
            System.arraycopy(
                sortedOtherArrays[ooIndex], 0,
                otherArrays[ooIndex], 0,
                numKeys);
        }
    }
    

    这不是最节省内存的策略,但代码不多。

    时间复杂度还不错。看起来像 O((M+1)*N*log(N)),其中 M 是 otherArrays 的数量,N 是键的数量。至少没有疯狂的最坏情况问题。

    【讨论】:

      猜你喜欢
      • 2017-07-12
      • 1970-01-01
      • 2021-07-19
      • 1970-01-01
      • 2019-03-12
      • 1970-01-01
      • 1970-01-01
      • 2013-03-23
      • 2018-09-22
      相关资源
      最近更新 更多