format code

main
lensfrex 4 months ago
parent ddc939fe45
commit 97674a6368
Signed by: lensfrex
GPG Key ID: B1E395B3C6CA0356
  1. 42
      cap3/ex10.go
  2. 26
      cap3/ex11.go
  3. 24
      cap3/ex12.go
  4. 32
      cap3/ex13.go
  5. 24
      cap3/ex14.go
  6. 28
      cap3/ex15.go
  7. 26
      cap3/ex16.go
  8. 70
      cap3/ex17.go
  9. 164
      cap3/ex18.go
  10. 238
      cap3/ex19.go
  11. 102
      cap3/ex5.go
  12. 146
      cap3/ex6.go
  13. 30
      cap3/ex7.go
  14. 40
      cap3/ex8.go
  15. 32
      cap3/ex9.go

@ -2,28 +2,28 @@ package cap3
// Ex10 从0~n的整数中取r个不同的数做一组,求所有可能的组合 // Ex10 从0~n的整数中取r个不同的数做一组,求所有可能的组合
func Ex10(n, r int, callback func(nums []int)) int { func Ex10(n, r int, callback func(nums []int)) int {
if r > n { if r > n {
return 0 return 0
} }
count := 0 count := 0
combine := make([]int, r) combine := make([]int, r)
var findCombine func(m, k int) var findCombine func(m, k int)
findCombine = func(n, k int) { findCombine = func(n, k int) {
// 从n开始往下遍历组合 // 从n开始往下遍历组合
for i := n; i >= k; i-- { for i := n; i >= k; i-- {
combine[k-1] = i combine[k-1] = i
if k > 1 { if k > 1 {
// k-1和n-1,继续深入遍历,处理子问题 // k-1和n-1,继续深入遍历,处理子问题
findCombine(i-1, k-1) findCombine(i-1, k-1)
} else { } else {
count++ count++
callback(combine) callback(combine)
} }
} }
} }
findCombine(n, r) findCombine(n, r)
return count return count
} }

@ -5,19 +5,19 @@ type Vote int // 票数
// Ex11 投票统计,有调整,这里不使用数组存储结果,使用hashmap表存结果 // Ex11 投票统计,有调整,这里不使用数组存储结果,使用hashmap表存结果
func Ex11(votes []Candidate, numOfCandidate int) map[Candidate]Vote { func Ex11(votes []Candidate, numOfCandidate int) map[Candidate]Vote {
result := map[Candidate]Vote{} result := map[Candidate]Vote{}
for _, candidate := range votes { for _, candidate := range votes {
// 无效的投票 // 无效的投票
if candidate <= 0 || int(candidate) > numOfCandidate { if candidate <= 0 || int(candidate) > numOfCandidate {
continue continue
} }
if _, exists := result[candidate]; !exists { if _, exists := result[candidate]; !exists {
result[candidate] = 1 result[candidate] = 1
} else { } else {
result[candidate]++ result[candidate]++
} }
} }
return result return result
} }

@ -4,18 +4,18 @@ type HeightGrade int
// Ex12 身高统计,这里也是用的hashmap存结果 // Ex12 身高统计,这里也是用的hashmap存结果
func Ex12(heights []int) []int { func Ex12(heights []int) []int {
result := make([]int, 8) result := make([]int, 8)
for _, height := range heights { for _, height := range heights {
// 身高映射,上下限调整 // 身高映射,上下限调整
mapping := height/5 - 29 mapping := height/5 - 29
if mapping < 0 { if mapping < 0 {
mapping = 0 mapping = 0
} else if mapping > 7 { } else if mapping > 7 {
mapping = 7 mapping = 7
} }
result[mapping]++ result[mapping]++
} }
return result return result
} }

@ -4,23 +4,23 @@ type Subject int
type Student int type Student int
func Ex14(subjectPassedStudentMap map[Subject]Student) []Student { func Ex14(subjectPassedStudentMap map[Subject]Student) []Student {
result := make([]Student, 0) result := make([]Student, 0)
// 学生及格科目数记录 // 学生及格科目数记录
studentRecord := map[Student]int{} studentRecord := map[Student]int{}
for _, student := range subjectPassedStudentMap { for _, student := range subjectPassedStudentMap {
// 对当前学生及格科目计数 // 对当前学生及格科目计数
if _, exists := studentRecord[student]; !exists { if _, exists := studentRecord[student]; !exists {
studentRecord[student] = 1 studentRecord[student] = 1
} else { } else {
studentRecord[student]++ studentRecord[student]++
} }
// 学生及格科目数已达到传入的科目数,即为全科及格 // 学生及格科目数已达到传入的科目数,即为全科及格
if studentRecord[student] == len(subjectPassedStudentMap) { if studentRecord[student] == len(subjectPassedStudentMap) {
result = append(result, student) result = append(result, student)
} }
} }
return result return result
} }

