zoukankan      html  css  js  c++  java
  • LeetCode——删除回文子数组

    Q:给你一个整数数组 arr,每一次操作你都可以选择并删除它的一个 回文 子数组 arr[i], arr[i+1], ..., arr[j]( i <= j)。
    注意,每当你删除掉一个子数组,右侧元素都会自行向前移动填补空位。
    请你计算并返回从数组中删除所有数字所需的最少操作次数。

    示例 1:
    输入:arr = [1,2]
    输出:2
    示例 2:
    输入:arr = [1,3,4,1,5]
    输出:3
    解释:先删除 [4],然后删除 [1,3,1],最后再删除 [5]。

    A:
    经典的区间dp,我们令f(i,j)f(i,j)代表删除区间[i,j][i,j]的最小值(即最小删除次数),那么可得以下递推公式:

    分析一下,这里根据a[i]是否等于a[j],分两种情况。因为当a[i] = a[j]的时候,有可能产生最小删除次数的方案是a[i]和a[j]等到最后一起被删。

        public int minimumMoves(int[] arr) {
            int n = arr.length;
            int[][] dp = new int[n][n];
            // 单个字符也是回文串,删除单个字符的最小删除次数就是1
            for (int i = 0; i < n; i++) {
                dp[i][i] = 1;
            }
    
            for (int j = 1; j < n; j++) {
                for (int i = j - 1; i >= 0; i--) {
                    if (i == j - 1) {
                        // 就两个元素
                        dp[i][j] = arr[i] == arr[j] ? 1 : 2;
                        continue;
                    }
                    // 下面至少三个元素
                    int min = Integer.MAX_VALUE;
                    if (arr[i] == arr[j]) {
                        // 头尾相等,最小值有可能是出现在这对头尾最后被删的结果
                        min = dp[i + 1][j - 1];
                    }
    
                    for (int k = i; k < j; k++) {
                        min = Math.min(min, dp[i][k] + dp[k + 1][j]);
                    }
                    dp[i][j] = min;
                }
            }
            return dp[0][n - 1];
        }
    
  • 相关阅读:
    Linux基本结构
    Linux诞生
    Python之克隆
    Python之数据类型转换
    gb18030与utf-8
    for循环与while循环
    code::blocks调试
    关于隐式创建vue实例实现简化弹出框组件显示步骤
    blob canvas img dataUrl的互相转换和用处
    观察者模式与发布订阅模式的区别
  • 原文地址:https://www.cnblogs.com/xym4869/p/13662210.html
Copyright © 2011-2022 走看看