diff --git a/codes/go/chapter_computational_complexity/time_complexity/time_complexity.go b/codes/go/chapter_computational_complexity/time_complexity/time_complexity.go new file mode 100644 index 000000000..4e8432ac8 --- /dev/null +++ b/codes/go/chapter_computational_complexity/time_complexity/time_complexity.go @@ -0,0 +1,127 @@ +package time_complexity + +/* 常数阶 */ +func constant(n int) int { + count := 0 + size := 100000 + for i := 0; i < size; i++ { + count++ + } + return count +} + +/* 线性阶 */ +func linear(n int) int { + count := 0 + for i := 0; i < n; i++ { + count++ + } + return count +} + +/* 线性阶(遍历数组) */ +func arrayTraversal(nums []int) int { + count := 0 + // 循环次数与数组长度成正比 + for range nums { + count++ + } + return count +} + +/* 平方阶 */ +func quadratic(n int) int { + count := 0 + // 循环次数与数组长度成平方关系 + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + count++ + } + } + return count +} + +/* 平方阶(冒泡排序) */ +func bubbleSort(nums []int) int { + count := 0 // 计数器 + // 外循环:待排序元素数量为 n-1, n-2, ..., 1 + for i := len(nums) - 1; i > 0; i-- { + // 内循环:冒泡操作 + for j := 0; j < i; j++ { + if nums[j] > nums[j+1] { + // 交换 nums[j] 与 nums[j + 1] + tmp := nums[j] + nums[j] = nums[j+1] + nums[j+1] = tmp + count += 3 // 元素交换包含 3 个单元操作 + } + } + } + return count +} + +/* 指数阶(循环实现)*/ +func exponential(n int) int { + count, base := 0, 1 + // cell 每轮一分为二,形成数列 1, 2, 4, 8, ..., 2^(n-1) + for i := 0; i < n; i++ { + for j := 0; j < base; j++ { + count++ + } + base *= 2 + } + // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1 + return count +} + +/* 指数阶(递归实现)*/ +func expRecur(n int) int { + if n == 1 { + return 1 + } + return expRecur(n-1) + expRecur(n-1) + 1 +} + +/* 对数阶(循环实现)*/ +func logarithmic(n float64) int { + count := 0 + for n > 1 { + n = n / 2 + count++ + } + return count +} + +/* 对数阶(递归实现)*/ +func logRecur(n float64) int { + if n <= 1 { + return 0 + } + return logRecur(n/2) + 1 +} + +/* 线性对数阶 */ +func linearLogRecur(n float64) int { + if n <= 1 { + return 1 + } + count := linearLogRecur(n/2) + + linearLogRecur(n/2) + for i := 0.0; i < n; i++ { + count++ + } + return count +} + +/* 阶乘阶(递归实现) */ +func factorialRecur(n int) int { + if n == 0 { + return 1 + } + count := 0 + // 从 1 个分裂出 n 个 + for i := 0; i < n; i++ { + count += factorialRecur(n - 1) + } + return count +} diff --git a/codes/go/chapter_computational_complexity/time_complexity/time_complexity_test.go b/codes/go/chapter_computational_complexity/time_complexity/time_complexity_test.go new file mode 100644 index 000000000..3c9527eff --- /dev/null +++ b/codes/go/chapter_computational_complexity/time_complexity/time_complexity_test.go @@ -0,0 +1,44 @@ +package time_complexity + +import ( + "fmt" + "testing" +) + +func TestTimeComplexity(t *testing.T) { + n := 8 + fmt.Println("输入数据大小 n =", n) + + count := constant(n) + fmt.Println("常数阶的计算操作数量 =", count) + + count = linear(n) + fmt.Println("线性阶的计算操作数量 =", count) + count = arrayTraversal(make([]int, n)) + fmt.Println("线性阶(遍历数组)的计算操作数量 =", count) + + count = quadratic(n) + fmt.Println("平方阶的计算操作数量 =", count) + nums := make([]int, n) + for i := 0; i < n; i++ { + nums[i] = n - i + } + count = bubbleSort(nums) + fmt.Println("平方阶(冒泡排序)的计算操作数量 =", count) + + count = exponential(n) + fmt.Println("指数阶(循环实现)的计算操作数量 =", count) + count = expRecur(n) + fmt.Println("指数阶(递归实现)的计算操作数量 =", count) + + count = logarithmic(float64(n)) + fmt.Println("对数阶(循环实现)的计算操作数量 =", count) + count = logRecur(float64(n)) + fmt.Println("对数阶(递归实现)的计算操作数量 =", count) + + count = linearLogRecur(float64(n)) + fmt.Println("线性对数阶(递归实现)的计算操作数量 =", count) + + count = factorialRecur(n) + fmt.Println("阶乘阶(递归实现)的计算操作数量 =", count) +} diff --git a/docs/chapter_computational_complexity/time_complexity.md b/docs/chapter_computational_complexity/time_complexity.md index ab55268c5..1d374e260 100644 --- a/docs/chapter_computational_complexity/time_complexity.md +++ b/docs/chapter_computational_complexity/time_complexity.md @@ -64,7 +64,16 @@ $$ === "Go" ```go title="" - + // 在某运行平台下 + func algorithm(n int) { + a := 2 // 1 ns + a = a + 1 // 1 ns + a = a * 2 // 10 ns + // 循环 n 次 + for i := 0; i < n; i++ { // 1 ns + fmt.Println(a) // 5 ns + } + } ``` === "JavaScript" @@ -164,7 +173,22 @@ $$ === "Go" ```go title="" - + // 算法 A 时间复杂度:常数阶 + func algorithm_A(n int) { + fmt.Println(0) + } + // 算法 B 时间复杂度:线性阶 + func algorithm_B(n int) { + for i := 0; i < n; i++ { + fmt.Println(0) + } + } + // 算法 C 时间复杂度:常数阶 + func algorithm_C(n int) { + for i := 0; i < 1000000; i++ { + fmt.Println(0) + } + } ``` === "JavaScript" @@ -249,13 +273,20 @@ $$ # 循环 n 次 for i in range(n): # +1 print(0) # +1 - } ``` === "Go" ```go title="" - + func algorithm(n int) { + a := 1 // +1 + a = a + 1 // +1 + a = a * 2 // +1 + // 循环 n 次 + for i := 0; i < n; i++ { // +1 + fmt.Println(a) // +1 + } + } ``` === "JavaScript" @@ -389,7 +420,20 @@ $$ === "Go" ```go title="" - + func algorithm(n int) { + a := 1 // +0(技巧 1) + a = a + n // +0(技巧 1) + // +n(技巧 2) + for i := 0; i < 5 * n + 1; i++ { + fmt.Println(0) + } + // +n*n(技巧 3) + for i := 0; i < 2 * n; i++ { + for j := 0; j < n + 1; j++ { + fmt.Println(0) + } + } + } ``` === "JavaScript" @@ -500,7 +544,15 @@ $$ === "Go" ```go title="time_complexity_types.go" - + /* 常数阶 */ + func constant(n int) int { + count := 0 + size := 100000 + for i := 0; i < size; i++ { + count ++ + } + return count + } ``` === "JavaScript" @@ -569,7 +621,14 @@ $$ === "Go" ```go title="time_complexity_types.go" - + /* 线性阶 */ + func linear(n int) int { + count := 0 + for i := 0; i < n; i++ { + count++ + } + return count + } ``` === "JavaScript" @@ -645,7 +704,15 @@ $$ === "Go" ```go title="time_complexity_types.go" - + /* 线性阶(遍历数组) */ + func arrayTraversal(nums []int) int { + count := 0 + // 循环次数与数组长度成正比 + for range nums { + count++ + } + return count + } ``` === "JavaScript" @@ -724,7 +791,17 @@ $$ === "Go" ```go title="time_complexity_types.go" - + /* 平方阶 */ + func quadratic(n int) int { + count := 0 + // 循环次数与数组长度成平方关系 + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + count++ + } + } + return count + } ``` === "JavaScript" @@ -829,7 +906,24 @@ $$ === "Go" ```go title="time_complexity_types.go" - + /* 平方阶(冒泡排序) */ + func bubbleSort(nums []int) int { + count := 0 // 计数器 + // 外循环:待排序元素数量为 n-1, n-2, ..., 1 + for i := len(nums) - 1; i > 0; i-- { + // 内循环:冒泡操作 + for j := 0; j < i; j++ { + if nums[j] > nums[j+1] { + // 交换 nums[j] 与 nums[j + 1] + tmp := nums[j] + nums[j] = nums[j+1] + nums[j+1] = tmp + count += 3 // 元素交换包含 3 个单元操作 + } + } + } + return count + } ``` === "JavaScript" @@ -918,7 +1012,19 @@ $$ === "Go" ```go title="time_complexity_types.go" - + /* 指数阶(循环实现)*/ + func exponential(n int) int { + count, base := 0, 1 + // cell 每轮一分为二,形成数列 1, 2, 4, 8, ..., 2^(n-1) + for i := 0; i < n; i++ { + for j := 0; j < base; j++ { + count++ + } + base *= 2 + } + // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1 + return count + } ``` === "JavaScript" @@ -983,7 +1089,13 @@ $$ === "Go" ```go title="time_complexity_types.go" - + /* 指数阶(递归实现)*/ + func expRecur(n int) int { + if n == 1 { + return 1 + } + return expRecur(n-1) + expRecur(n-1) + 1 + } ``` === "JavaScript" @@ -1061,7 +1173,15 @@ $$ === "Go" ```go title="time_complexity_types.go" - + /* 对数阶(循环实现)*/ + func logarithmic(n float64) int { + count := 0 + for n > 1 { + n = n / 2 + count++ + } + return count + } ``` === "JavaScript" @@ -1126,7 +1246,13 @@ $$ === "Go" ```go title="time_complexity_types.go" - + /* 对数阶(递归实现)*/ + func logRecur(n float64) int { + if n <= 1 { + return 0 + } + return logRecur(n/2) + 1 + } ``` === "JavaScript" @@ -1205,7 +1331,18 @@ $$ === "Go" ```go title="time_complexity_types.go" - + /* 线性对数阶 */ + func linearLogRecur(n float64) int { + if n <= 1 { + return 1 + } + count := linearLogRecur(n/2) + + linearLogRecur(n/2) + for i := 0.0; i < n; i++ { + count++ + } + return count + } ``` === "JavaScript" @@ -1292,7 +1429,18 @@ $$ === "Go" ```go title="time_complexity_types.go" - + /* 阶乘阶(递归实现) */ + func factorialRecur(n int) int { + if n == 0 { + return 1 + } + count := 0 + // 从 1 个分裂出 n 个 + for i := 0; i < n; i++ { + count += factorialRecur(n - 1) + } + return count + } ``` === "JavaScript" @@ -1447,7 +1595,40 @@ $$ === "Go" ```go title="worst_best_time_complexity.go" + /* 生成一个数组,元素为 { 1, 2, ..., n },顺序被打乱 */ + func randomNumbers(n int) []int { + nums := make([]int, n) + // 生成数组 nums = { 1, 2, 3, ..., n } + for i := 0; i < n; i++ { + nums[i] = i + 1 + } + // 随机打乱数组元素 + rand.Shuffle(len(nums), func(i, j int) { + nums[i], nums[j] = nums[j], nums[i] + }) + return nums + } + /* 查找数组 nums 中数字 1 所在索引 */ + func findOne(nums []int) int { + for i := 0; i < len(nums); i++ { + if nums[i] == 1 { + return i + } + } + return -1 + } + + /* Driver Code */ + func main() { + for i := 0; i < 10; i++ { + n := 100 + nums := randomNumbers(n) + index := findOne(nums) + fmt.Println("\n数组 [ 1, 2, ..., n ] 被打乱后 =", nums) + fmt.Println("数字 1 的索引为", index) + } + } ``` === "JavaScript"