@ -1,25 +1,25 @@
package cap3 package cap3
var _numberTexts = []string{ var _numberTexts = []string{
"zero", "one", "two", "three", "four", "zero", "one", "two", "three", "four",
"five", "six", "seven", "eight", "nine", "five", "six", "seven", "eight", "nine",
} }
// Ex14NumInput 输入数字,输出英文 // Ex14NumInput 输入数字,输出英文
func Ex14NumInput(num uint64, callback func(str string)) { func Ex14NumInput(num uint64, callback func(str string)) {
digits := make([]uint8, 0, 20) digits := make([]uint8, 0, 20)
for i := num; i >= 1; i /= 10 { for i := num; i >= 1; i /= 10 {
digits = append(digits, uint8(i%10)) digits = append(digits, uint8(i%10))
} }
for i := len(digits) - 1; i >= 0; i-- { for i := len(digits) - 1; i >= 0; i-- {
callback(_numberTexts[digits[i]]) callback(_numberTexts[digits[i]])
} }
} }
// Ex14StrInput 输入数字字符串,输出英文 // Ex14StrInput 输入数字字符串,输出英文
func Ex14StrInput(num string, callback func(str string)) { func Ex14StrInput(num string, callback func(str string)) {
for _, char := range num { for _, char := range num {
callback(_numberTexts[char-48]) callback(_numberTexts[char-48])
} }
} }

@ -1,24 +1,24 @@
package cap3 package cap3
var ( var (
cashes = []int{50, 20, 10, 5, 2, 1} cashes = []int{50, 20, 10, 5, 2, 1}
) )
// Ex15 最少的纸币找零钱 // Ex15 最少的纸币找零钱
func Ex15(amount, paid int) map[int]int { func Ex15(amount, paid int) map[int]int {
result := map[int]int{} result := map[int]int{}
// 还要找的钱 // 还要找的钱
change := paid - amount change := paid - amount
for i, cash := range cashes { for i, cash := range cashes {
// 当前面额需要找的张数,整除后结果为0说明当前面额不足以找零 // 当前面额需要找的张数,整除后结果为0说明当前面额不足以找零
cashNum := change / cash cashNum := change / cash
if cashNum != 0 { if cashNum != 0 {
result[i] = cashNum result[i] = cashNum
// 当前面额找完后更新剩余未找余额 // 当前面额找完后更新剩余未找余额
change = change - cashNum*cash change = change - cashNum*cash
} }
} }
return result return result
} }

@ -3,20 +3,20 @@ package cap3
// Ex16 求x,其平方为一个各位数字互不相同的九位数 // Ex16 求x,其平方为一个各位数字互不相同的九位数
func Ex16(callback func(x, x2 int)) { func Ex16(callback func(x, x2 int)) {
Next: Next:
for x := 10000; x < 32000; x++ { for x := 10000; x < 32000; x++ {
numCntMap := map[int]bool{} numCntMap := map[int]bool{}
x2 := x * x x2 := x * x
for i := x2; i >= 1; i /= 10 { for i := x2; i >= 1; i /= 10 {
digit := i % 10 digit := i % 10
// 当前数字已经出现过,直接跳过,找下一个x,如果没出现过,则做标记后看下一位数字情况 // 当前数字已经出现过,直接跳过,找下一个x,如果没出现过,则做标记后看下一位数字情况
if _, exists := numCntMap[digit]; exists { if _, exists := numCntMap[digit]; exists {
continue Next continue Next
} }
numCntMap[digit] = true numCntMap[digit] = true
} }
callback(x, x2) callback(x, x2)
} }
} }

@ -2,52 +2,52 @@ package cap3
// _node 链表节点,单向循环链表 // _node 链表节点,单向循环链表
type _node struct { type _node struct {
Value int Value int
Next *_node Next *_node
} }
// 初始化长度为n的环 // 初始化长度为n的环
func _initCircle(n int) *_node { func _initCircle(n int) *_node {
head := &_node{0, nil} head := &_node{0, nil}
current := head current := head
for i := 1; i < n; i++ { for i := 1; i < n; i++ {
newNode := &_node{i, nil} newNode := &_node{i, nil}
current.Next = newNode current.Next = newNode
current = newNode current = newNode
} }
// 头尾相连成环 // 头尾相连成环
current.Next = head current.Next = head
return head return head
} }
// Ex17Normal 小朋友游戏(约瑟夫问题),一般解法(非数学解法),n: 总人数(节点数),k:出队报数 // Ex17Normal 小朋友游戏(约瑟夫问题),一般解法(非数学解法),n: 总人数(节点数),k:出队报数
func Ex17Normal(n, k int) int { func Ex17Normal(n, k int) int {
circle := _initCircle(n) circle := _initCircle(n)
current := circle current := circle
for current.Next != current { for current.Next != current {
for i := 1; i < k-1; i++ { for i := 1; i < k-1; i++ {
current = current.Next current = current.Next
} }
// 报到k-1时移除下一个节点 // 报到k-1时移除下一个节点
next := current.Next next := current.Next
current.Next = next.Next current.Next = next.Next
current = current.Next current = current.Next
// 避免内存泄露 // 避免内存泄露
next.Next = nil next.Next = nil
} }
return current.Value return current.Value
} }
// Ex17Math 小朋友游戏(约瑟夫问题),公式递推解法,n: 总人数(节点数),k:出队报数 // Ex17Math 小朋友游戏(约瑟夫问题),公式递推解法,n: 总人数(节点数),k:出队报数
func Ex17Math(n, k int) int { func Ex17Math(n, k int) int {
idx := 0 idx := 0
for i := 2; i <= n; i++ { for i := 2; i <= n; i++ {
idx = (idx + k) % i idx = (idx + k) % i
} }
return idx return idx
} }

