Dynamic Programming

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Core of DP

  • mathematical induction

DP VS Recursion

  • recursion : big -> small

  • DP: small -> big

Longest increasing Subarray

Given an array of Integers A , find the length of Longest sub-array whose elements are in Non-Decreasing Order.

{9,7,2,4,1,5,8,9,5}

DP principle

  • Base case: M[0] = 1;
  • Induction rule: M[i] represents the length of the longest increasing subarray from A[0] to A[i].
    • M[i] = M[i-1] + 1   if(A[i] > A[i-1])
    • M[i] = 1;

Code

Public static int longestLength(int[] A){
    int length = 1;
    int maxLength = 0;
    for(int i = 1; i < A.length; i++){
        if(A[i] > A[i - 1]){
            length++;
            if(length > maxLength){
                maxLength = length;
            }
        }
        else{
            length = 1;
        }
    }
    return maxLength; 
}

Longest Increasing Subsequence

3, 1, 4, 5, 7, 6, 8, 2

1, 4, 5, 6, 8 (Or 1, 4, 5, 7, 8)

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Longest Increasing Subsequence

What is the optimal sub-structure?

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Longest Increasing Subsequence

Copyright © 直通硅谷

http://www.zhitongguigu.com/

We store lis[i] for the LIS by i?

We store lis[i] for the LIS using sequence[i]

Longest Increasing Subsequence

public int longestIncreasingSubsequence(int[] nums) {
    if(nums.length == 0){
        return 0;
    }
    int[] lis = new int[nums.length];
    int max = 0;
    for (int i = 0; i < nums.length; i++){
        int localMax = 0;
        for (int j = 0; j < i; j++){
            if (lis[j] > localMax && nums[j] <= nums[i]){
                localMax = lis[j];
            }
        }
        lis[i] = localMax + 1;
        max = Math.max(max, lis[i]);
    }
    return max;
}

Copyright © 直通硅谷

http://www.zhitongguigu.com/

What is the Time Complexity?

What is the Space Complexity?

Can we do better?

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Patient Sort

Copyright © 直通硅谷

http://www.zhitongguigu.com/

1, 3, 5, 2, 8, 4, 7, 6, 0, 9, 10

1 -> 0
1,3 -> 1,2
1,3,5 -> 1,3,4
1,3,5,8 -> 1,3,5,7 -> 1,3,5,6
1,3,5,6,9
1,3,5,6,9,10
public int longestIncreasingSubsequence(int[] nums) {
    if(nums.length == 0){
        return 0;
    }
    int len = 0;
    int[] tails = new int[nums.length];
    tails[0] = nums[0];
    for(int i = 1; i < nums.length; i++){
        if(nums[i] < tails[0]){
            tails[0] = nums[i];
        } else if (nums[i] >= tails[len]){
            tails[++len] = nums[i];
        } else {
            tails[binarySearch(tails, 0, len, nums[i])] = nums[i];
        }
    }
    return len + 1;
}
private int binarySearch(int[] tails, int min, int max, int target){
    while(min < max){
        int mid = min + (max - min) / 2;
        if(tails[mid] == target){
            return mid;
        }
        else if(tails[mid] < target){
            min = mid + 1;
        }
        else max = mid;
    }
    return min;
}

Copyright © 直通硅谷

http://www.zhitongguigu.com/

1d DP solve pattern

  • 1d original data

    • if each smallest element is identical/similar

Linear scan and look back to the privous elements

Example 

Longest increasing subarray

longest increasing subsequence

cut rope

Jump Game

Given an array of non-negative integers, you are initially positioned at the first index of the array.

Each element in the array represents your maximum jump length at that position.

Determine if you are able to reach the last index.

For example:

A = [2,3,1,1,4], return true.

A = [3,2,1,0,4], return false. 

 

Index [0,1,2,3,4]

    A = [2,3,1,1,4],

      start          goal

   M = [x,x,x,x,T]

                      i j    <--- scan direction

                     i + A[i]

 

Index [0,1,2,3,4]

    A = [2,3,1,1,4],

      start          goal

   M = [x,x,x,x,T]

                      i j    <--- scan direction

                     i + A[i]

 

