本来想写一片关于 slice 切片的文章,但是又复习了一下《go程序设计语言》,并且网上类似的东西数不胜数。。
于是想着把课后练习题做了吧,(ps:当时看第一遍的时候不太明白所以没做)。
本文代码可以直接在 playground 中运行。
练习 4.3:
重写reverse函数,使用数组指针代替slice。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package mainimport ( "fmt" ) func main () { nums:=[10 ]int {1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 } Reverse(&nums) fmt.Println(nums) } func Reverse (nums *[10]int ) { for i, j := 0 , len (nums)-1 ; i < j; i,j = i+1 ,j-1 { nums[i], nums[j] = nums[j], nums[i] } }
Tips: 在 golang 中,建立了 arrPtr := &arr 这种类似地址关系后,* 允许不写。
所以等同于:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package mainimport ( "fmt" ) func main () { nums:=[10 ]int {1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 } Reverse(&nums) fmt.Println(nums) } func Reverse (numPtr *[10]int ) { for i, j := 0 , len (*numPtr)-1 ; i < j; i,j = i+1 ,j-1 { (*numPtr)[i], (*numPtr)[j] = (*numPtr)[j], (*numPtr)[i] } }
为什么要用 () 吧 *numPtr 括起来呢。
因为在 Golang 中 * 寻址运算符和 [] 中括号运算符的优先级是不同的!
初等运算符的优先级是大于单目运算符的,因此先参与计算的是 arrPtr[0],arrPtr[0] 其实就是数组的第一个元素,就是数字 1。 数字 1 必然是 int 类型,而不是一个地址,因此针对数字 1 使用 * 寻址运算符自然也就发生了错误。
练习 4.4:
编写一个rotate函数,通过一次循环完成镟转。
说让通过一次循环翻转,没说要原地翻转。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package mainimport ( "fmt" ) func main () { nums := []int {1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 } fmt.Println(Rotate(nums, 2 )) } func Rotate (nums []int , r int ) []int { n := len (nums) ans := make ([]int , n, n) for i := 0 ; i < n; i++ { index := i+r if index >= n { index = index - n } ans[i] = nums[index] } return ans }
练习 4.5:
写一个函数在原地完成消除[]string中相邻重复的字符串的操作。
关键是原地,不开辟额外空间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package mainimport ( "fmt" ) func main () { strs := []string {"a" , "a" ,"a" , "b" , "b" , "c" } fmt.Println(Clear(strs)) } func Clear (strs []string ) []string { for i, j := 0 , 1 ; j < len (strs)-1 ; i, j = i+1 ,j+1 { if strs[i] == strs[j] { copy (strs[j:],strs[j+1 :]) strs = strs[:len (strs)-1 ] i-- j-- } } return strs }
练习 4.6:
编写一个函数,原地将一个UTF-8编码的[]byte类型的slice中相邻的空格(参考 unicode.IsSpace)替换成一个空格返回
空格的 unicode 码是 32。
和上一题没有区别。只是多了一个 unicode.IsSpace() 的判断。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package mainimport ( "fmt" "unicode" ) func main () { strs := []byte {228 , 184 , 173 , 32 , 32 , 33 , 33 , 229 , 155 , 189 } fmt.Println(string (clear(strs))) } func clear (strList []byte ) []byte { for i, j := 0 , 1 ; i < len (strList)-1 ; i, j = i+1 , j+1 { if strList[i] == strList[j] && unicode.IsSpace(rune (strList[i])) { copy (strList[j:], strList[j+1 :]) strList = strList[:len (strList)-1 ] i-- j-- } } return strList }
练习 4.7:
修改reverse函数用于原地反转UTF-8编码的[]byte。是否可以不用分配额外的内存?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package mainimport ( "fmt" ) func main () { strs := "asadqweq" fmt.Println(string (reverse([]byte (strs)))) } func reverse (strs []byte ) []byte { for i, j := 0 , len (strs)-1 ; i < j; i, j = i+1 , j-1 { strs[i], strs[j] = strs[j], strs[i] } return strs }
2022年2月3日17:59:16:
可以在这里查看 The Go Programming Language 其它的课后习题答案代码:
https://github.com/ruomuc/go-programming-language