[剑指offer] 动态规划篇

发布时间 2023-09-26 21:25:48作者: Vivid-BinGo

JZ42 连续子数组的最大和

/* 贪心 */
public class JZ42_1
{
    public static int FindGreatestSumOfSubArray(int[] array)
    {
        int sum = 0, res = Integer.MIN_VALUE;
        for (int i = 0; i < array.length; i++)
        {
            sum += array[i];
            res = Math.max(res, sum);
            if (sum < 0)
                sum = 0;
        }
        return res;
    }
}

/*
* dp
* dp[i]:以 array[i] 结尾的连续子数组最大和。
* 状态转移方程: dp[i] = Math.max(dp[i-1] + array[i], array[i]);
* */
public class JZ42_2
{
    public static int FindGreatestSumOfSubArray(int[] array)
    {
        int[] dp = new int[array.length];
        int res = array[0];
        dp[0] = array[0];
        for (int i = 1; i < array.length; i++)
        {
            dp[i] = Math.max(array[i], dp[i - 1] + array[i]);
            res = Math.max(res, dp[i]);
        }
        return res;
    }
}

JZ85 连续子数组的最大和(二)

/* 贪心(与JZ42类似) */
public class JZ85_1
{
    public static int[] FindGreatestSumOfSubArray(int[] array)
    {
        int sum = 0, mmax = Integer.MIN_VALUE, len = -1, start = 0, idx = 0;
        for (int i = 0; i < array.length; i++)
        {
            sum += array[i];
            if (mmax == sum)
            {
                if (i - idx + 1 > len)
                {
                    len = i - idx + 1;
                    start = idx;
                }
            }
            if (mmax < sum)
            {
                mmax = sum;
                len = i - idx + 1;
                start = idx;
            }
            if (sum < 0)
            {
                idx = i + 1;
                sum = 0;
            }
        }
        int[] res = new int[len];
        System.arraycopy(array, start, res, 0, len);
        return res;
    }
}

/*
 * dp
 * dp[i]:以 array[i] 结尾的连续子数组最大和。
 * 状态转移方程: dp[i] = Math.max(dp[i-1] + array[i], array[i]);
 * (与JZ42类似)
 * */
public class JZ85_2
{
    public static int[] FindGreatestSumOfSubArray(int[] array)
    {
        int[] dp = new int[array.length];
        int mmax = array[0], idx = 0, start = 0, len = 1;
        dp[0] = array[0];
        for (int i = 1; i < array.length; i++)
        {
            dp[i] = dp[i - 1] + array[i];
            if (dp[i] < array[i])
            {
                dp[i] = array[i];
                idx = i;
            }
            if (mmax == dp[i])
            {
                if (i - idx + 1 > len)
                {
                    len = i - idx + 1;
                    start = idx;
                }
            }
            if (mmax < dp[i])
            {
                len = i - idx + 1;
                start = idx;
                mmax = dp[i];
            }
        }
        int[] res = new int[len];
        System.arraycopy(array, start, res, 0, len);
        return res;
    }
}

JZ69 跳台阶

/*
* dp
* dp[n]: 跳 n 级台阶,有 dp[n] 种跳法
* 状态转移方程: dp[n]=dp[n-1]+dp[n-2]
* */
public class JZ69_1
{
    public static int jumpFloor(int number)
    {
        if (number <= 2) return number;
        int[] dp = new int[number + 1];
        dp[1] = 1;
        dp[2] = 2;
        for (int i = 3; i <= number; i++)
            dp[i] = dp[i - 1] + dp[i - 2];
        return dp[number];
    }
}

/* 递归 */
public class JZ69_2
{
    public static int jumpFloor(int number)
    {
        if (number <= 2) return number;
        return jumpFloor(number - 1) + jumpFloor(number - 2);
    }
}

JZ10 斐波那契数列

/* 递推 */
public class JZ10_1
{
    public static int Fibonacci(int n)
    {
        if (n < 3) return 1;
        int x1 = 1, x2 = 1;
        for (int i = 3; i <= n; i++)
        {
            x2 = x1 + x2;
            x1 = x2 - x1;
        }
        return x2;
    }
}

