diff --git a/codes/go/chapter_array_and_linkedlist/array.go b/codes/go/chapter_array_and_linkedlist/array.go new file mode 100644 index 000000000..26eef2a91 --- /dev/null +++ b/codes/go/chapter_array_and_linkedlist/array.go @@ -0,0 +1,83 @@ +package chapter_array_and_linkedlist + +import ( + "fmt" + "math/rand" +) + +// ExpectSize 预期大小。 在 Go 中,声明数组长度必须是常量表达式, +// 所以这里我们约定,扩展后的长度为 6 +const ExpectSize = 6 + +/* 随机返回一个数组元素 */ +func randomAccess(nums [5]int) (ans int) { + // 在区间 [0, nums.length) 中随机抽取一个数字 + randomIndex := rand.Intn(len(nums)) + // 获取并返回随机元素 + ans = nums[randomIndex] + return +} + +/* 扩展数组长度 */ +func extend(nums [5]int) [ExpectSize]int { + // 初始化一个扩展长度后的数组 + var res [ExpectSize]int + // 将原数组中的所有元素复制到新数组 + for i := 0; i < len(nums); i++ { + res[i] = nums[i] + } + // 返回扩展后的新数组 + return res +} + +/* 在数组的索引 index 处插入元素 num */ +func insert(nums *[5]int, num int, index int) { + // 把索引 index 以及之后的所有元素向后移动一位 + // 如果超出了数组长度,会被直接舍弃 + for i := len(nums) - 1; i > index; i-- { + nums[i] = nums[i-1] + } + // 将 num 赋给 index 处元素 + nums[index] = num +} + +/* 删除索引 index 处元素 */ +func remove(nums *[5]int, index int) { + // 越界检查 + if index >= len(nums) { + return + } + // 把索引 index 之后的所有元素向前移动一位 + for i := index; i < len(nums); i++ { + if i+1 >= len(nums) { + nums[len(nums)-1] = 0 + break + } + nums[i] = nums[i+1] + } +} + +/* 遍历数组 */ +func traverse(nums [5]int) { + var count int + // 通过索引遍历数组 + for i := 0; i < len(nums); i++ { + count++ + } + // 直接遍历数组 + for index, val := range nums { + fmt.Printf("index:%v value:%v\n", index, val) + } +} + +/* 在数组中查找指定元素 */ +func find(nums [5]int, target int) (ans int) { + ans = -1 + for i := 0; i < len(nums); i++ { + if nums[i] == target { + ans = i + break + } + } + return +} diff --git a/codes/go/chapter_array_and_linkedlist/array_test.go b/codes/go/chapter_array_and_linkedlist/array_test.go new file mode 100644 index 000000000..1f5510345 --- /dev/null +++ b/codes/go/chapter_array_and_linkedlist/array_test.go @@ -0,0 +1,145 @@ +package chapter_array_and_linkedlist + +import ( + "reflect" + "testing" +) + +func TestInitArray(t *testing.T) { + t.Parallel() + var arr [5]int + for _, v := range arr { + if v != 0 { + t.Fatalf("array init exception") + } + } +} + +func TestRandomAccess(t *testing.T) { + t.Parallel() + min, max := 1, 5 + nums := [5]int{min, 2, 3, 4, max} + ans := randomAccess(nums) + if ans < min || ans > max { + t.Fatalf("Expected range is greater than min: %v and less than max: %v, got ans: %v", min, max, ans) + } +} + +func TestExtend(t *testing.T) { + t.Parallel() + nums := [5]int{1, 2, 3, 4, 5} + newNums := extend(nums) + if len(newNums) != ExpectSize { + t.Fatalf("Expected len: %v, got: %v", ExpectSize, len(nums)) + } +} + +func TestInsert(t *testing.T) { + t.Parallel() + nums := [5]int{1, 2, 3, 4, 5} + insert(&nums, 5, 0) + if nums[0] != 5 { + t.Fatalf("Expected index[0] val: 5, got: %v", nums[0]) + } +} + +func TestRemove(t *testing.T) { + t.Parallel() + type fields struct { + index int + after [5]int + before [5]int + } + + tests := []struct { + name string + fields fields + }{ + { + name: "remove index[0]", + fields: struct { + index int + after [5]int + before [5]int + }{ + index: 0, + after: [5]int{2, 3, 4, 5, 0}, + before: [5]int{1, 2, 3, 4, 5}, + }, + }, + { + name: "remove end", + fields: struct { + index int + after [5]int + before [5]int + }{ + index: 4, + after: [5]int{1, 2, 3, 4, 0}, + before: [5]int{1, 2, 3, 4, 5}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + v := tt.fields + remove(&v.before, v.index) + if !reflect.DeepEqual(v.before, v.after) { + t.Errorf("remove(&v.before, v.index) = %v, want %v", v.before, v.after) + } + }) + } +} + +func TestTraverse(t *testing.T) { + t.Parallel() + nums := [5]int{1, 2, 3, 4, 5} + traverse(nums) +} + +func TestFind(t *testing.T) { + t.Parallel() + type fields struct { + target int + nums [5]int + } + + tests := []struct { + name string + fields fields + want int + }{ + { + name: "element exists", + fields: struct { + target int + nums [5]int + }{ + target: 1, + nums: [5]int{1, 2, 3, 4, 5}, + }, + want: 0, + }, + { + name: "element does not exist", + fields: struct { + target int + nums [5]int + }{ + target: 6, + nums: [5]int{1, 2, 3, 4, 5}, + }, + want: -1, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + v := tt.fields + if got := find(v.nums, v.target); got != tt.want { + t.Errorf("find(v.nums, v.target) = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/docs/chapter_array_and_linkedlist/array.md b/docs/chapter_array_and_linkedlist/array.md index 3228e678f..52d23024f 100644 --- a/docs/chapter_array_and_linkedlist/array.md +++ b/docs/chapter_array_and_linkedlist/array.md @@ -43,7 +43,9 @@ comments: true === "Go" ```go title="array.go" - + /* 初始化数组 */ + var arr [5]int // {0, 0, 0, 0, 0} + nums := [5]int{1, 3, 2, 5, 4} ``` === "JavaScript" @@ -133,7 +135,14 @@ elementAddr = firtstElementAddr + elementLength * elementIndex === "Go" ```go title="array.go" - + /* 随机返回一个数组元素 */ + func randomAccess(nums [5]int) (ans int) { + // 在区间 [0, nums.length) 中随机抽取一个数字 + randomIndex := rand.Intn(len(nums)) + // 获取并返回随机元素 + ans = nums[randomIndex] + return + } ``` === "JavaScript" @@ -236,7 +245,20 @@ elementAddr = firtstElementAddr + elementLength * elementIndex === "Go" ```go title="array.go" - + // 在 Go 中,声明数组长度必须是常量表达式, + // 所以这里我们约定,扩展后的长度为 6 + const expectSize = 6 + // 扩展数组长度 + func extend(nums [5]int) [expectSize]int { + // 初始化一个扩展长度后的数组 + var res [expectSize]int + // 将原数组中的所有元素复制到新数组 + for i := 0; i < len(nums); i++ { + res[i] = nums[i] + } + // 返回扩展后的新数组 + return res + } ``` === "JavaScript" @@ -370,7 +392,32 @@ elementAddr = firtstElementAddr + elementLength * elementIndex === "Go" ```go title="array.go" - + /* 在数组的索引 index 处插入元素 num */ + func insert(nums [5]int, num int, index int) { + // 把索引 index 以及之后的所有元素向后移动一位 + // 如果超出了数组长度,会被直接舍弃 + for i := len(nums) - 1; i > index; i-- { + nums[i] = nums[i-1] + } + // 将 num 赋给 index 处元素 + nums[index] = num + } + + /* 删除索引 index 处元素 */ + func remove(nums [5]int, index int) { + // 越界检查 + if index >= len(nums) { + return + } + // 把索引 index 之后的所有元素向前移动一位 + for i := index; i < len(nums); i++ { + if i+1 >= len(nums) { + nums[len(nums)-1] = 0 + break + } + nums[i] = nums[i+1] + } + } ``` === "JavaScript" @@ -499,7 +546,18 @@ elementAddr = firtstElementAddr + elementLength * elementIndex === "Go" ```go title="array.go" - + /* 遍历数组 */ + func traverse(nums [5]int) { + var count int + // 通过索引遍历数组 + for i := 0; i < len(nums); i++ { + count++ + } + // 直接遍历数组 + for index, val := range nums { + fmt.Printf("index:%d value:%d\n", index, val) + } + } ``` === "JavaScript" @@ -604,7 +662,17 @@ elementAddr = firtstElementAddr + elementLength * elementIndex === "Go" ```go title="array.go" - + /* 在数组中查找指定元素 */ + func find(nums [5]int, target int) (ans int){ + ans = -1 + for i := 0; i < len(nums); i++ { + if nums[i] == target { + ans = i + break + } + } + return + } ``` === "JavaScript" @@ -660,4 +728,4 @@ elementAddr = firtstElementAddr + elementLength * elementIndex **二分查找。** 例如前文查字典的例子,我们可以将字典中的所有字按照拼音顺序存储在数组中,然后使用与日常查纸质字典相同的“翻开中间,排除一半”的方式,来实现一个查电子字典的算法。 -**深度学习。** 神经网络中大量使用了向量、矩阵、张量之间的线性代数运算,这些数据都是以数组的形式构建的。数组是神经网络编程中最常使用的数据结构。 +**深度学习。** 神经网络中大量使用了向量、矩阵、张量之间的线性代数运算,这些数据都是以数组的形式构建的。数组是神经网络编程中最常使用的数据结构。 \ No newline at end of file