Go语言基础语法练习 | 青训营

297 阅读3分钟

试着使用Go语言完成了两道简单的题目。
感觉语法还是,写了就忘,忘了就查🥲

LeetCode654 最大二叉树 
给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:

  1. 创建一个根节点,其值为 nums 中的最大值。
  2. 递归地在最大值 左边 的 子数组前缀上 构建左子树。
  3. 递归地在最大值 右边 的 子数组后缀上 构建右子树。

返回 nums 构建的 最大二叉树 。

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func maxIdx(nums []int, l int, r int) int {
	var idx = l
	for i := l + 1; i < r; i++ {
		if nums[idx] < nums[i] {
			idx = i
		}
	}
	return idx
}
//前开后闭区间
func constructor(nums []int,l int,r int) *TreeNode {
	if l >= r {
		return nil 
	}
	idx := maxIdx(nums,l,r)
	return &TreeNode{nums[idx],constructor(nums,l,idx),constructor(nums,idx+1,r)}
}
func constructMaximumBinaryTree(nums []int) *TreeNode {
	return constructor(nums,0,len(nums))
}
复制代码

题目本身是相当简单的二叉树基础题:只需要找到数组最大值的下标,创建一个新的二叉树节点,再去递归地构建它的左右子树。递归的终点即左指针大于等于右指针的时候(这个时候左右指针范围内的子数组已经不存在元素了)。所以我将它作为我巩固Go语言基础语法的练习的第一题。

用到了Go语言的循环语句(其实和c++/Java等一众语言都很像,只是把括号去掉了罢了),但是值得注意的是Go语言的似乎并不支持++i 。和过去一段时间写C++养成的习惯有些许冲突。
在这里展示一下C++和go在循环语法上的差别\

for(int i = 0;i < n; ++i){ 
    ...
}
for i := 0 ;i < n ; i++ {
    ···
}

尝试了变量名 := 值 和var 变量名 = 值两种不同的变量声明方式,
Go语言函数的定义func 函数名 (参数列表) 返回值 {}
和Go语言函数返回指针变量的方式(只需要加个&就行)\

LeetCode 442 数组中重复的数据
给你一个长度为 n 的整数数组 nums ,其中 nums 的所有整数都在范围 [1, n] 内,且每个整数出现 一次 或 两次 。请你找出所有出现 两次 的整数,并以数组形式返回。

你必须设计并实现一个时间复杂度为 O(n) 且仅使用常量额外空间的算法解决此问题。

func findDuplicates(nums []int) []int {
	//由于下标从0开始,而根据题目所给数据范围,nums[i]为 1 ~ n 中的整数
	for i := 0; i < len(nums); i++ {
		for nums[i] != nums[nums[i]-1] {
			nums[i],nums[nums[i] - 1] = nums[nums[i] - 1],nums[i]//go的交换语法
		}
	}
	var ans []int //初始化为空
	for i := 0; i < len(nums); i++ {
		if i != nums[i] - 1 {
			ans = append(ans, nums[i])
		}
	}
	return ans
}

这道题是一个原地哈希的问题,第一个for循环将数组中的元素根据 “把 num 放在下标 num - 1 处的对应关系” 放在其对应的位置

例如 {4,5,1,4,5}要重新摆放为 {1,5,4,4,5} ,1放在下标 0 处,4放在下标 3 处,5放在下标 4 处(即 nums[i] 放在下标 nums[i] - 1 处)。完成重新排列后,我们再遍历一次数组,就可以将所有不存在对应关系的位置上的元素加入答案集合了

写这道题时用到了go语言的交换语句 a,b = b,a 和 切片的简单操作。
对比一下声明go语言切片和go语言数组我们会发现,其实go语言数组在定义时的不同也不过就是在[]里面加上了一个数字来指定大小。go语言的切片具有着与c++的vector,Java的ArrayList相似的用法,并且go语言的切片和c++vector一样会动态扩容。但是切片有着后者不具备的神奇特性,那就是直接可以作为一个数组返回,这样的功能确实使代码编写变得极其便捷。