Leetcode.1849 将字符串拆分为递减的连续值

Posted 感觉画质不如…原神

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode.1849 将字符串拆分为递减的连续值相关的知识,希望对你有一定的参考价值。

题目链接

Leetcode.1849 将字符串拆分为递减的连续值 Rating : 1747

题目描述

给你一个仅由数字组成的字符串 s

请你判断能否将 s拆分成 两个或者多个 非空子字符串 ,使子字符串的 数值降序 排列,且每两个 相邻子字符串 的数值之 等于 1

  • 例如,字符串 s = "0090089"可以拆分成 ["0090", "089"],数值为 [90,89]。这些数值满足按降序排列,且相邻值相差 1 ,这种拆分方法可行。
  • 另一个例子中,字符串 s = "001"可以拆分成 ["0", "01"]["00", "1"]["0", "0", "1"]。然而,所有这些拆分方法都不可行,因为对应数值分别是 [0,1]、[0,1][0,0,1],都不满足按降序排列的要求。

如果可以按要求拆分 s,返回 true ;否则,返回 false

子字符串 是字符串中的一个连续字符序列。

示例 1:

输入:s = “1234”
输出:false
解释:不存在拆分 s 的可行方法。

示例 2:

输入:s = “050043”
输出:true
解释:s 可以拆分为 [“05”, “004”, “3”] ,对应数值为 [5,4,3] 。
满足按降序排列,且相邻值相差 1 。

示例 3:

输入:s = “9080701”
输出:false
解释:不存在拆分 s 的可行方法。

示例 4:

输入:s = “10009998”
输出:true
解释:s 可以拆分为 [“100”, “099”, “98”] ,对应数值为 [100,99,98] 。
满足按降序排列,且相邻值相差 1 。

提示:

  • 1 < = s . l e n g t h < = 20 1 <= s.length <= 20 1<=s.length<=20
  • s仅由数字组成

解法:模拟

提示1:题目要求相邻字符串数值之差为1,说明当确定第一个字符串时,后续字符串的数值也就确定了。

提示2:题目要求最少分成两个串,s.size()最大才是 20,一个子串的值不能超过 1 0 10 10^10 1010,超过就无解了。

pre表示第一段子串的值,用 cur表示接下来每一段子串 实际的值,用 next表示接下来每一段子串 正确的值

时间复杂度: O ( n 2 ) O(n^2) O(n2)

C++代码:

using LL = long long;
class Solution 
public:
    bool splitString(string s) 
        int n = s.size();
        //第一段子串的值 和 子串最大的值
        LL pre = 0,mx = 1e10;

        for(int i = 0;i < n;i++)
            pre = pre * 10 + (s[i] - '0');
            //如果有子串的值 > mx 后面也不会有解了
            if(pre > mx) break;

            //cur 表示接下来每一段 实际的值
            //next 表示接下来每一段 符合条件的值
            LL cur = 0;
            LL next = pre - 1;
            
            for(int j = i + 1;j < n && next >= 0;j++)
                cur = cur * 10 + (s[j] - '0');
                //这一段子串的值符合要求,更新 next 和 cur 开始寻找下一段
                //只有当 cur 的这一段是最后一段时,并且 cur == next , cur 才允许为0 if((cur == next && cur != 0) || (cur == next && cur == 0 && j == n - 1))
                    cur = 0;
                    next--;
                    //当前已经是最后一段,说明s 可以分解为题目要求的非空子串,直接返回 true
                    if(j == n - 1) return true;
                
                //cur > next 说明该段不符合要求,直接退出循环
                else if(cur > next) break;
            
        

        return false;
    
;

5747. 将字符串拆分为递减的连续值

题目链接:https://leetcode-cn.com/problems/splitting-a-string-into-descending-consecutive-values/

思路:每次截取一段“符合题目条件”的字符串(第一段不用,当然第一段数过大也需要break),然后从当前位置往后递归即可。由于判断的时候需要判断相邻相差1,因为不能用大数,所以我们就判断是不是>100L*Integer.MAX_VALUE即可,也不一定是这个数,只要满足不可能出现下一个与当前数相差是1的数即可(原因是为了防止越界Long,也是剪枝)。剪枝:(1)判断是不是>100L*Integer.MAX_VALUE,大于直接返回,不大于继续执行循环体 (2)判断相邻的差,小于0直接返回,等于1继续递归,大于1继续执行循环体

上代码:

class Solution {
   public boolean splitString(String s) {
        if (s.length() <= 1) {
            return false;
        }
        boolean flag = false;
        for (int i = 0; i < s.length() - 1; i++) {
            String substring = s.substring(0, i + 1);
            if (Long.parseLong(substring) > 100L * Integer.MAX_VALUE) {
                break;
            }
            flag = dfs(substring, i + 1, s);
            if (flag) {
                break;
            }
        }
        return flag;
    }

    public boolean dfs(String str, int index, String s) {
        if (index == s.length()) {
            return true;
        }
        for (int i = index; i < s.length(); i++) {
            String substring = s.substring(index, i + 1);
            if (Long.parseLong(substring) > 100L * Integer.MAX_VALUE) {
                return false;
            }
            long x = Long.parseLong(str) - Long.parseLong(substring);
            if (x < 0L) {
                return false;
            }
            if (x == 1L && dfs(substring, i + 1, s)) {
                return true;
            }
        }
        return false;
    }
}

 

以上是关于Leetcode.1849 将字符串拆分为递减的连续值的主要内容,如果未能解决你的问题,请参考以下文章

使用 itertools 将列表拆分为递增的序列

整数拆分

pandas:将具有相同值的连续行分组为一组

将字符串拆分为字符串数组[重复]

如何将字符串拆分为列表?

如何将字符串中的“\t”拆分为两个单独的字符“\”和“t”? (如何拆分转义序列?)[重复]