Base case:   M[n-1] = true

Induction rule: 

     M[i] =

      case 1: if(i + A[i] >= n-1) M[i] = true;

      case 2: if(M[j] == true && j < i + A[i]) M[i] = true;

 

 

Index [0,1,2,3,4]

    A = [2,3,1,1,4],

      start          goal

   M = [F,F,F,F,T]

                      i j    <--- scan direction

                     i + A[i]

 

Base case:   M[n-1] = true

Induction rule: 

     M[i] =

      case 1: if(i + A[i] >= n-1) M[i] = true;

      case 2: if(M[j] == true && j < i + A[i]) M[i] = true;

 

 

    //DP
    bool canJump1(vector<int>& nums) {
        int n = (int)nums.size();
        vector<bool> dp(n,false);
        dp[n-1] = true;
        for(int i= n-2;i>=0;i--){
            dp[i] = false;
            for(int j=1;j<nums[i];j++){
                if(i+j>=n-1 || dp[i+j]){
                    dp[i] = true;
                    break;
                }
            }
        }
        return dp[0];
    }
    //greedy
    bool canJump(vector<int>& nums) {
        int n = (int)nums.size();
        int res = nums[0];
        for(int i = 1; i < n; i++){
            --res;
            if(res<0) return false;
            res =max(res, nums[i]);
        }
        return true;
    }

Jump Game 2

same setup as Jump Game,

Return the minimum number of jumps needed to reach the end.

same setup as Jump Game,

Return the minimum number of jumps needed to reach the end.

 

1, base Case: M[n - 1] = 0

2 Induction Rule: M[i] ?????

 

 

 

 

same setup as Jump Game,

Return the minimum number of jumps needed to reach the end.

 

1, base Case: M[n - 1] = 0

2 Induction Rule: M[i] ?????

   M[i] represent the least number of jumps to reach M[n - 1]

      M[i] = 1 + min(M[j])

           * j is all the elements that can be reached by               1 jump from i;

 

 

 

public static int minJumps(int A[]) {
    int n = A.length;
    int[] jumps = new int[n];
    int min = Integer.MAX_VALUE;
    jump[n-1] = 0;

    for(int i = n-2; i >= 0; i--){
        if(A[i] == 0){
            jumps[i] = Integer.MAX_VALUE;
        }
        else if(i + A[i] >= n - 1){ // jump over border
            jumps[i] = 1;
        }
        else{
            min = Integer.MAX_VALUE;
            for(int j = i + 1; j < n && j <= A[i] + i; j++){
                if(min > jumps[j]){
                    min = jumps[j];
                }
            }
            if(min != Integer.MAX_VALUE) {
                jumps[i] = min + 1;
            }
            else{
                jumps[i] = Integer.MAX_VALUE;
            }
        }
    } 
    return jumps[0];
}

Longest Common Sequence

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Longest Common Sequence

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Example: abcfbc abfcab

return 4 (abcb)

Longest Common Sequence

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Example: abcfbc abfcab

return 4 (abcb)

Longest Common Sequence

What is the optimal sub-structure?

maxCommon(i,j): longest common string for String A(0,i) and String B(0,j)

We finally need to get maxCommon(stringA.length, stringB.length)

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Longest Common Sequence

Copyright © 直通硅谷

http://www.zhitongguigu.com/

What is the relationship between maxCommon(i,j) and maxCommon(i-1,j-1)?

If(A[i-1] = B[j-1]) ?

If(A[i-1] != B[j-1])?

Longest Common Sequence

Copyright © 直通硅谷

http://www.zhitongguigu.com/

What is the relationship between maxCommon(i,j) and maxCommon(i-1,j-1)?

If(A[i-1] = B[j-1]) ?

If(A[i-1] != B[j-1])?

maxCommon(i,j) = maxCommon(i-1,j-1) + 1

maxCommon(i,j) = max(maxCommon(i-1,j), maxCommon(i,j-1))

Longest Common Sequence

Copyright © 直通硅谷

http://www.zhitongguigu.com/