@ -1,107 +1,107 @@
package cap3 package cap3
import ( import (
"strings" "strings"
) )
// Ex18 超长整数乘法(都超长) // Ex18 超长整数乘法(都超长)
func Ex18(a, b string) string { func Ex18(a, b string) string {
result := make([]uint8, len(a)+len(b)) result := make([]uint8, len(a)+len(b))
resultEndIdx := len(result) - 1 resultEndIdx := len(result) - 1
for i := 0; i < len(b); i++ { for i := 0; i < len(b); i++ {
carry := uint8(0) carry := uint8(0)
aEnd, bEnd, resultIdx := len(a)-1, len(b)-1, 0 aEnd, bEnd, resultIdx := len(a)-1, len(b)-1, 0
bDigit := b[bEnd-i] - 48 bDigit := b[bEnd-i] - 48
for j := 0; j < len(a); j++ { for j := 0; j < len(a); j++ {
// 字符转数字 // 字符转数字
aDigit := a[aEnd-j] - 48 aDigit := a[aEnd-j] - 48
// 当前位计算结果 = 当前结果 + aDigit*bDigit + 进位 // 当前位计算结果 = 当前结果 + aDigit*bDigit + 进位
resultIdx = resultEndIdx - (i + j) resultIdx = resultEndIdx - (i + j)
num := result[resultIdx] + aDigit*bDigit + carry num := result[resultIdx] + aDigit*bDigit + carry
// 当前位为计算结果的个位,进位为十位上的数字 // 当前位为计算结果的个位,进位为十位上的数字
result[resultIdx] = num % 10 result[resultIdx] = num % 10
carry = num / 10 carry = num / 10
} }
// 如果还有进位,则对下一个结果位添加进位,此时不会再有进位 // 如果还有进位,则对下一个结果位添加进位,此时不会再有进位
if carry != 0 { if carry != 0 {
resultIdx-- resultIdx--
result[resultIdx] += carry result[resultIdx] += carry
} }
} }
zeroPrefix := true zeroPrefix := true
sb := strings.Builder{} sb := strings.Builder{}
for _, num := range result { for _, num := range result {
if zeroPrefix && num == 0 { if zeroPrefix && num == 0 {
continue continue
} else { } else {
zeroPrefix = false zeroPrefix = false
} }
sb.WriteByte(num + 48) sb.WriteByte(num + 48)
} }
return sb.String() return sb.String()
} }
// Ex18type2 超长整数乘法(都超长),a和b都是大端序的数字数组/切片 // Ex18type2 超长整数乘法(都超长),a和b都是大端序的数字数组/切片
func Ex18type2(a, b []uint8) []uint8 { func Ex18type2(a, b []uint8) []uint8 {
result := make([]uint8, len(a)+len(b)) result := make([]uint8, len(a)+len(b))
resultEndIdx := len(result) - 1 resultEndIdx := len(result) - 1
for i := 0; i < len(b); i++ { for i := 0; i < len(b); i++ {
carry := uint8(0) carry := uint8(0)
aEnd, bEnd, resultIdx := len(a)-1, len(b)-1, 0 aEnd, bEnd, resultIdx := len(a)-1, len(b)-1, 0
bDigit := b[bEnd-i] bDigit := b[bEnd-i]
for j := 0; j < len(a); j++ { for j := 0; j < len(a); j++ {
// 字符转数字 // 字符转数字
aDigit := a[aEnd-j] aDigit := a[aEnd-j]
// 当前位计算结果 = 当前结果 + aDigit*bDigit + 进位 // 当前位计算结果 = 当前结果 + aDigit*bDigit + 进位
resultIdx = resultEndIdx - (i + j) resultIdx = resultEndIdx - (i + j)
num := result[resultIdx] + aDigit*bDigit + carry num := result[resultIdx] + aDigit*bDigit + carry
// 当前位为计算结果的个位,进位为十位上的数字 // 当前位为计算结果的个位,进位为十位上的数字
result[resultIdx] = num % 10 result[resultIdx] = num % 10
carry = num / 10 carry = num / 10
} }
// 如果还有进位,则对下一个结果位添加进位,此时不会再有进位 // 如果还有进位,则对下一个结果位添加进位,此时不会再有进位
if carry != 0 { if carry != 0 {
resultIdx-- resultIdx--
result[resultIdx] += carry result[resultIdx] += carry
} }
} }
return result return result
} }
// Ex18type3 超长整数乘法(都超长),a是大端序的数字数组/切片,b为uint64 // Ex18type3 超长整数乘法(都超长),a是大端序的数字数组/切片,b为uint64
func Ex18type3(a []uint8, b uint64) []uint8 { func Ex18type3(a []uint8, b uint64) []uint8 {
result := make([]uint8, len(a)+22) result := make([]uint8, len(a)+22)
resultEndIdx := len(result) - 1 resultEndIdx := len(result) - 1
bOffset := 0 bOffset := 0
for i := b; i >= 1; i /= 10 { for i := b; i >= 1; i /= 10 {
carry := uint8(0) carry := uint8(0)
bDigit := uint8(i % 10) bDigit := uint8(i % 10)
aEnd, resultIdx := len(a)-1, 0 aEnd, resultIdx := len(a)-1, 0
for j := 0; j < len(a); j++ { for j := 0; j < len(a); j++ {
// 字符转数字 // 字符转数字
aDigit := a[aEnd-j] aDigit := a[aEnd-j]
// 当前位计算结果 = 当前结果 + aDigit*bDigit + 进位 // 当前位计算结果 = 当前结果 + aDigit*bDigit + 进位
resultIdx = resultEndIdx - (bOffset + j) resultIdx = resultEndIdx - (bOffset + j)
num := result[resultIdx] + aDigit*bDigit + carry num := result[resultIdx] + aDigit*bDigit + carry
// 当前位为计算结果的个位,进位为十位上的数字 // 当前位为计算结果的个位,进位为十位上的数字
result[resultIdx] = num % 10 result[resultIdx] = num % 10
carry = num / 10 carry = num / 10
} }
// 如果还有进位,则对下一个结果位添加进位,此时不会再有进位 // 如果还有进位,则对下一个结果位添加进位,此时不会再有进位
if carry != 0 { if carry != 0 {
resultIdx-- resultIdx--
result[resultIdx] += carry result[resultIdx] += carry
} }
bOffset++ bOffset++
} }
return result return result
} }