/* 递归+备忘录 */
public class JZ10_2
{
    public static int[] memo = new int[50];

    public static int Fibonacci(int n)
    {
        if (memo[n] != 0) return memo[n];
        if (n <= 2) return 1;
        else
        {
            memo[n] = Fibonacci(n - 1) + Fibonacci(n - 2);
            return memo[n];
        }
    }
}

JZ19 正则表达式匹配⭐

/* 递归 */
public class JZ19_1
{
    public static boolean match(String str, String pattern)
    {
        return match(str, 0, pattern, 0);
    }

    private static boolean match(String str, int sIdx, String pattern, int pIdx)
    {
        if (str.length() == sIdx && pattern.length() == pIdx) return true;
        if (pattern.length() == pIdx) return false;
        boolean res = false;
        if (pIdx + 1 < pattern.length() && pattern.charAt(pIdx + 1) == '*')
            if (sIdx < str.length() && (str.charAt(sIdx) == pattern.charAt(pIdx) || pattern.charAt(pIdx) == '.'))
                return match(str, sIdx, pattern, pIdx + 2) || match(str, sIdx+1, pattern , pIdx + 2) || match(str, sIdx+1, pattern, pIdx);
            else
               return match(str, sIdx, pattern, pIdx + 2);
        else
        {
            if (sIdx < str.length() && (str.charAt(sIdx) == pattern.charAt(pIdx) || pattern.charAt(pIdx) == '.'))
                return match(str, sIdx + 1, pattern, pIdx + 1);
            else return false;
        }
    }
}

/* dp */
public class JZ19_2
{
    public boolean match(String str, String pattern)
    {
        int n = str.length();
        int m = pattern.length();
        boolean[][] f = new boolean[n + 1][m + 1];

        for (int i = 0; i <= n; i++)
        {
            for (int j = 0; j <= m; j++)
            {
                if (j == 0)
                    f[i][j] = i == 0;
                else
                {
                    if (pattern.charAt(j - 1) != '*')
                    {
                        if (i > 0 && (str.charAt(i - 1) == pattern.charAt(j - 1) || pattern.charAt(j - 1) == '.'))
                            f[i][j] = f[i - 1][j - 1];
                    }
                    else
                    {
                        if (j >= 2)
                            f[i][j] |= f[i][j - 2];
                        if (i >= 1 && j >= 2 && (str.charAt(i - 1) == pattern.charAt(j - 2) || pattern.charAt(j - 2) == '.'))
                            f[i][j] |= f[i - 1][j];
                    }
                }
            }
        }
        return f[n][m];
    }
}

JZ71 跳台阶扩展问题

/* 找规律 */
public class JZ71_1
{
    public static int jumpFloorII(int number)
    {
        return (int) Math.pow(2,number-1);
    }
}

/* dp */
public class JZ71_2
{
    public static int jumpFloorII(int number)
    {
        if (number <= 2) return number;
        int[] dp = new int[number + 1];
        dp[0] = 1;
        dp[1] = 1;
        dp[2] = 2;
        for (int i = 3; i <= number; i++)
            for (int j = 0; j < i; j++)
                dp[i] += dp[j];
        return dp[number];
    }
}

JZ70 矩形覆盖

/* 找规律 */
public class JZ70_1
{
    public static int rectCover(int target)
    {
        if (target == 0) return 0;
        if (target <= 2) return target;
        return rectCover(target - 1) + rectCover(target - 2);
    }
}

JZ63 买卖股票的最好时机(一)⭐

/*
 * dp
 * dp[i][0]: 第i天不持股; dp[i][1]: 第i天持股;
 * 状态转移方程:
 * dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1] + prices[i]);
 * dp[i][1] = Math.max(dp[i-1][1], -prices[i]);
 * */
public class JZ63_1
{
    public static int maxProfit(int[] prices)
    {
        int[][] dp = new int[prices.length + 1][2];
        dp[0][1] = -prices[0];
        dp[0][0] = 0;
        for (int i = 1; i < prices.length; i++)
        {
            dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
            dp[i][1] = Math.max(dp[i - 1][1], -prices[i]);
        }
        return dp[prices.length - 1][0];
    }
}

JZ47 礼物的最大价值

