关于算法复杂度

2016-01-17 LEo 更多博文 » 博客 » GitHub »

原文链接 http://reborncodinglife.com/2016/01/17/algorithm-complexity/
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。


本文主要通过介绍如何计算十进制数转换成二进制数后,其二进制数中是1的个数,进而分析算法复杂度相关问题。例如十进制数7,二进制表示为0111,总共有三个1。

代码使用go语言实现,为简单起见,算法4和算法5只能计算0-255范围之内的数。

算法1

算法复杂度是O(N),其中N是十进制数字的二进制表示位数。 比如:十进制16,二进制表示为:1 0000 计算出16二进制数中1的个数需运算5次。

func divideCount(number int) int {
    counter := 0
    for counter = 0; number != 0; number /= 2 {
        if number%2 == 1 {
            counter++
        }
    }
    return counter
}

算法2

算法复杂度是O(N),其中N是十进制数字的二进制表示位数。 比如:十进制16,二进制表示为:1 0000 计算出16二进制数中1的个数需运算5次。

func shiftCount(number int) int {
    counter := 0
    for counter = 0; number != 0; number >>= 1 {
        if number&1 != 0 {
            counter++
        }
    }
    return counter
}

算法3

算法复杂度是O(N),其中N是十进制数字的二进制位数中是1的位数。 比如:十进制16,二进制表示为:1 0000 计算出16的二进制数中1的个数需运算1次(一个1)。 十进制15,二进制表示为:1111 计算出15的二进制数中1的个数需运算4次(4个1)。

func subtractCount(a int) int {
    counter := 0
    for counter = 0; a != 0; a &= (a - 1) {
        counter++
    }
    return counter
}

算法4

算法复杂度是一个动态值,范围是O(1)至O(1)*255,因为如果是数字0,则运算一次就得出结果。 如果是数字255,需经过255次运算才能得出结果(因为需要执行255次case语句)。 比如:计算出0的二进制数中1的个数只需运算1次, 而计算出255的二进制数中1的个数需运算255次。

