前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >力扣664. 奇怪的打印机

力扣664. 奇怪的打印机

作者头像
才浅Coding攻略
发布2022-12-12 17:04:54
2660
发布2022-12-12 17:04:54
举报
文章被收录于专栏:才浅coding攻略

阿巩

一切已妥当,绝不咕咕!

阿巩想死你们了!今日起恢复日更。由于被再三嘱咐不能熬夜,如果当天时间充裕的话,会学习并及时输出干货;时间比较紧则在次日上班前更新一道数据结构或算法题。日拱一卒,我们开始吧!

在之前分享动态规划的文章中,我们说动态规划主要是用于解决求最值的问题的。它希望上一个状态和下一个状态之间有关系而且连续。对于本题来说求打印次数有以下几种情况:

1、只有一个字符a:1次

2、打印字符ab:2次

3、打印字符aba:2次

4、打印字符abab:3次

我们可以看出两点规律:首先判断区间两边字符是否相同,如果相同(aba),它的打印次数与更小一层的子区间结果一致;如果不相同(abab)那么将对剩区间内的组合方式进行枚举,并取出最小值。

状态定义:[i, j]表示从i到j的一个区间,dp[i][j]表示最少打印次数。

状态转移方程:如果s[i] == s[j]即区间两边字符相同,那么dp[i][j] = dp[i][j-1]即与更小一层的子区间结果一致;如果s[i] 和s[j]不相等,则进行枚举并返回最小值 min(dp[i][j], dp[i][k] + dp[k+1][j])。

初始状态:n 是字符串的长度。dp数组抽象成一个n * n 的矩阵。dp = [[n] * n for _ in range(n)]

返回值:dp[0][n-1]

Python的区间DP代码如下

代码语言:javascript
复制
def strangePrinter(s):
    n = len(s)
    dp = [[n] * n for _ in range(n)]
    for i in range(n-1, -1, -1):
        dp[i][i] = 1
        for j in range(i+1, n):
            if s[i] == s[j]:
                dp[i][j] = dp[i][j-1]
            else:
                for k in range(i, j):
                    dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j])
    return dp[0][n-1]


s = "abab"
print(strangePrinter(s))  # 3

用GO语言实现代码如下

代码语言:javascript
复制
package main

func strangePrinter(s string) int {
  n := len(s)
  dp := make([][]int, n)
  for i := 0; i < n; i++{
    dp[i] = make([]int, n)
  }
  for i := n-1; i >= 0; i-- {
    for j := i; j < n; j++ {
      if i == j {
        dp[i][j] = 1
        continue
      }
      if s[i] == s[j] {
        dp[i][j] = dp[i][j-1]
        continue
      }
      min := j-i+1
      for k := i; k < j; k++ {
        tmp := dp[i][k] + dp[k+1][j]
        if tmp < min {
          min = tmp
        }
      }
      dp[i][j] = min
    }
  }
  return dp[0][n-1]
}

func main() {
  s := "abab"
  println(strangePrinter(s))  // 3
}

除了区间DP,本题还可以使用记忆化DFS+剪枝的思路理解,代码实现与dp类似。

预处理:将连续的,由相同字符组成的子串看做一个。比如"aaabbb"和"ab"是没有区别的。

递推:如果j和i是相同的,那么打印i到j和打印i到j-1所需的次数是一样的;如果i和j不同,找出所有拆分方法中的最小值。

代码语言:javascript
复制
from functools import lru_cache


def strangePrinter(s):
    printer = [s[0]]
    for i in range(1, len(s)):
        if s[i] != s[i-1]:
            printer.append(s[i])

    @ lru_cache(None)
    def dfs(i, j):
        if i > j:
            return 0
        elif i == j:
            return 1
        if printer[i] == printer[j]:
            return dfs(i, j-1)
        return min(dfs(i, k) + dfs(k+1, j) for k in range(i, j))

    return dfs(0, len(printer)-1)


s = "aabaaab"
print(strangePrinter(s))  # 3

END

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-05-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 才浅coding攻略 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档