/* dp */
public class JZ47_1
{
    public static int maxValue(int[][] grid)
    {
        int m = grid.length, n = grid[0].length;
        int[][] dp = new int[m][n];
        dp[0][0] = grid[0][0];
        for (int i = 1; i < n; i++)
            dp[0][i] = dp[0][i - 1] + grid[0][i];
        for (int i = 1; i < m; i++)
            dp[i][0] = dp[i - 1][0] + grid[i][0];
        for (int i = 1; i < m; i++)
            for (int j = 1; j < n; j++)
                dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
        return dp[m - 1][n - 1];
    }
}

/* dfs+memo */
public class JZ47_2
{
    public static int[][] memo;

    public static int maxValue(int[][] grid)
    {
        int m = grid.length, n = grid[0].length;
        memo = new int[m][n];
        return dfs(grid, m - 1, n - 1);
    }

    public static int dfs(int[][] grid, int x, int y)
    {
        if (memo[x][y] != 0) return memo[x][y];
        if (x == 0 && y == 0) return memo[x][y] = grid[0][0];
        if (x == 0) return memo[x][y] = grid[x][y] + dfs(grid, x, y - 1);
        if (y == 0) return memo[x][y] = grid[x][y] + dfs(grid, x - 1, y);
        return memo[x][y] = grid[x][y] + Math.max(dfs(grid, x, y - 1), dfs(grid, x - 1, y));
    }
}

JZ48 最长不含重复字符的子字符串

/* 滑动窗口 */
public class JZ48_1
{
    public static int lengthOfLongestSubstring(String s)
    {
        int res = Integer.MIN_VALUE, left = 0, right = 0;
        while (right < s.length())
        {
            while (left < right && s.substring(left, right).contains("" + s.charAt(right)))
                left++;
            right++;
            res = Math.max(res, right - left);
        }
        return res;
    }
}

public class JZ48_2
{
    public static int lengthOfLongestSubstring(String s)
    {
        int[] dp = new int[s.length()];
        int[] start = new int[s.length()];
        int res = 1;
        dp[0] = 1;
        start[0] = 0;
        for (int i = 1; i < s.length(); i++)
        {
            if (s.substring(start[i - 1], i).contains("" + s.charAt(i)))
            {
                int temp = s.substring(start[i - 1], i).indexOf("" + s.charAt(i)) + start[i - 1];
                dp[i] = i - temp;
                start[i] = temp + 1;
            }
            else
            {
                dp[i] = dp[i - 1] + 1;
                start[i] = start[i - 1];
            }
            res = Math.max(res, dp[i]);
        }
        return res;
    }
}

JZ46 把数字翻译成字符串⭐

/* dp */
public class JZ46_1
{
    public static int solve(String nums)
    {
        if (nums.length() == 0) return 0;
        if (nums.charAt(0) == '0') return 0;
        if (nums.length() == 1) return 1;
        int[] dp = new int[nums.length()];
        dp[0] = 1;
        dp[1] = 1;
        if (new Integer(nums.substring(0, 2)) <= 26 && nums.charAt(1) != '0')
            dp[1]++;
        for (int i = 2; i < nums.length(); i++)
        {
            if (nums.charAt(i) == '0')
            {
                if (nums.charAt(i - 1) == '1' || nums.charAt(i - 1) == '2')
                    dp[i] = dp[i - 2];
                else
                    break;
            }
            else
            {
                dp[i] = dp[i - 1];
                if (nums.charAt(i - 1) != '0' && new Integer(nums.substring(i - 1, i + 1)) <= 26)
                    dp[i] += dp[i - 2];
            }

        }
        return dp[nums.length() - 1];
    }
}

/* 递归 */
public class JZ46_2
{
    public int solve(String nums)
    {
        return back(nums.toCharArray(), 0);
    }

    public int back(char[] nums, int start)
    {
        if (start == nums.length) return 1;
        if (nums[start] == '0') return 0;
        int res1 = back(nums, start + 1);
        int res2 = 0;
        if ((start < nums.length - 1) && (nums[start] == '1' || (nums[start] == '2' && nums[start + 1] <= '6')))
            res2 = back(nums, start + 2);
        return res1 + res2;
    }
}