func switchCount(number int) int {
    counter := 0
    switch number {
    case 0:
        counter = 0
    case 1:
        fallthrough
    case 2:
        fallthrough
    case 4:
        fallthrough
    case 8:
        fallthrough
    case 16:
        fallthrough
    case 32:
        fallthrough
    case 64:
        fallthrough
    case 128:
        counter = 1
    case 3:
        fallthrough
    case 5:
        fallthrough
    case 6:
        fallthrough
    case 9:
        fallthrough
    case 10:
        fallthrough
    case 12:
        fallthrough
    case 17:
        fallthrough
    case 18:
        fallthrough
    case 20:
        fallthrough
    case 24:
        fallthrough
    case 33:
        fallthrough
    case 34:
        fallthrough
    case 36:
        fallthrough
    case 40:
        fallthrough
    case 48:
        fallthrough
    case 65:
        fallthrough
    case 66:
        fallthrough
    case 68:
        fallthrough
    case 72:
        fallthrough
    case 80:
        fallthrough
    case 96:
        fallthrough
    case 129:
        fallthrough
    case 130:
        fallthrough
    case 132:
        fallthrough
    case 136:
        fallthrough
    case 144:
        fallthrough
    case 160:
        fallthrough
    case 192:
        counter = 2
    case 7:
        fallthrough
    case 11:
        fallthrough
    case 13:
        fallthrough
    case 14:
        fallthrough
    case 19:
        fallthrough
    case 21:
        fallthrough
    case 22:
        fallthrough
    case 25:
        fallthrough
    case 26:
        fallthrough
    case 28:
        fallthrough
    case 35:
        fallthrough
    case 37:
        fallthrough
    case 38:
        fallthrough
    case 41:
        fallthrough
    case 42:
        fallthrough
    case 44:
        fallthrough
    case 49:
        fallthrough
    case 50:
        fallthrough
    case 52:
        fallthrough
    case 56:
        fallthrough
    case 67:
        fallthrough
    case 69:
        fallthrough
    case 70:
        fallthrough
    case 73:
        fallthrough
    case 74:
        fallthrough
    case 76:
        fallthrough
    case 81:
        fallthrough
    case 82:
        fallthrough
    case 84:
        fallthrough
    case 88:
        fallthrough
    case 97:
        fallthrough
    case 98:
        fallthrough
    case 100:
        fallthrough
    case 104:
        fallthrough
    case 112:
        fallthrough
    case 131:
        fallthrough
    case 133:
        fallthrough
    case 134:
        fallthrough
    case 137:
        fallthrough
    case 138:
        fallthrough
    case 140:
        fallthrough
    case 145:
        fallthrough
    case 146:
        fallthrough
    case 148:
        fallthrough
    case 152:
        fallthrough
    case 161:
        fallthrough
    case 162:
        fallthrough
    case 164:
        fallthrough
    case 168:
        fallthrough
    case 176:
        fallthrough
    case 193:
        fallthrough
    case 194:
        fallthrough
    case 196:
        fallthrough
    case 200:
        fallthrough
    case 208:
        fallthrough
    case 224:
        counter = 3
    case 15:
        fallthrough
    case 23:
        fallthrough
    case 27:
        fallthrough
    case 29:
        fallthrough
    case 30:
        fallthrough
    case 39:
        fallthrough
    case 43:
        fallthrough
    case 45:
        fallthrough
    case 46:
        fallthrough
    case 51:
        fallthrough
    case 53:
        fallthrough
    case 54:
        fallthrough
    case 57:
        fallthrough
    case 58:
        fallthrough
    case 60:
        fallthrough
    case 71:
        fallthrough
    case 75:
        fallthrough
    case 77:
        fallthrough
    case 78:
        fallthrough
    case 83:
        fallthrough
    case 85:
        fallthrough
    case 86:
        fallthrough
    case 89:
        fallthrough
    case 90:
        fallthrough
    case 92:
        fallthrough
    case 99:
        fallthrough
    case 101:
        fallthrough
    case 102:
        fallthrough
    case 105:
        fallthrough
    case 106:
        fallthrough
    case 108:
        fallthrough
    case 113:
        fallthrough
    case 114:
        fallthrough
    case 116:
        fallthrough
    case 120:
        fallthrough
    case 135:
        fallthrough
    case 139:
        fallthrough
    case 141:
        fallthrough
    case 142:
        fallthrough
    case 147:
        fallthrough
    case 149:
        fallthrough
    case 150:
        fallthrough
    case 153:
        fallthrough
    case 154:
        fallthrough
    case 156:
        fallthrough
    case 163:
        fallthrough
    case 165:
        fallthrough
    case 166:
        fallthrough
    case 169:
        fallthrough
    case 170:
        fallthrough
    case 172:
        fallthrough
    case 177:
        fallthrough
    case 178:
        fallthrough
    case 180:
        fallthrough
    case 184:
        fallthrough
    case 195:
        fallthrough
    case 197:
        fallthrough
    case 198:
        fallthrough
    case 201:
        fallthrough
    case 202:
        fallthrough
    case 204:
        fallthrough
    case 209:
        fallthrough
    case 210:
        fallthrough
    case 212:
        fallthrough
    case 216:
        fallthrough
    case 225:
        fallthrough
    case 226:
        fallthrough
    case 228:
        fallthrough
    case 232:
        fallthrough
    case 240:
        counter = 4
    case 31:
        fallthrough
    case 47:
        fallthrough
    case 55:
        fallthrough
    case 59:
        fallthrough
    case 61:
        fallthrough
    case 62:
        fallthrough
    case 79:
        fallthrough
    case 87:
        fallthrough
    case 91:
        fallthrough
    case 93:
        fallthrough
    case 94:
        fallthrough
    case 103:
        fallthrough
    case 107:
        fallthrough
    case 109:
        fallthrough
    case 110:
        fallthrough
    case 115:
        fallthrough
    case 117:
        fallthrough
    case 118:
        fallthrough
    case 121:
        fallthrough
    case 122:
        fallthrough
    case 124:
        fallthrough
    case 143:
        fallthrough
    case 151:
        fallthrough
    case 155:
        fallthrough
    case 157:
        fallthrough
    case 158:
        fallthrough
    case 167:
        fallthrough
    case 171:
        fallthrough
    case 173:
        fallthrough
    case 174:
        fallthrough
    case 179:
        fallthrough
    case 181:
        fallthrough
    case 182:
        fallthrough
    case 185:
        fallthrough
    case 186:
        fallthrough
    case 188:
        fallthrough
    case 199:
        fallthrough
    case 203:
        fallthrough
    case 205:
        fallthrough
    case 206:
        fallthrough
    case 211:
        fallthrough
    case 213:
        fallthrough
    case 214:
        fallthrough
    case 217:
        fallthrough
    case 218:
        fallthrough
    case 220:
        fallthrough
    case 227:
        fallthrough
    case 229:
        fallthrough
    case 230:
        fallthrough
    case 233:
        fallthrough
    case 234:
        fallthrough
    case 236:
        fallthrough
    case 241:
        fallthrough
    case 242:
        fallthrough
    case 244:
        fallthrough
    case 248:
        counter = 5
    case 63:
        fallthrough
    case 95:
        fallthrough
    case 111:
        fallthrough
    case 119:
        fallthrough
    case 123:
        fallthrough
    case 125:
        fallthrough
    case 126:
        fallthrough
    case 159:
        fallthrough
    case 175:
        fallthrough
    case 183:
        fallthrough
    case 187:
        fallthrough
    case 189:
        fallthrough
    case 190:
        fallthrough
    case 207:
        fallthrough
    case 215:
        fallthrough
    case 219:
        fallthrough
    case 221:
        fallthrough
    case 222:
        fallthrough
    case 231:
        fallthrough
    case 235:
        fallthrough
    case 237:
        fallthrough
    case 238:
        fallthrough
    case 243:
        fallthrough
    case 245:
        fallthrough
    case 246:
        fallthrough
    case 249:
        fallthrough
    case 250:
        fallthrough
    case 252:
        counter = 6
    case 127:
        fallthrough
    case 191:
        fallthrough
    case 223:
        fallthrough
    case 239:
        fallthrough
    case 247:
        fallthrough
    case 251:
        fallthrough
    case 253:
        fallthrough
    case 254:
        counter = 7
    case 255:
        counter = 8
    }
    return counter
}

