Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/.htaccess/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 根据数组元素的频率对其排序_Ios_Arrays_Swift_Sorting_Time Complexity - Fatal编程技术网

Ios 根据数组元素的频率对其排序

Ios 根据数组元素的频率对其排序,ios,arrays,swift,sorting,time-complexity,Ios,Arrays,Swift,Sorting,Time Complexity,我需要根据元素的频率对数组进行排序,例如: Input array: [1, 6, 6, 6, 6, 4, 3, 5, 5, 5, 2, 2] Expected output: [1, 3, 4, 2, 2, 5, 5, 5, 6, 6, 6, 6] 我尝试了以下代码: var set: NSCountedSet = [1, 6, 6, 6, 6, 4, 3, 5, 5, 5, 2, 2] var dictionary = [Int: Int]() set.forEach { (item)

我需要根据元素的频率对数组进行排序,例如:

Input array: [1, 6, 6, 6, 6, 4, 3, 5, 5, 5, 2, 2]
Expected output: [1, 3, 4, 2, 2, 5, 5, 5, 6, 6, 6, 6]
我尝试了以下代码:

var set: NSCountedSet = [1, 6, 6, 6, 6, 4, 3, 5, 5, 5, 2, 2]

var dictionary = [Int: Int]()
set.forEach { (item) in
    dictionary[item as! Int] = set.count(for: item)
}
dictionary.keys.sorted()
print(dictionary)
说明:由于1、3、4只出现一次,它们显示在开头,2出现两次,5出现三次,6出现四次。[1,3,4]在其中排序


预期结果:时间复杂度应O(n)

尝试此解决方案。这对我来说就像一个符咒:)

你可以试试

let dd = [1, 6, 6, 6, 6, 4, 3, 5, 5, 5, 2, 2]
let res = dd.sorted { f, s in
    dd.filter { $0 == f }.count <   dd.filter { $0 == s }.count 
} 
print(res) // [1, 4, 3, 2, 2, 5, 5, 5, 6, 6, 6, 6]
让dd=[1,6,6,6,4,3,5,5,5,2]
设res=dd.sorted{f,s in
dd.filter{$0==f}.count
无法按O(n)时间复杂度排序。请看下面流行算法的最坏情况复杂性

较好的最坏情况时间复杂度为O(nlogn)。以下是我们如何利用O(nlogn)时间复杂性解决该问题:


    let array = [1, 6, 6, 6, 6, 4, 3, 5, 5, 5, 2, 2]

    extension Array where Element: Comparable & Hashable {
        func countableSorted() -> [Element] {
            var counts = [Element: Int]()
            // O(n)
            for element in self {
                counts[element] = (counts[element] ?? 0) + 1
            }

            // I think that standart method uses O(nlogn) time complexity.
            // O(nlogn) + O(n) approximately equal to O(nlogn).
            let sorted = counts.sorted { item1, item2 -> Bool in
                if item2.value > item1.value {
                    return true
                }

                if item2.value == item1.value {
                    return item2.key > item1.key
                }

                return false
            }

            var result = [Element]()
            // O(n)
            for item in sorted {
                let items = Array(repeating: item.key, count: item.value)
                result.append(contentsOf: items)
            }

            // Total time complexity for worst case scenario is O(nlogn)

            return result
        }
    }

    print(array.countableSorted())

    // Output: [1, 3, 4, 2, 2, 5, 5, 5, 6, 6, 6, 6]


通过首先创建一个包含每个元素出现次数(
O(n)
)的
字典(
O(n)
),然后调用
数组上的
sorted
O(nlogn)
)并使用先前创建的
字典中的值进行排序。数组中的元素需要具有可比性,才能进行排序,并且可以散列存储在字典中,字典提供了元素查找功能

extension Array where Element: Comparable & Hashable {
    func sortByNumberOfOccurences() -> [Element] {
        let occurencesDict = self.reduce(into: [Element:Int](), { currentResult, element in
            currentResult[element, default: 0] += 1
        })
        return self.sorted(by: { current, next in occurencesDict[current]! < occurencesDict[next]!})
    }
}

[1, 6, 6, 6, 6, 4, 3, 5, 5, 5, 2, 2].sortByNumberOfOccurences() // [1, 4, 3, 2, 2, 5, 5, 5, 6, 6, 6, 6]
甚至更短,:

return self.sorted(按:{(occurrencesdict[$0]!,$0)<(occurrencesdict[$1]!,$1)})
它生成您提供的示例输出,
[1,3,4,2,2,5,5,5,6,6,6,6]
var-inputArray=[1,6,6,6,6,4,3,5,5,5,2]
var inputArray = [1, 6, 6, 6, 6, 4, 3, 5, 5, 5, 2, 2]
var map:[Int: Int] = [:]
for element in inputArray {
    let count = map[element]
    if count == nil {
        map[element] = 1
    } else {
        map[element] = count! + 1
    }
}
var keysArray = map.keys
let sortedKeys = keysArray.sorted { (number1, number2) -> Bool in
    if map[number1]! == map[number2]! {
        return number1 < number2
    } else {
        return map[number1]! < map[number2]!
    }
}
var finalArray: [Int] = []
for element in sortedKeys {
    for _ in 1...map[element]! {
        finalArray.append(element)
    }
}
print(finalArray)
变量映射:[Int:Int]=[:] 用于输入阵列中的元素{ 让计数=映射[元素] 如果计数=nil{ 映射[元素]=1 }否则{ 映射[元素]=计数!+1 } } var keysArray=map.keys 让sortedKeys=keysArray.sorted{(number1,number2)->Bool输入 如果映射[number1]!==映射[number2]{ 返回编号1<编号2 }否则{ 返回地图[number1]!

时间复杂度:O(nlogn)

您可以尝试下面的代码,这工作正常

var inputArray = [1, 6, 6, 6, 6, 4, 3, 5, 5, 5, 2, 2]
inputArray.sort()
let freq = inputArray.sorted { f, s in
    inputArray.filter { $0 == f}.count < inputArray.filter { $0 == s}.count
}
print(freq)
var-inputArray=[1,6,6,6,4,3,5,5,2]
inputArray.sort()
设freq=inputArray.sorted{f,s in
inputArray.filter{$0==f}.count

不确定时间复杂度。

我想在O(n)中添加一个解决方案。

排序需要O(nLogn),但这个问题也可以通过Java中的HashMap不使用排序来解决,因为它包含根据键排序的对。

import java.util.*; 

class Simple 
{ 
    public static void main(String[] arg) 
    {  int inputArray[] = {1, 6, 6, 6, 6, 4, 3, 5, 5, 5, 2, 2};
        Map<Integer,Integer> map = new HashMap<Integer,Integer>(); 
        Map<Integer,List<Integer>> map2 = new HashMap<Integer,List<Integer>>();
       for(int i: inputArray)
      {
                  if(map.get(i) == null){
                 map.put(i, 1) ;
                  }
                  else{
                  int a = map.get(i);
                  map.put(i,a+1);
                 }
      }

        // using for-each loop for iteration over Map.entrySet() 
        for (Map.Entry<Integer,Integer> entry : map.entrySet()) {
            if(map2.get(entry.getValue()) == null){
                map2.put(entry.getValue(), new ArrayList<Integer>()) ;
            }
            map2.get(entry.getValue()).add(entry.getKey());
        }

        for(Map.Entry<Integer,List<Integer>> entry : map2.entrySet()){
            for(int j=0; j<entry.getValue().size(); j++){
                for(int i=0; i<entry.getKey(); i++){
                System.out.print(entry.getValue().get(j) + " ");
            }
            }

        }    
    }         

}
import java.util.*;
简单类
{ 
公共静态void main(字符串[]arg)
{int inputArray[]={1,6,6,6,4,3,5,5,5,2};
Map Map=newhashmap();
Map map2=新的HashMap();
for(int i:输入阵列)
{
if(map.get(i)==null){
图.put(i,1);
}
否则{
int a=map.get(i);
地图放置(i,a+1);
}
}
//使用for each循环在Map.entrySet()上进行迭代
对于(Map.Entry:Map.entrySet()){
if(map2.get(entry.getValue())==null){
put(entry.getValue(),newArrayList());
}
map2.get(entry.getValue()).add(entry.getKey());
}
对于(Map.Entry:map2.entrySet()){

对于(int j=0;j我认为这种排序可以在O(n)中实现,如下所示:

let input = [1, 6, 6, 6, 6, 4, 3, 5, 5, 5, 2, 2]

// build the frequency dictionary (easy task)
let frequencies = input.reduce(into: [:]) { $0[$1] = ($0[$1] ?? 0) + 1 }

// allocate a 2-D array of ints, each item in this array will hold the numbers that
// appear I times in the input array
let frequencyTable: [[Int]] = frequencies.reduce(into: Array(repeating: [Int](), count: input.count)) {
    // substracting one as arrays are zero indexed
    // we can't get of of bounds here since the maximum frequency is the 
    // number of elements in the input array
    // Also replicating the numbers by their frequency, to have
    // the same contents as in the input array
    $0[$1.value - 1] += Array(repeating: $1.key, count: $1.value)
}

// lastly, simply flatten the 2-D array to get the output we need
let output = frequencyTable.flatMap { $0 }

print(output)
样本结果:

[4, 1, 3, 2, 2, 5, 5, 5, 6, 6, 6, 6]
请注意,具有相同频率的数字顺序可能因字典哈希函数的工作方式而异

此外,我们还牺牲了空间(分配的二维阵列)以换取时间

frequencyTable
内容看起来与此类似(同样,1、4、3的顺序可能不同):


我想知道这是否是O(n)。-还要注意排序是不稳定的,不能保证同样频繁出现的数字顺序是保持不变的。@MartinR我不认为用O(n)可以解决这个问题,当然对于@Sh_Khan的答案,可能还有其他不太广泛的答案,但预期的输出应该是
[1,3,4,2,2,5,5,5,6,6,6]
如果您声明循环条件为
x…y-1
,则执行
x更为合理。对于输入
[1,1,1,2,2,3]
,您的代码生成的结果
[3,1,1,1,2,2]
,这在我看来是错误的。我认为您无法到达O(n)在最坏的情况下。如果您的要求是对唯一的项也进行排序,那么这已经给了您O(n*logn)。计数排序是满足O(n)的一个选择,如果频率很小,我正要发布这个
let array=[1,6,6,6,6,4,3,5,5,5,2]let freq=array.reduce(转换为:[:]){$0[$1,默认值:0]+=1}让SorterDarray=array.sorted(){freq[$0]!
不能在O(n)中完成。您需要先对该数组进行排序,然后使用上述方法。@RakeshaShastri不,您不需要先对数组进行排序,这在
sorted
调用中完成。但是,您是对的,我的算法的总体时间复杂度是
O(nlogn)
,更新了我的答案以反映
排序(按:)
不是O(n)@LeoDabus我也在考虑第二种解决方案,但使用了
你能在swift中尝试相同的方法吗?@Bappaditya Hi我尝试用swift编写代码。我正在添加代码。但由于swift中的字典无法维持我们在该解决方案中应用排序方法所需的顺序,这会增加复杂性
import java.util.*; 

class Simple 
{ 
    public static void main(String[] arg) 
    {  int inputArray[] = {1, 6, 6, 6, 6, 4, 3, 5, 5, 5, 2, 2};
        Map<Integer,Integer> map = new HashMap<Integer,Integer>(); 
        Map<Integer,List<Integer>> map2 = new HashMap<Integer,List<Integer>>();
       for(int i: inputArray)
      {
                  if(map.get(i) == null){
                 map.put(i, 1) ;
                  }
                  else{
                  int a = map.get(i);
                  map.put(i,a+1);
                 }
      }

        // using for-each loop for iteration over Map.entrySet() 
        for (Map.Entry<Integer,Integer> entry : map.entrySet()) {
            if(map2.get(entry.getValue()) == null){
                map2.put(entry.getValue(), new ArrayList<Integer>()) ;
            }
            map2.get(entry.getValue()).add(entry.getKey());
        }

        for(Map.Entry<Integer,List<Integer>> entry : map2.entrySet()){
            for(int j=0; j<entry.getValue().size(); j++){
                for(int i=0; i<entry.getKey(); i++){
                System.out.print(entry.getValue().get(j) + " ");
            }
            }

        }    
    }         

}
extension Array where Element: Comparable & Hashable {
func sortByNumberOfOccurences() -> [Element] {
    let occurencesDict = self.reduce(into: [Element:Int](), { currentResult, element in
        currentResult[element, default: 0] += 1
    })
    let dict = occurencesDict.sorted(by: {$0.0 < $1.0})
    var dictioanary = [Int:Array]()
    for (element,occurence) in dict {
        if dictioanary[occurence] == nil
        {
            dictioanary[occurence] = Array()
        }
        dictioanary[occurence]?.append(element)
    }


    var resultArray = Array()
    let finalDict = dictioanary.sorted(by: {$0.0  < $1.0})
    for (frequency,allValuesOccuringWithThisFrequncy) in finalDict {
       for i in allValuesOccuringWithThisFrequncy
       {
        var j = 0
        while(j < frequency)
        {
            resultArray.append(i)
            j = j + 1
        }
       }
    }
    print(resultArray)
    return resultArray
}
let input = [1, 6, 6, 6, 6, 4, 3, 5, 5, 5, 2, 2]

// build the frequency dictionary (easy task)
let frequencies = input.reduce(into: [:]) { $0[$1] = ($0[$1] ?? 0) + 1 }

// allocate a 2-D array of ints, each item in this array will hold the numbers that
// appear I times in the input array
let frequencyTable: [[Int]] = frequencies.reduce(into: Array(repeating: [Int](), count: input.count)) {
    // substracting one as arrays are zero indexed
    // we can't get of of bounds here since the maximum frequency is the 
    // number of elements in the input array
    // Also replicating the numbers by their frequency, to have
    // the same contents as in the input array
    $0[$1.value - 1] += Array(repeating: $1.key, count: $1.value)
}

// lastly, simply flatten the 2-D array to get the output we need
let output = frequencyTable.flatMap { $0 }

print(output)
[4, 1, 3, 2, 2, 5, 5, 5, 6, 6, 6, 6]
[[4, 3, 1], [2, 2], [5, 5, 5], [6, 6, 6, 6], [], [], [], [], [], [], [], []]