@ -4,134 +4,134 @@ import "strings"
// Ex19 高精度阶乘 // Ex19 高精度阶乘
func Ex19(n uint64) string { func Ex19(n uint64) string {
result := []uint8{1} result := []uint8{1}
for i := uint64(2); i <= n; i++ { for i := uint64(2); i <= n; i++ {
result = multiply(result, i) result = multiply(result, i)
} }
return DigitSlice2String(result) return DigitSlice2String(result)
} }
func multiply(a []uint8, b uint64) []uint8 { func multiply(a []uint8, b uint64) []uint8 {
result := make([]uint8, len(a)+22) result := make([]uint8, len(a)+22)
resultEndIdx := len(result) - 1 resultEndIdx := len(result) - 1
bOffset := 0 bOffset := 0
for i := b; i >= 1; i /= 10 { for i := b; i >= 1; i /= 10 {
carry := uint8(0) carry := uint8(0)
bDigit := uint8(i % 10) bDigit := uint8(i % 10)
aEnd, resultIdx := len(a)-1, 0 aEnd, resultIdx := len(a)-1, 0
for j := 0; j < len(a); j++ { for j := 0; j < len(a); j++ {
// 字符转数字 // 字符转数字
aDigit := a[aEnd-j] aDigit := a[aEnd-j]
// 当前位计算结果 = 当前结果 + aDigit*bDigit + 进位 // 当前位计算结果 = 当前结果 + aDigit*bDigit + 进位
resultIdx = resultEndIdx - (bOffset + j) resultIdx = resultEndIdx - (bOffset + j)
num := result[resultIdx] + aDigit*bDigit + carry num := result[resultIdx] + aDigit*bDigit + carry
// 当前位为计算结果的个位,进位为十位上的数字 // 当前位为计算结果的个位,进位为十位上的数字
result[resultIdx] = num % 10 result[resultIdx] = num % 10
carry = num / 10 carry = num / 10
} }
// 如果还有进位,则对下一个结果位添加进位,此时不会再有进位 // 如果还有进位,则对下一个结果位添加进位,此时不会再有进位
if carry != 0 { if carry != 0 {
resultIdx-- resultIdx--
result[resultIdx] += carry result[resultIdx] += carry
} }
bOffset++ bOffset++
} }
return result return result
} }
func multiply2(a []uint8, b uint64) []uint8 { func multiply2(a []uint8, b uint64) []uint8 {
result := make([]uint8, len(a)+22) result := make([]uint8, len(a)+22)
resultEndIdx := len(result)*2 - 1 resultEndIdx := len(result)*2 - 1
bOffset := 0 bOffset := 0
for i := b; i >= 1; i /= 10 { for i := b; i >= 1; i /= 10 {
carry := uint8(0) carry := uint8(0)
bDigit := uint8(i % 10) bDigit := uint8(i % 10)
aEnd, resultIdx := len(a)*2-1, 0 aEnd, resultIdx := len(a)*2-1, 0
for j := 0; j < len(a); j++ { for j := 0; j < len(a); j++ {
// 字符转数字 // 字符转数字
aDigit := uint8(0) aDigit := uint8(0)
// 4,5 -> 37(0010,0101) // 4,5 -> 37(0010,0101)
aIdx := aEnd - j aIdx := aEnd - j
if aIdx%2 == 0 { if aIdx%2 == 0 {
aDigit = a[aIdx/2] >> 4 aDigit = a[aIdx/2] >> 4
} else { } else {
aDigit = a[aIdx/2] & 0b00001111 aDigit = a[aIdx/2] & 0b00001111
} }
// 当前位计算结果 = 当前结果 + aDigit*bDigit + 进位 // 当前位计算结果 = 当前结果 + aDigit*bDigit + 进位
resultIdx = resultEndIdx - (bOffset + j) resultIdx = resultEndIdx - (bOffset + j)
bitIdx := resultIdx / 2 bitIdx := resultIdx / 2
if resultIdx%2 == 0 { if resultIdx%2 == 0 {
num := (result[bitIdx] >> 4) + aDigit*bDigit + carry num := (result[bitIdx] >> 4) + aDigit*bDigit + carry
// 清位 // 清位
// 4,5 -> 37(0010,0101) => 0,5 -> 5(0000,0101) // 4,5 -> 37(0010,0101) => 0,5 -> 5(0000,0101)
result[bitIdx] &= 0b00001111 result[bitIdx] &= 0b00001111
// 位赋值 // 位赋值
// 0,5 -> 5(0000,0101) => 5,5 -> 5(0101,0101) // 0,5 -> 5(0000,0101) => 5,5 -> 5(0101,0101)
// 5(0000,0101) << 4 => 80(0101,0000) // 5(0000,0101) << 4 => 80(0101,0000)
// 5(0000,0101) | 80(0101,0000) => 5,5 -> 5(0101,0101) // 5(0000,0101) | 80(0101,0000) => 5,5 -> 5(0101,0101)
result[bitIdx] |= (num % 10) << 4 result[bitIdx] |= (num % 10) << 4
carry = num / 10 carry = num / 10
} else { } else {
num := (result[bitIdx] & 0b00001111) + aDigit*bDigit + carry num := (result[bitIdx] & 0b00001111) + aDigit*bDigit + carry
// 清位 // 清位
// 4,5 -> 37(0010,0101) => 4,0 -> 32(0010,0000) // 4,5 -> 37(0010,0101) => 4,0 -> 32(0010,0000)
result[bitIdx] &= 0b11110000 result[bitIdx] &= 0b11110000
// 赋值 // 赋值
// 4,0 -> 32(0010,0000) => 4,5 -> 37(0010,0101) // 4,0 -> 32(0010,0000) => 4,5 -> 37(0010,0101)
// 32(0010,0000) | 5(0000,0101) => 4,5 -> 37(0010,0101) // 32(0010,0000) | 5(0000,0101) => 4,5 -> 37(0010,0101)
result[bitIdx] |= num % 10 result[bitIdx] |= num % 10
carry = num / 10 carry = num / 10
} }
} }
// 如果还有进位,则对下一个结果位添加进位,此时不会再有进位 // 如果还有进位,则对下一个结果位添加进位,此时不会再有进位
if carry != 0 { if carry != 0 {
resultIdx-- resultIdx--
bitIdx := resultIdx / 2 bitIdx := resultIdx / 2
if resultIdx%2 == 0 { if resultIdx%2 == 0 {
// 4,5 -> 37(0010,0101) => 5,5 -> 37(0101,0101) // 4,5 -> 37(0010,0101) => 5,5 -> 37(0101,0101)
// 4+1 -> 5(0000,0101) << 4 => 80(0101,0000) // 4+1 -> 5(0000,0101) << 4 => 80(0101,0000)
// 5(0000,0101) | 80(0101,0000) => 5,5 -> 5(0101,0101) // 5(0000,0101) | 80(0101,0000) => 5,5 -> 5(0101,0101)
result[bitIdx] &= 0b00001111 result[bitIdx] &= 0b00001111
num := (result[bitIdx] >> 4) + carry num := (result[bitIdx] >> 4) + carry
result[bitIdx] |= num << 4 result[bitIdx] |= num << 4
} else { } else {
result[bitIdx] &= 0b11110000 result[bitIdx] &= 0b11110000
num := (result[bitIdx] & 0b00001111) + carry num := (result[bitIdx] & 0b00001111) + carry
result[bitIdx] |= num result[bitIdx] |= num
} }
} }
bOffset++ bOffset++
} }
return result return result
} }
// Ex19LowMem 低内存使用版,两位数字结果按位存在同一个uint8中,一个0~9数字只使用四字节,uint8可存两位,一个字节拆成两半用 // Ex19LowMem 低内存使用版,两位数字结果按位存在同一个uint8中,一个0~9数字只使用四字节,uint8可存两位,一个字节拆成两半用
func Ex19LowMem(n uint64) string { func Ex19LowMem(n uint64) string {
result := []uint8{1} result := []uint8{1}
for i := uint64(2); i <= n; i++ { for i := uint64(2); i <= n; i++ {
result = multiply2(result, i) result = multiply2(result, i)
} }
zeroPrefix := true zeroPrefix := true
sb := strings.Builder{} sb := strings.Builder{}
for _, num := range result { for _, num := range result {
if zeroPrefix && num == 0 { if zeroPrefix && num == 0 {
continue continue
} else { } else {
zeroPrefix = false zeroPrefix = false
} }
sb.WriteByte((num >> 4) + 48) sb.WriteByte((num >> 4) + 48)
sb.WriteByte((num & 0b00001111) + 48) sb.WriteByte((num & 0b00001111) + 48)
} }
return sb.String() return sb.String()
} }

