2020_10_20 每日一题 删造序列II

给定由 N 个小写字母字符串组成的数组 A,其中每个字符串长度相等。

选取一个删除索引序列,对于 A 中的每个字符串,删除对应每个索引处的字符。

比如,有 A = [“abcdef”, “uvwxyz”],删除索引序列 {0, 2, 3},删除后 A 为[“bef”, “vyz”]。

假设,我们选择了一组删除索引 D,那么在执行删除操作之后,最终得到的数组的元素是按 字典序(A[0] <= A[1] <= A[2] …
<= A[A.length - 1])排列的,然后请你返回 D.length 的最小可能值。

示例 1:

输入:
[“ca”,“bb”,“ac”]
输出:1
解释: 删除第一列后,A = [“a”, “b”, “c”]。 现在 A中元素是按字典排列的 (即,A[0] <= A[1] <= A[2])。 我们至少需要进行 1 次删除,因为最初 A不是按字典序排列的,所以答案是 1。
示例 2:

输入:
[“xc”,“yb”,“za”]
输出:0
解释: A 的列已经是按字典序排列了,所以我们不需要删除任何东西。 注意 A 的行不需要按字典序排列。 也就是说,A[0][0] <= A[0][1] <= … 不一定成立。 示例 3:

输入:
[“zyx”,“wvu”,“tsr”]
输出:3
解释: 我们必须删掉每一列。

提示:

1 <= A.length <= 100 1 <= A[i].length <= 100

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/delete-columns-to-make-sorted-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

如果第一列是按从大到小排列的,并且相邻元素不相等,那么之后的都不用检查了;如果第一列是按从大到小排列,但是相邻元素存在相同,那么后面一列只用检查第一列相同的区域,区域内如果出现逆序对就要删除该列。那么就可以写递归了,往后传递需要价差的区域,第一列也可以归到相同的逻辑:

class Solution {
    String[] AA;
    int n;
    int ret; 

    void rec(int col, List<int[]> equals) {
        if(col == n || equals.isEmpty())
            return;//边界条件
        List<int[]> next = new ArrayList<>();//对下一个的问题 只有当这一列不删除的时候才有资格对下一列提问
        for(int[] range : equals) {
            int beg = range[0], end = range[1];
            int i = beg + 1;
            while(i <= end) {
                if(AA[i].charAt(col) < AA[i - 1].charAt(col)) {
                    //出现逆序对 完蛋
                    ++ret;
                    rec(col + 1, equals);
                    return;
                } else if(AA[i].charAt(col) > AA[i - 1].charAt(col)) {
                    ++i;
                } else {
                    int [] r = new int[2];
                    r[0] = i - 1;
                    while(i <= end && AA[i].charAt(col) == AA[i - 1].charAt(col)) {
                        ++i;
                    }
                    r[1] = i - 1;
                    next.add(r);
                }
            }
        }
        rec(col + 1, next);
    }

    public int minDeletionSize(String[] A) {
        //如果用数据结构的迭代感觉麻烦干脆递归算了
        //如果这招不行就抄答案
        AA = A;
        ret = 0;
        if(A.length == 1)
            return 0;
        n = A[0].length();
        List<int[]> equals = new ArrayList<>();
        equals.add(new int[]{0, A.length - 1});
        rec(0, equals);//检查第一列的从0到n-1个字符
        return ret;
    }
}

写的时候有点害怕,会不会出某一列没有逆序对但是删掉更好的情形,后来想想不可能。因为某一列不删掉和删掉相比,对下一列的要求肯定不会变得更严格,所以遇见可以保留的列无脑保留就好

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值