【问题标题】:Sorting an array and retrieving the sorted index对数组进行排序并检索排序后的索引
【发布时间】:2019-12-23 20:17:44
【问题描述】:

我想按他的索引对数组进行排序。

看下面的代码:

var distances = [530, 0, 24, 335, 274, 591];

console.log(sortIndex(distances));

function sortIndex(toSort) {
  return toSort.map(
    (e,i) => {return {index: i, value: e};}
  ).sort(
    (a,b) => a.value - b.value
  ).map(
    (e,i) => {return e.index;},[]
  );
}

输出是:

[1, 2, 4, 3, 0, 5]

谁能告诉我如何降低这个 sn-p 的复杂性?这个算法是O(n^3),不知道你能不能用更好的方案解决同样的问题?

外面有人吗?谢谢。

【问题讨论】:

  • 该算法没有O(n^3) 复杂度。它具有O((n) + (n log n) + (n)) = O(n log n) 的复杂性。第一个mapO(n),排序是O(n log n),最后的映射是O(n)。当我们将这些步骤加在一起时,剩下的复杂度是n log n

标签: arrays algorithm sorting indexing time-complexity


【解决方案1】:

您可以通过创建数组的copy 和索引的hash 结构获得更好的性能,其中复杂度为O(N),因为我们只迭代数组一次。

var distances = [530, 0, 24, 335, 274, 591];
var copy = Object.assign([], distances);

var indexes = distances.reduce((hash, elem, i) => {
  hash[elem] = i;
  return hash;
}, {});

sortIndex = (toSort) => toSort.sort().map(el => indexes[el]);
console.log(sortIndex(copy));

所以,算法的最终复杂度是sort的复杂度加上map函数的复杂度。

对于sort,复杂度为Θ(n log(n))

对于map 方法,复杂性是O(n),因为您只通过callback 提供的函数 迭代数组一次以映射每个项目。

【讨论】:

  • 如果距离[] 有重复值,这会起作用吗?
  • @gihef,不幸的是,没有。对于重复值,您需要使用 indexOf 方法而不是创建哈希结构。
【解决方案2】:

我实际上正在考虑使用TreeMap 解决问题,该TreeMap 按升序保存键,并且可以将索引存储为键的值。这样,我们可以正确索引重复值,我想使用TreeMap 解决问题应该具有O(n log n) 复杂性。

这是我在 Java 中的工作代码。

import java.util.*;

public class HelloWorld {

     public static void main(String []args){
        int arr[] = {530, 0, 24, 335, 274, 591};

        int sortedIndexes[] = getSortedIndexes(arr);
        printSortedIndexes(sortedIndexes); 
     }

     public static void printSortedIndexes(int[] printArr) {
         for (int element : printArr) {
             System.out.print(element + " ");
         }
     }

     public static int[] getSortedIndexes (int[] arr) {
         TreeMap<Integer, List<Integer>> map = new TreeMap<>();

         for (int i = 0; i < arr.length; i++) {
             if (map.containsKey(arr[i])) {
                 List<Integer> indexes = map.get(arr[i]);
                 indexes.add(i);
             } else {
                 List<Integer> indexes = new ArrayList<>();
                 indexes.add(i);
                 map.put(arr[i], indexes);
             }
         }

         // Now get the elements from the LinkedHashMap 
         int[] result = new int[arr.length];
         int counter = 0;

         for( Map.Entry<Integer, List<Integer>> entry : map.entrySet()) {
            Integer key = entry.getKey();
            List<Integer> indexes = entry.getValue();

            for (int index : indexes) {
                result[counter] = index;
                counter++;
            }
        }

        return result;
     }
}

TreeMap 本身具有O(log n) 的插入和查找复杂性。我正在获取&lt;Integer, Lis&lt;Integer&gt;&gt; 的映射,以便我们可以将给定数组中的值存储为键,并将值的索引存储为该键下的List(这是为了处理重复的情况)。如果输入中没有重复,我们可以去掉List&lt;Integer&gt;,只剩下TreeMap&lt;Integer, Integer&gt;

我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2016-01-01
    • 2018-04-08
    • 1970-01-01
    • 1970-01-01
    • 2022-09-23
    • 2011-12-17
    • 2017-07-12
    • 2017-04-28
    • 1970-01-01
    相关资源
    最近更新 更多