@ -4,66 +4,66 @@ import "lavos/common"
// Ex5 例题5 汉诺塔问题,输出移动的步骤,可指定算法类型,每做出一步移动操作都将会调用callback // Ex5 例题5 汉诺塔问题,输出移动的步骤,可指定算法类型,每做出一步移动操作都将会调用callback
func Ex5(beadNum int, algoType AlgoType, callback func(from string, to string)) { func Ex5(beadNum int, algoType AlgoType, callback func(from string, to string)) {
switch algoType { switch algoType {
case AlgoTypeRecursion: case AlgoTypeRecursion:
Ex5Recursive(beadNum, "A", "B", "C", callback) Ex5Recursive(beadNum, "A", "B", "C", callback)
default: default:
Ex5NonRecursive(beadNum, "A", "B", "C", callback) Ex5NonRecursive(beadNum, "A", "B", "C", callback)
} }
} }
func Ex5Recursive(beadNum int, a, b, c string, callback func(from string, to string)) { func Ex5Recursive(beadNum int, a, b, c string, callback func(from string, to string)) {
if beadNum == 1 { if beadNum == 1 {
// 如果只有一颗珠子,直接从 A 移动到 C,结束 // 如果只有一颗珠子,直接从 A 移动到 C,结束
callback(a, c) callback(a, c)
} else { } else {
// 第二步:将所有在 N 之上的珠子(即 N-1 颗珠子)从 A 移动到 B。此时 C 是中转站 // 第二步:将所有在 N 之上的珠子(即 N-1 颗珠子)从 A 移动到 B。此时 C 是中转站
Ex5Recursive(beadNum-1, a, c, b, callback) Ex5Recursive(beadNum-1, a, c, b, callback)
// 第二步:将 A 的珠子移动到 C // 第二步:将 A 的珠子移动到 C
callback(a, c) callback(a, c)
// 第三步:将剩余的 N-1 颗珠子从 B 移动到 C。此时 A 是中转站 // 第三步:将剩余的 N-1 颗珠子从 B 移动到 C。此时 A 是中转站
Ex5Recursive(beadNum-1, b, a, c, callback) Ex5Recursive(beadNum-1, b, a, c, callback)
} }
} }
type _step struct { type _step struct {
n int n int
from, transit, to string from, transit, to string
} }
func Ex5NonRecursive(beadNum int, a, b, c string, callback func(from string, to string)) { func Ex5NonRecursive(beadNum int, a, b, c string, callback func(from string, to string)) {
stack := common.NewStack[_step](beadNum * 5) stack := common.NewStack[_step](beadNum * 5)
// 最终状态:a->c,b作为中转 // 最终状态:a->c,b作为中转
stack.Push(&_step{ stack.Push(&_step{
n: beadNum, n: beadNum,
from: a, transit: b, to: c, from: a, transit: b, to: c,
}) })
for !stack.Empty() { for !stack.Empty() {
status := stack.Pop() status := stack.Pop()
if status.n == 1 { if status.n == 1 {
callback(status.from, status.to) callback(status.from, status.to)
} else { } else {
// 把子问题的三个基本步骤压入栈 // 把子问题的三个基本步骤压入栈
stack.Push(&_step{ stack.Push(&_step{
n: status.n - 1, n: status.n - 1,
from: status.transit, from: status.transit,
transit: status.from, transit: status.from,
to: status.to, to: status.to,
}) })
stack.Push(&_step{ stack.Push(&_step{
n: 1, n: 1,
from: status.from, from: status.from,
transit: status.transit, transit: status.transit,
to: status.to, to: status.to,
}) })
stack.Push(&_step{ stack.Push(&_step{
n: status.n - 1, n: status.n - 1,
from: status.from, from: status.from,
transit: status.to, transit: status.to,
to: status.transit, to: status.transit,
}) })
} }
} }
} }

