「这是我参与11月更文挑战的第 4 天,活动详情查看:2021最后一次更文挑战」
两数之和
题目来源:LeetCode-1. 两数之和
题目描述
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案
示例
示例 1
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1]
示例 2
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3
输入:nums = [3,3], target = 6
输出:[0,1]
提示:
2 <= nums.length <= 104109 <= nums[i] <= 109109 <= target <= 109- 只会存在一个有效答案
解题
思路
这道题暴力去解,很简单,但是时间复杂度比较高。时间复杂度高的原因是,当我们遍历到nuns中的一个元素之后,需要跟nums中的剩余每一个元素相加,与target进行比较。因此我们就想,如何能高效的根据当前的值,在nums中找到另一个与它相加和为target的值
快速查找,不免会想到散列表。因此,我们可以将nums中的值作为下标,下标作为值,存储到散列表中。这样,当我们遍历到一个值时,拿着target减去该值得到的结果,去散列表中寻找,如果找到了,那这两个值对应的下标就是我们要的;如果没找到则将该数据存入散列表,继续遍历。这样我们就可以在O(n)的时间复杂度下找到这两个数字的下标
代码
func TwoSum(nums []int, target int) []int {
if len(nums) < 2 {
return nil
}
hashMap := make(map[int]int, len(nums))
for j := 0; j < len(nums); j++ {
if v, ok := hashMap[target-nums[j]]; ok {
return []int{j, v}
}
hashMap[nums[j]] = j
}
return nil
}
跳台阶
题目来源:LeetCode-剑指 Offer 10- II. 青蛙跳台阶问题
题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1
示例
示例 1
输入:n = 2
输出:2
示例 2
输入:n = 7
输出:21
示例 3
输入:n = 0
输出:1
解题
思路
这道题经常会看见,一看见大家就会想到使用递归来解。那为什么会想到用递归来解这道题?如果我们知道什么样的题适合用递归来解,不就好了吗?
这里简单说一下适合用递归解的题有哪些特点:
- 一个问题的解可以分解成几个子问题的解
- 子问题除了数据规模不一样,求解思路必须完全一样
- 存在递归终止条件
回到本题,套用上边提到的递归题有哪些特点,看一下本题是否满足这些特点
- **一个问题的解可以分解成几个子问题的解。**求青蛙跳上一个n级的台阶有几种跳法,那如果我知道跳n-1级台阶有多少种跳法不就好了,想知道跳n-1级台阶有多少种跳法,知道跳n-2级台阶有多少种跳法不就好了。....一直到2级台阶有几种跳法
- 从1中可以看出来,n级、n-1级、n-2级、...、2级,这些子问题,除了数据规模不一样,其它都是一样的
- 有递归终止条件,当n=2、n=1的时候,就是终止条件
因此,就可以用递归来解
那如何来解递归题?有没有什么规律?
- 写出递归公式
- 找到递归条件
OK,按照这个规律来解题。求n级台阶的走法,因为每一级台阶都有两种走法,要么一次走一级,要么一次走两级。那如果我想知道n级台阶的走法,不就是第一次走一级和第一次走两级的和吗?因此就可以轻松的得出下边的公式(f(n)是,n级台阶有多少种走法)
f(n) = f(n-1) + f(n-2)
知道了递归公式,下边就是终止条件。这个就简单了
f(2) = 2(分两个一级走,和一次走完两级,两种走法)
f(1) = 1
知道递归公式和终止条件,代码就很好写了
我们知道,递归代码的时间复杂度很高,是指数级的。里边有很多的重复计算,我们可以将计算过的值“缓存起来”,在求某一个的时候,先去缓存里边看有没有,如果有就不再计算了,这样可以有效提高效率(在实际的开发中,也要注意递归深度,避免溢出)
代码
//跳台阶
var depth int
var hashMap = map[int]int{}
func Step(n int) int {
if depth > 1000 {
return -1
}
if n <= 1 {
return 1
}
if n==2 {
return 2
}
if hashMap[n] != 0 {
return hashMap[n]
}
res := Step(n-1) + Step(n-2)
hashMap[n] = res
return res
}