本来以为java回暖了,结果4k还嫌多。。

9a9fd3967a07c93d0692015cbd9686e9.gif

精品推荐

《征服数据结构》专栏:50多种数据结构彻底征服。

《经典图论算法》专栏:50多种经典图论算法全部掌握。

一网友发文称,Java回暖了,大半夜收到几个offer,该网友要求薪资4k左右,结果hr还嫌多,其他网友评论说:这么搞还不如去养猪算了。

4k还嫌多,估计最多也就3千多,也可能是2千多,也可能是……,算了,如果是2千多还不如去养猪了。一天收到上百份java简历,就因为人多,各种压榨,压榨到令人发指的程度。

81c0a1c1eb25c7debb5a585118b3e320.png

c4bbf56c63be7fb25fda4a88239a072c.jpeg

eac7c349bc939df70c83788e9d49ffa2.jpeg

网友评论:

c709306dedae9878fae64ce2a1a29a99.png

--------------下面是今天的算法题--------------

来看下今天的算法题,这题是LeetCode的第132:分割回文串 II。

问题描述

来源:LeetCode第132题

难度:困难

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文串。返回符合要求的最少分割次数 。

示例1:

输入:s = "aab"

输出:1

解释:只需一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。

示例2:

输入:s = "a"

输出:0

  • 1 <= s.length <= 2000

  • s 仅由小写英文字母组成

问题分析

昨天讲过《分割回文串》,昨天那道题让返回的是所有可能的分割方案,而这题让求的是最小分割次数。

这题可以使用动态规划来解决,定义dp[i]表示前 i 个字符的最小分割次数。

1,如果前 i 个字符构成的子串s[0,i]是回文串,则不需要分割,也就是dp[i]=0。

2,否则就尝试分割,从前 i 个字符中不断截取子串s[j,i],判断子串s[j,i]是否是回文串,如果是回文串,表示子串s[j,i]可以单独分割,然后前面分割的最少次数就是dp[j-1],所以dp[i]=min(dp[i],dp[j-1]+1);

这里还是和昨天一样,需要先对所有的子串进行预处理,提前知道哪些是回文的,哪些不是。

JAVA:

public int minCut(String s) {
    int length = s.length();
    int[] dp = new int[length];
    // 判断子串[i…j]是否是回文串
    boolean[][] palindrome = new boolean[length][length];
    for (int j = 0; j < length; j++) {
        for (int i = 0; i <= j; i++) {
            // 如果子串s[j,i]是回文串,则两边的字符s[i]和s[j]必须相同,并且
            // 中间的子串s[i+1,j-1]如果存在,也必须是回文串。
            if (s.charAt(i) == s.charAt(j) && (j - i <= 2 || palindrome[i + 1][j - 1]))
                palindrome[i][j] = true;
        }
    }

    // 字符串s的回文子串最大也只能是字符串的长度,这里都默认初始化为最大值。
    Arrays.fill(dp, length);
    for (int i = 0; i < length; i++) {
        // 如果子串s[0,i]本身就是回文的,就不需要分隔。
        if (palindrome[0][i]) {
            dp[i] = 0;
        } else {
            // 否则就要分隔,找出最小的分隔方案
            for (int j = 0; j <= i; ++j) {
                if (palindrome[j][i])
                    dp[i] = Math.min(dp[i], dp[j - 1] + 1);
            }
        }
    }
    return dp[length - 1];
}

C++:

public:
    int minCut(string s) {
        int length = s.length();
        // 判断子串[i…j]是否是回文串
        vector<vector<bool>> palindrome(length, vector<bool>(length, false));
        for (int j = 0; j < length; j++) {
            for (int i = 0; i <= j; i++) {
                // 如果子串s[j,i]是回文串,则两边的字符s[i]和s[j]必须相同,并且
                // 中间的子串s[i+1,j-1]如果存在,也必须是回文串。
                if (s[i] == s[j] && (j - i <= 2 || palindrome[i + 1][j - 1]))
                    palindrome[i][j] = true;
            }
        }

        // 字符串s的回文子串最大也只能是字符串的长度,这里都默认初始化为最大值。
        vector<int> dp(length, length);
        for (int i = 0; i < length; i++) {
            // 如果子串s[0,i]本身就是回文的,就不需要分隔。
            if (palindrome[0][i]) {
                dp[i] = 0;
            } else {
                // 否则就要分隔,找出最小的分隔方案
                for (int j = 0; j <= i; ++j) {
                    if (palindrome[j][i])
                        dp[i] = min(dp[i], dp[j - 1] + 1);
                }
            }
        }
        return dp[length - 1];
    }

Python:

def minCut(self, s: str) -> int:
    length = len(s)
    # 判断子串[i…j]是否是回文串
    palindrome = [[False] * length for _ in range(length)]
    for j in range(length):
        for i in range(j + 1):
            # 如果i和j指向的字符不一样,那么dp[i][j]就不能构成回文字符串。
            if s[i] == s[j] and (j - i <= 2 or palindrome[i + 1][j - 1]):
                palindrome[i][j] = True

    dp = [length] * length
    for i in range(length):
        # 如果子串s[0, i]本身就是回文的,就不需要分隔。
        if palindrome[0][i]:
            dp[i] = 0
        else:
            # 否则就要分隔,找出最小的分隔方案
            for j in range(i + 1):
                if palindrome[j][i]:
                    dp[i] = min(dp[i], dp[j - 1] + 1)
    return dp[length - 1]

f3b343b7c555725c3490455ebd9d5ba4.gif

笔者简介

博哥,真名:王一博,毕业十多年,《算法秘籍》作者,专注于数据结构和算法的讲解,在全球30多个算法网站中累计做题2000多道,在公众号中写算法题解800多题,对算法题有自己独特的解题思路和解题技巧,喜欢的可以给个关注,也可以下载我整理的1000多页的PDF算法文档。

84f2d6e2695ab721c66bdedc7a86d7c0.gif

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数据结构和算法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值