@ -2,102 +2,102 @@ package cap3
// Ex6Output 例六的带输出结果 // Ex6Output 例六的带输出结果
func Ex6Output(num int, callback func(nums []int)) { func Ex6Output(num int, callback func(nums []int)) {
Ex6RecursionOutput(num, callback) Ex6RecursionOutput(num, callback)
} }
// Ex6NoneOutput 例六的不带输出结果版本,只求数量 // Ex6NoneOutput 例六的不带输出结果版本,只求数量
func Ex6NoneOutput(num int, algoType AlgoType, callback func(nums []int)) int { func Ex6NoneOutput(num int, algoType AlgoType, callback func(nums []int)) int {
switch algoType { switch algoType {
case AlgoTypeRecursion: case AlgoTypeRecursion:
return Ex6Recursion(num) return Ex6Recursion(num)
default: default:
return Ex6NoneRecursion(num) return Ex6NoneRecursion(num)
} }
} }
// Ex6Recursion 整数划分,递归写法,只计算结果,但对算法经过调整以适合输出 // Ex6Recursion 整数划分,递归写法,只计算结果,但对算法经过调整以适合输出
func Ex6Recursion(num int) int { func Ex6Recursion(num int) int {
count := 0 count := 0
var divider func(num, m int) var divider func(num, m int)
divider = func(num, m int) { divider = func(num, m int) {
// num == 0 来源会有两种:递归中num==m,以及传入的num本身就是0,此时可以作为一个划分 // num == 0 来源会有两种:递归中num==m,以及传入的num本身就是0,此时可以作为一个划分
if num == 0 { if num == 0 {
count++ count++
return return
} }
// 最大划分大小m逐级-1求划分数 // 最大划分大小m逐级-1求划分数
if m > 1 { if m > 1 {
divider(num, m-1) divider(num, m-1)
} }
// m <= num,对剩余未加的数进行划分 // m <= num,对剩余未加的数进行划分
if m <= num { if m <= num {
divider(num-m, m) divider(num-m, m)
} }
} }
divider(num, num) divider(num, num)
return count return count
} }
// Ex6RecursionOutput 整数划分,由上面的递归写法修改而来,可求划分情况,对算法经过调整以适合输出 // Ex6RecursionOutput 整数划分,由上面的递归写法修改而来,可求划分情况,对算法经过调整以适合输出
func Ex6RecursionOutput(num int, callback func(dividedNums []int)) { func Ex6RecursionOutput(num int, callback func(dividedNums []int)) {
var divider func(num, m int, dividedNums []int, callback func(dividedNums []int)) var divider func(num, m int, dividedNums []int, callback func(dividedNums []int))
divider = func(num, m int, dividedNums []int, callback func(dividedNums []int)) { divider = func(num, m int, dividedNums []int, callback func(dividedNums []int)) {
// num==0时,当前已划分完毕,回调输出 // num==0时,当前已划分完毕,回调输出
if num == 0 { if num == 0 {
callback(dividedNums) callback(dividedNums)
return return
} }
// 最大划分大小m逐级-1求划分数 // 最大划分大小m逐级-1求划分数
if m > 1 { if m > 1 {
divider(num, m-1, dividedNums, callback) divider(num, m-1, dividedNums, callback)
} }
if m <= num { if m <= num {
// m <= num,对剩余未加的数进行划分,当前的m已经是划分中的一个成员,将其添加进dividedNums中 // m <= num,对剩余未加的数进行划分,当前的m已经是划分中的一个成员,将其添加进dividedNums中
divider(num-m, m, append(dividedNums, m), callback) divider(num-m, m, append(dividedNums, m), callback)
} }
} }
divider(num, num, make([]int, 0, num), callback) divider(num, num, make([]int, 0, num), callback)
} }
// Ex6NoneRecursion 整数划分,非递归写法,由递归法改写而来,模拟递归过程 // Ex6NoneRecursion 整数划分,非递归写法,由递归法改写而来,模拟递归过程
func Ex6NoneRecursion(num int) int { func Ex6NoneRecursion(num int) int {
divider := func(num, divideMax int) int { divider := func(num, divideMax int) int {
// 初始化 // 初始化
result := make([][]int, num+1) result := make([][]int, num+1)
for i := 0; i < num+1; i++ { for i := 0; i < num+1; i++ {
result[i] = make([]int, num+1) result[i] = make([]int, num+1)
} }
for i := 1; i <= num; i++ { for i := 1; i <= num; i++ {
result[0][i] = 1 result[0][i] = 1
} }
// i从1开始到num进行划分计算, // i从1开始到num进行划分计算,
// 里层j从1开始到m(最大划分大小)开始计算子问题的划分 // 里层j从1开始到m(最大划分大小)开始计算子问题的划分
// 从1开始,自底向上计算 // 从1开始,自底向上计算
// 此处为非递归写法,当前的结果依赖上一个结果,因此需要先计算上一个结果, // 此处为非递归写法,当前的结果依赖上一个结果,因此需要先计算上一个结果,
// 因此整个问题过程需要从最小的问题开始计算 // 因此整个问题过程需要从最小的问题开始计算
divideMax = min(num, divideMax) divideMax = min(num, divideMax)
for n := 1; n <= num; n++ { for n := 1; n <= num; n++ {
for m := 1; m <= divideMax; m++ { for m := 1; m <= divideMax; m++ {
if n <= m { if n <= m {
// 对应 Q(n,n) = 1 + Q(n, n-1) 的情况 // 对应 Q(n,n) = 1 + Q(n, n-1) 的情况
// n < m (n < m) 时均看作i == m (n == m) // n < m (n < m) 时均看作i == m (n == m)
result[n][m] = 1 + result[n][n-1] result[n][m] = 1 + result[n][n-1]
} else { } else {
// 对应 Q(n,m) = Q(n, m-1) + Q(n-m, m) 的情况 // 对应 Q(n,m) = Q(n, m-1) + Q(n-m, m) 的情况
result[n][m] = result[n][m-1] + result[n-m][m] result[n][m] = result[n][m-1] + result[n-m][m]
} }
} }
} }
return result[num][divideMax] return result[num][divideMax]
} }
return divider(num, num) return divider(num, num)
} }