算法5

算法复杂度是O(1),可以说是效率最高的了,perfect!即每次都只需运算一次就可以得出结果。 比如:计算出十进制数0-255的二进制数中1的个数都只需运算1次。

func tableCount(number int) int {
    table := []int{
        0, 1, 1, 2, 1, 2, 2, 3, 1, 2,
        2, 3, 2, 3, 3, 4, 1, 2, 2, 3,
        2, 3, 3, 4, 2, 3, 3, 4, 3, 4,
        4, 5, 1, 2, 2, 3, 2, 3, 3, 4,
        2, 3, 3, 4, 3, 4, 4, 5, 2, 3,
        3, 4, 3, 4, 4, 5, 3, 4, 4, 5,
        4, 5, 5, 6, 1, 2, 2, 3, 2, 3,
        3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
        2, 3, 3, 4, 3, 4, 4, 5, 3, 4,
        4, 5, 4, 5, 5, 6, 2, 3, 3, 4,
        3, 4, 4, 5, 3, 4, 4, 5, 4, 5,
        5, 6, 3, 4, 4, 5, 4, 5, 5, 6,
        4, 5, 5, 6, 5, 6, 6, 7, 1, 2,
        2, 3, 2, 3, 3, 4, 2, 3, 3, 4,
        3, 4, 4, 5, 2, 3, 3, 4, 3, 4,
        4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
        2, 3, 3, 4, 3, 4, 4, 5, 3, 4,
        4, 5, 4, 5, 5, 6, 3, 4, 4, 5,
        4, 5, 5, 6, 4, 5, 5, 6, 5, 6,
        6, 7, 2, 3, 3, 4, 3, 4, 4, 5,
        3, 4, 4, 5, 4, 5, 5, 6, 3, 4,
        4, 5, 4, 5, 5, 6, 4, 5, 5, 6,
        5, 6, 6, 7, 3, 4, 4, 5, 4, 5,
        5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
        4, 5, 5, 6, 5, 6, 6, 7, 5, 6,
        6, 7, 6, 7, 7, 8,
    }
    return table[number]
}

总结

相比较算法1和算法2,算法3效率更高,算法4的计算效率是一个动态值,其计算效率依赖具体的数字。 相比之前3个算法效率有时候反而更低。但是该算法提供了一种很好的解决思路,即借助空间(内存)换取时间,将已知的值全部列出来,可以使用查找表实现算法,于是有算法5。算法5是通过查找表方式实现,通过空间(即内存)换取时间。由此可以看出,在不同的应用场景需选择不同算法实现,例如在内存很充裕且追求最高计算效率情况下,算法5是最适合的。但是在嵌入式开发过程中,内存受限且追求计算效率时,那么算法3是最适合的。