public static int longestCommonString(String a, String b) {
	int m = a.length();
	int n = b.length();
	int[][] maxCommon = new int[m+1][n+1];
	for(int i = 0; i <= m; i ++) {
		maxCommon[i][0] = 0;
	}
	for(int j = 0; j <= n; j ++) {
		maxCommon[0][j] = 0;
	}
	for(int i = 1; i <= m; i ++) {
		for(int j = 1; j <= n; j ++) {
		  if(a.charAt(i-1) == b.charAt(j-1)) {
		    maxCommon[i][j] = maxCommon[i-1][j-1] + 1;
		  }
		  else {
		    maxCommon[i][j] = Math.max(maxCommon[i][j-1], maxCommon[i-1][j]);
		  }
		}
	}
	return maxCommon[m][n];
}

Edit Distance

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Replace: abc -> abd

Remove: abc -> ab

Add: abc -> abcd

How many steps you need from String A to B?

e.g.  abca -> eeba 3 steps

abcdf -> eecf 3 steps

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Example:

s1 = "asdf"

s2 = "hjkl"

s1 = c1 and s1r <- rest of s1

s2 = c2 and s2r <- rest of s2

 

1, replace:  a -> h

   h sdf

   h jkl

   editDistance(sdf, jkl) + 1

 

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Example:

s1 = "asdf"

s2 = "hjkl"

s1 = c1 and s1r <- rest of s1

s2 = c2 and s2r <- rest of s2

 

2, delete:  a 

   a sdf

      hjkl

   editDistance(sdf, hjkl) + 1

 

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Example:

s1 = "asdf"

s2 = "hjkl"

s1 = c1 and s1r <- rest of s1

s2 = c2 and s2r <- rest of s2

 

3, insert:  h 

   h asdf

   h jkl

   editDistance(asdf, jkl) + 1

 

x x x x x x x
x x x x x x x
x x x x x x x
x x x x x x x
x x x x x x x
x x x x x x x
x x x x x x x

M[i][j]

Edit Distance

Copyright © 直通硅谷

http://www.zhitongguigu.com/

What is the optimal sub-structure?

what is the connection between EDIT[i,j]

and EDIT[i-1,j], EDIT[i,j-1] and EDIT[i-1,j-1]?

Copyright © 直通硅谷

http://www.zhitongguigu.com/

what is the connection between EDIT[i,j]

and EDIT[i-1,j], EDIT[i,j-1] and EDIT[i-1,j-1]?

 

Edit Distance

Copyright © 直通硅谷

http://www.zhitongguigu.com/

what is the connection between EDIT[i,j]

and EDIT[i-1,j], EDIT[i,j-1] and EDIT[i-1,j-1]?

if(A[i-1]!=B[j-1])?

if(A[i-1]=B[j-1])?

Copyright © 直通硅谷

http://www.zhitongguigu.com/

public static int editDistance(String a, String b) {
    int m = a.length() + 1; 
    int n = b.length() + 1;
    int[][] f = new int[m][n];
    for(int i = 0; i < m; i ++) {
        f[i][0] = i;
    }
    for(int j = 0; j < n; j ++) {
        f[0][j] = j;
    }
	
    for(int i = 1; i < m; i ++) {
        for(int j = 1; j < n; j ++) {
            if(a.charAt(i-1) == b.charAt(j-1)) {
                f[i][j] = f[i-1][j-1];
            }
            else {
                f[i][j] = f[i-1][j-1] + 1;
            }
            f[i][j] = Math.min(f[i][j], Math.min(f[i-1][j]+1, f[i][j-1]+1));
        }
    }
    return f[m-1][n-1];
}

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Homework

Unique Path II

Climbing Stairs

Maximum Subarray

 

edit Distance

 

Longest common Subsequence

Copyright © 直通硅谷

http://www.zhitongguigu.com/

Homework (Optional)

Longest Valid Parentheses

Triangle

Best Time to Buy and Sell Stock

Distinct Subsequences

[GoValley-201612] Dynamic Programming 2

By govalley201612

[GoValley-201612] Dynamic Programming 2

  • 724