Dynamic Programming

研究生学过DP,当时觉得还挺简单的,就是从初始状态开始,找到推导公式一步步往下推嘛。但实际刷题时发现DP还是很难的,有时候想不到或者理不清推导的逻辑。今天笔试了一家大公司,两道编程题全是dp问题,而且leetcode上全有但是当时觉得挺难所以跳过了,现在还是要还的。

1.通配符wildcard

借用leetcode上的题目描述:

Implement wildcard pattern matching with support for '?' and ''.

'?' Matches any single character.
'
' Matches any sequence of characters (including the empty sequence).

The matching should cover the entire input string (not partial).

The function prototype should be:
bool isMatch(const char s, const char p)

Some examples:
isMatch("aa","a") ? false
isMatch("aa","aa") ? true
isMatch("aaa","aa") ? false
isMatch("aa", "
") ? true
isMatch("aa", "a
") ? true
isMatch("ab", "?") ? true
isMatch("aab", "c
a*b") ? false

这时候就可以用一个二维数组储存dp结果,dp[i][j]表示s的前i位和p的前j位的字符串的匹配结果。
初始化dp[i][0]和dp[0][j]。
dp[i][j] = true当出现以下之一情况:
1.dp[i-1][j] == true && p[j-1] == '*',因为通配符最后一位是所以s随便加一个没关系啦;
2.dp[i][j-1] == true && p[j-1] == '*',因为加的是
这个无所谓所以还是成立啦;
3.dp[i-1][j-1] == true && s[i-1] == p[j-1],通配符和字符串加个一样的字符还是成立啦。
4.dp[i-1][j-1] == true && p[j-1] == '*'或'?'。
其他情况dp[i][j]就为false啦。

 public static boolean isMatch(String s, String p) {
        
        
        int sLength = s.length();
        int pLength = p.length();
    
        
        char[] sChar = s.toCharArray();
        char[] pChar = p.toCharArray();
        
        
        boolean[][] dp = new boolean[sLength + 1][pLength + 1];
        
        dp[0][0] = true;

        for(int i = 1; i < sLength + 1; i++){
            dp[i][0] = false;
        }
        
        for(int j = 1; j < pLength + 1; j++){
            if(dp[0][j-1] && pChar[j-1] == '*') dp[0][j] = true;
            else dp[0][j] = false;
        }
        
        for(int i = 1; i < sLength + 1; i++){
            for(int j = 1; j < pLength + 1; j++){
                if((pChar[j-1] == '*' && (dp[i-1][j] || dp[i][j-1])) ||
                   (dp[i-1][j-1] && (pChar[j-1] == '*' || pChar[j-1] == '?' || pChar[j-1] == sChar[i-1]))){
                    dp[i][j] = true;
                }else{
                    dp[i][j] = false;
                }
            }
       
         return dp[sLength][pLength];      
        
    }


2.最长上升子序列Longest Increasing Subsequence

Given an unsorted array of integers, find the length of longest increasing subsequence.
For example,
Given [10, 9, 2, 5, 3, 7, 101, 18],
The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4. Note that there may be more than one LIS combination, it is only necessary for you to return the length.

建立dp数组,dp[i]储存的是以a[i]为结尾的最长上升子序列的长度。
初始dp[0] = 0。
dp[i] = 1 + Max {dp[j]} s.t. j < i && a[j] < a[i]。
注意最后求得的是dp中的最大值,因为最大值不一定是以最后一个数结尾的最大上升子序列哦。

public int lengthOfLIS(int[] nums) {
    
    if(nums.length == 0) return 0;
    int[] dp = new int[nums.length];
    
    dp[0] = 1;
           
    for(int i = 1; i < nums.length; i++){
        dp[i] = 1;
        for(int j = 0; j < i; j++){
            if(dp[j] >= dp[i] && nums[i] > nums[j]){
                 dp[i] = dp[j] + 1;
            }
        }
    }
    
    int res = 1;
    for(int i = 1; i < nums.length; i++){
        if(res < dp[i]){
            res = dp[i];
        }
    }
    
    return res;
}

你可能感兴趣的:(Dynamic Programming)