@ -2,25 +2,25 @@ package cap3
// Ex7 低位到高位输出正整数的数字 // Ex7 低位到高位输出正整数的数字
func Ex7(num uint64, algoType AlgoType, callback func(digit uint8)) { func Ex7(num uint64, algoType AlgoType, callback func(digit uint8)) {
switch algoType { switch algoType {
case AlgoTypeRecursion: case AlgoTypeRecursion:
Ex7Recursion(num, callback) Ex7Recursion(num, callback)
default: default:
Ex7NoneRecursion(num, callback) Ex7NoneRecursion(num, callback)
} }
} }
func Ex7Recursion(num uint64, callback func(digit uint8)) { func Ex7Recursion(num uint64, callback func(digit uint8)) {
if num < 10 { if num < 10 {
callback(uint8(num)) callback(uint8(num))
} else { } else {
callback(uint8(num % 10)) callback(uint8(num % 10))
Ex7Recursion(num/10, callback) Ex7Recursion(num/10, callback)
} }
} }
func Ex7NoneRecursion(num uint64, callback func(digit uint8)) { func Ex7NoneRecursion(num uint64, callback func(digit uint8)) {
for i := num; i >= 1; i /= 10 { for i := num; i >= 1; i /= 10 {
callback(uint8(i % 10)) callback(uint8(i % 10))
} }
} }

