數(shù)據(jù)結(jié)構(gòu)和算法(二)-空間換取時間

介紹

我們寫算法的目的是盡可能的采用時間復(fù)雜度和空間復(fù)雜度都很低的算法。所以優(yōu)化算法的時候我們都從時間和空間兩個維度去考核。時間復(fù)雜度的調(diào)優(yōu)可以使用遞歸,二分法,動態(tài)規(guī)劃等等。空間的復(fù)雜度調(diào)優(yōu)就要根據(jù)業(yè)務(wù)選擇合適的數(shù)據(jù)結(jié)構(gòu),今天我們就看看如何選擇數(shù)據(jù)機構(gòu)?我們都聽過使用空間復(fù)雜度替換時間復(fù)雜度的方案。

案例

查找數(shù)組中出現(xiàn)次數(shù)最多的那個元素和出現(xiàn)的次數(shù)。
比如 intArrayOf(3, 7, 5, 7, 8, 2, 7, 3, 8)
方法1:

fun findMaxTimes(): Pair<Int, Int> {
    val a = intArrayOf(3, 7, 5, 7, 8, 2, 7, 3, 8)
    var maxTimes = 0
    var valueOfMaxTimes = 0
    for (i in a.indices) {
        var tmpTimes = 0
        var tmpValue = a[i]
        for (m in a.indices) {
            val tmpValue2 = a[m]
            if (tmpValue == tmpValue2) {
                tmpTimes++
            }
            if (tmpTimes > maxTimes) {
                maxTimes = tmpTimes
                valueOfMaxTimes = tmpValue
            }
        }
    }

    return Pair(valueOfMaxTimes, maxTimes)
}

這種方法可讀性高,邏輯就是使用兩層循環(huán),每次使用外部循環(huán)的元素和數(shù)組內(nèi)的元素進行一一比較并且統(tǒng)計重復(fù)次數(shù),找到最大重復(fù)次數(shù)的。這種算法的時間復(fù)雜度是O(n),空間復(fù)雜度沒變。
方法2

fun findMaxTimes2(): Pair<Int, Int> {
    val a = intArrayOf(3, 7, 5, 7, 8, 2, 7, 3, 8)

    val groupMap: MutableMap<Int, Int> = mutableMapOf()
    a.forEach {
        val tmp = groupMap[it] ?: 0
        groupMap[it] = tmp + 1
    }

    val entry = groupMap.maxWith(Comparator { o1, o2 -> (o1!!.value.compareTo(o2!!.value)) })

    return Pair(entry?.key?:0,entry?.value?:0)
}

方法2中使用一個map統(tǒng)計所有元素的出現(xiàn)次數(shù),然后遍歷map找到最大次數(shù)的元素和次數(shù)。這種方法的時間復(fù)雜度是O(n),但是空間復(fù)雜度是O(n).
方法3


fun findMaxTimes3():Pair<Int,Int> {
    val a = intArrayOf(3, 7, 5, 7, 8, 2, 7, 3, 8)

    val b= IntArray(9)

    for (i in a) {
        val tmp = if(b[i]==0)1 else b[i]+1
        b[i]=tmp
    }

    var maxTimes=0
    var valueOfMaxTimes = 0
    for(p in b.withIndex()){
        if(maxTimes<p.value){
            maxTimes = p.value
            valueOfMaxTimes = p.index
        }
    }

    return valueOfMaxTimes to maxTimes
}

方法3有種取巧的方式了,因為數(shù)組的值都是10以內(nèi),而且長度也是小于10,所以定義一個等長的數(shù)組b,其中b的下標對應(yīng)a數(shù)組的value,b的value存儲的是重復(fù)次數(shù)。這種方式在內(nèi)存方面會浪費一部分空間,比如極端情況下,a數(shù)組內(nèi)都是8,那么b數(shù)組的index是8的位置有值,其他位置的空間都是浪費掉了。同樣這種方法的時間和空間復(fù)雜度都是O(n)

總結(jié)

我們在算法優(yōu)化的時候,值得優(yōu)化的地方:
1.無效的計算和存儲,刪除無效的計算和存儲,節(jié)約時間和空間復(fù)雜度。
2.采用合適的數(shù)據(jù)結(jié)構(gòu)存儲可以實現(xiàn)時間復(fù)雜度向空間復(fù)雜度的轉(zhuǎn)移。
3.多層循環(huán)的時候,找到合適的跳轉(zhuǎn)條件,跳出循環(huán)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容