Golang语法的25个练习题:16至20题

2023-02-23
2分钟阅读时长

题目16:大衍数列

中国古代文献中,曾记载过“大衍数列”,主要用于解释中国传统文化中的太极衍生原理

它的前几项是:0、2、4、8、12、18、24、32、40、50…

其规律是:偶数项,是序号平方再除2,奇数项,是序号平方减1再除2。

打印大衍数列的前100项

package main

import (
	"fmt"
	"math"
)

func main() {
	for i := 1; i <= 100; i++ {
		var a int
		if i%2 == 0 { // 偶数
			a = int(math.Pow(float64(i), 2)) / 2
		} else { // 奇数
			a = (int(math.Pow(float64(i), 2)) - 1) / 2
		}
		fmt.Println("//", a)
	}
	// 0
	// 2
	// 4
	// 8
	// 12
	// 18
	// 24
	// 32
	// 40
	// 50
}

题目17:单词分析

  • 小蓝正在学习一门神奇的语言,这门语言中的单词都是由小写英文字母组成,有些单词很长,远远超过正常英文单词的长度。小蓝学了很长时间也记不住一些单词,他准备不再完全记忆这些单词,而是根据单词中哪个字母出现得最多来分辨单词
  • 现在,请你帮助小蓝,给了一个单词后,帮助他找到出现最多的字母和这个字母出现的次数
  • 其实就是让你输入一段字符串后,得到当前字符串出现最多的字母和它的次数
  • 输入:HelloWorld
  • 输出:
  • l
  • 3
  • 我们可以对当前的字符串进行循环迭代,然后把字符串当前每个字符当作key值,把它存到字典里面,如果当前key在字典里面,我们就让它加一,如果不在那我们就让它的次数初始化为1,最终我们再从字典找到次数最多的key值和value值
package main

import "fmt"

func main() {
	analyseWords("helloworld")
	// l 3
}

func analyseWords(word string) {
	wordDict := map[rune]int{}
	var (
		count int
		ch    rune
	)
	for _, c := range word {
		wordDict[c]++
		if wordDict[c] > count {
			count, ch = wordDict[c], c
		}
	}
	fmt.Println(string(ch), count)
}

题目18:利用栈打印菱形

输入边长n,打印对应边长的菱形

分析:

  1. 打印几行
  2. 每一行打印几个空格,几个星星
  3. 前几行打印之前加入到栈,利用栈的后进先出原则打印后几行的内容
package main

import (
	"fmt"
	"strings"
)

func main() {
	diamond(5)
	//     *
	//    ***
	//   *****
	//  *******
	// *********
	//  *******
	//   *****
	//    ***
	//     *
}

func diamond(n int) {
	var stack []string
	for i := 1; i < 2*n; i++ {
		var pStr string
		if i <= n {
			pStr = strings.Repeat(" ", n-i) + strings.Repeat("*", 2*i-1)
			if i != n {
				stack = append(stack, pStr)
			}
		} else {
			pStr = stack[len(stack)-1]
			stack = stack[:len(stack)-1]
		}
		fmt.Println("//", pStr)
	}
}

题目19:深入理解递归函数

什么是递归函数?

递归函数就是一个函数在它的函数体内调用它自身。执行递归函数将反复调用其自身,每调用一次就进入新的一层。

递归函数必须有结束条件。

设计递归函数三要素:

  1. 明确你这个函数想要干什么
  2. 寻找递归结束条件
  3. 找出函数的等价关系式
package main

import "fmt"

func main() {
	p(5)
	//递归前-> 5
	//递归前-> 4
	//递归前-> 3
	//递归前-> 2
	//递归前-> 1
	//递归后-> 1
	//递归后-> 2
	//递归后-> 3
	//递归后-> 4
	//递归后-> 5
}

func p(n int) {
	if n == 0 {
		return
	}
	fmt.Println("//递归前->", n)
	defer fmt.Println("//递归后->", n)
	p(n - 1)
}

题目20:斐波那契递归函数

斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:

1、1、2、3、5、8、13、21、34、…

这个数列,前两项都是数字1,从第三项开始,每一项数字是前两项数字之和

关系表达式【f(n) = f(n-1)+f(n-2)】

package main

import "fmt"

func main() {
	fmt.Println(fib(10))  //89
	fmt.Println(fib(2))   //2
	fmt.Println(fib(5))   //8
	fmt.Println(fib2(10)) //89
	fmt.Println(fib2(2))  //2
	fmt.Println(fib2(5))  //8
}

func fib(n int) int {
	if n <= 2 {
		return n
	}
	return fib(n-1) + fib(n-2)
}

var mp = map[int]int{}

func fib2(n int) int {
	if n <= 2 {
		return n
	}
	// 记忆化递归
	if k, ok := mp[n]; ok {
		return k
	}
	return fib(n-1) + fib(n-2)
}

递归与栈的关系

递归函数原理:每一次调用都会把当前调用压入到栈里,最后按照后进先出的原则,不停返回返回

由递归程序的执行过程,我们得知递归程序的调用是一层层向下的,而返回过程则恰好相反,一层层向上。

换个说法:最先一次的函数调用在最后返回,而最后一次的函数调用则是最先返回。这就跟栈的“后进先出”次序是一样的。因此,在实现递归调用的时候,通常就会使用栈来保存每一次调用的现场数据:

  • 当一个函数被调用的时候,系统会把调用时的现场数据压入到系统调用栈,压入栈的现场数据称为栈帧。
  • 当函数返回时,要从调用栈的栈顶取得返回地址,恢复现场,弹出栈帧,按地址返回。

python原文:https://www.52pojie.cn/thread-1689186-1-1.html

关注公众号获得更多精彩文章

公众号:程序员大兵