2351. 第一个出现两次的字母-简单
题目描述:
给你一个由小写英文字母组成的字符串 s ,请你找出并返回第一个出现 两次 的字母。
注意:
如果 a 的 第二次 出现比 b 的 第二次 出现在字符串中的位置更靠前,则认为字母 a 在字母 b 之前出现两次。
s 包含至少一个出现两次的字母。
题解:
哈希表
代码(Go):
func repeatedCharacter(s string) byte {
dict := map[rune]int{}
for _,v := range s{
if _,ok := dict[v];ok{
return byte(v)
}else{
dict[v] = 1
}
}
return s[0]
}
2395. 和相等的子数组-简单
题目描述:
给你一个下标从 0 开始的整数数组 nums ,判断是否存在 两个 长度为 2 的子数组且它们的 和 相等。注意,这两个子数组起始位置的下标必须 不相同 。
如果这样的子数组存在,请返回 true,否则返回 false 。
子数组 是一个数组中一段连续非空的元素组成的序列。
题解:
哈希表存储两个相邻元素的和,查看有无重复
代码(Go):
func findSubarrays(nums []int) bool {
dict := map[int]bool{}
for i := 1; i < len(nums); i++ {
temp := nums[i-1] + nums[i]
if dict[temp] {
return true
}
dict[temp] = true
}
return false
}
276. 栅栏涂色-中等
题目描述:
有 k 种颜色的涂料和一个包含 n 个栅栏柱的栅栏,请你按下述规则为栅栏设计涂色方案:
每个栅栏柱可以用其中 一种 颜色进行上色。
相邻的栅栏柱 最多连续两个 颜色相同。
给你两个整数 k 和 n ,返回所有有效的涂色 方案数 。
题解:
动态规划,仔细观察可以发现i个栅栏的涂色方案实际上与i-3个栅栏的涂色方案有关联,因为最多连续两个颜色相同,很容易想到可以用没有限制的情况减掉出现三个颜色相同的情况,所以dp[i]=dp[i-1]k(没有限制的情况下dp[i]的值)-dp[i-3](k-1)(只有当前两个颜色相同时会出现三个颜色相同的情况)后者实际上是dp[i-3]/k*(k-1)*k(dp[i-3]的所有情况除以k种颜色得到单个颜色所有情况,再乘上与此单个颜色不等的另外k-1种颜色再乘上k种颜色的情况)根据转移方程写出代码即可。题解大部分人都是额外用一个标记位标记两种颜色是否相等,和我写的都不一样
代码(Go):
func numWays(n int, k int) int {
if n == 1{
return k
}else if n == 2{
return k * k
}
dp := make([]int,n)
dp[0] = k
dp[1] = k*k
dp[2] = k*k*k - k
for i := 3;i < n;i++{
dp[i] = dp[i - 1] * k - dp[i - 3] * (k - 1)
}
return dp[n - 1]
}
322. 零钱兑换-中等
题目描述:
给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。
计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。
你可以认为每种硬币的数量是无限的。
题解:
动态规划,从前往后保存每个金额需要的最少硬币,每个金额的最少硬币取决于之前的状态,枚举coins中的每个值,取dp[i-coin]中的最小值+1即可得到当前金额所需的最少硬币
代码(Go):
func coinChange(coins []int, amount int) int {
dp := make([]int,amount + 1)
dp[0] = 0
for i := 1;i <= amount;i++{
temp := 10001
for _,v := range coins{
if i - v >= 0 && dp[i - v] != -1{
if temp > dp[i - v]{
temp = dp[i - v]
}
}
}
if temp == 10001{
dp[i] = -1
}else{
dp[i] = temp + 1
}
}
return dp[amount]
}
总结
目前需要用二维数组记录同一个点的多种状态这种类型的动态规划还是不会做,只能做做只需要记录一种状态的动态规划,转移方程是真的难找,梦回初高中做题画辅助线