@ -2,33 +2,33 @@ package cap3
// Ex8 高位到低位输出正整数的数字 // Ex8 高位到低位输出正整数的数字
func Ex8(num uint64, algoType AlgoType, callback func(digit uint8)) { func Ex8(num uint64, algoType AlgoType, callback func(digit uint8)) {
switch algoType { switch algoType {
case AlgoTypeRecursion: case AlgoTypeRecursion:
Ex8Recursion(num, callback) Ex8Recursion(num, callback)
default: default:
Ex8NoneRecursion(num, callback) Ex8NoneRecursion(num, callback)
} }
} }
// Ex8Recursion 高位到低位输出正整数的数字(递归) // Ex8Recursion 高位到低位输出正整数的数字(递归)
func Ex8Recursion(num uint64, callback func(digit uint8)) { func Ex8Recursion(num uint64, callback func(digit uint8)) {
if num < 10 { if num < 10 {
callback(uint8(num)) callback(uint8(num))
} else { } else {
// 跟ex7的小区别 // 跟ex7的小区别
Ex8Recursion(num/10, callback) Ex8Recursion(num/10, callback)
callback(uint8(num % 10)) callback(uint8(num % 10))
} }
} }
// Ex8NoneRecursion 高位到低位输出正整数的数字(非递归) // Ex8NoneRecursion 高位到低位输出正整数的数字(非递归)
func Ex8NoneRecursion(num uint64, callback func(digit uint8)) { func Ex8NoneRecursion(num uint64, callback func(digit uint8)) {
digits := make([]uint8, 0, 20) digits := make([]uint8, 0, 20)
for i := num; i >= 1; i /= 10 { for i := num; i >= 1; i /= 10 {
digits = append(digits, uint8(i%10)) digits = append(digits, uint8(i%10))
} }
for i := len(digits) - 1; i >= 0; i-- { for i := len(digits) - 1; i >= 0; i-- {
callback(digits[i]) callback(digits[i])
} }
} }

@ -2,27 +2,27 @@ package cap3
// Ex9t1 整数拆解为2的幂之和(返回整数的二进制bit取值情况,bit的idx对应相应的幂) // Ex9t1 整数拆解为2的幂之和(返回整数的二进制bit取值情况,bit的idx对应相应的幂)
func Ex9t1(num int) []bool { func Ex9t1(num int) []bool {
// 传进来的是int,一般是32bit,这里就用64来存bit,肯定够了 // 传进来的是int,一般是32bit,这里就用64来存bit,肯定够了
bits := make([]bool, 0, 64) bits := make([]bool, 0, 64)
for i := 0; num != 0; i++ { for i := 0; num != 0; i++ {
bits = append(bits, num%2 == 1) bits = append(bits, num%2 == 1)
num /= 2 num /= 2
} }
return bits return bits
} }
// Ex9t2 整数拆解为2的幂之和(返回幂取值) // Ex9t2 整数拆解为2的幂之和(返回幂取值)
func Ex9t2(num int) []uint8 { func Ex9t2(num int) []uint8 {
// 传进来的是int,一般是32bit,这里就用64来存bit,肯定够了 // 传进来的是int,一般是32bit,这里就用64来存bit,肯定够了
bits := make([]uint8, 0, 64) bits := make([]uint8, 0, 64)
for i := uint8(0); num != 0; i++ { for i := uint8(0); num != 0; i++ {
if num%2 == 1 { if num%2 == 1 {
bits = append(bits, i) bits = append(bits, i)
} }
num /= 2 num /= 2
} }
return bits return bits
} }

Loading…
Cancel
Save