동적 계획 면접 문제 (최대 필드 와 / 삼각 배열 최대 와 / LIS 최 장 비 하강 서브 시퀀스 / LCS 최 장 (연속 / 비 연속) 공공 서브 시퀀스)

11058 단어 알고리즘
1. 최대 필드 와
설명: n 개의 정수 (음수 일 수 있 음) 로 구 성 된 서열 a [1], a [2], a [3].                            주어진 정수 가 모두 마이너스 일 때 하위 세그먼트 와 0 을 정의 합 니 다. 만약 에 시퀀스 에 모두 마이너스 라면 최대 하위 단 과 0 입 니 다. 이 정의 에 따라 원 하 는 최 적 화 된 값 은 Max {0, a [i] + a [i + 1] 입 니 다.     +....+a [1}, 1 ≤ i ≤ j ≤ n. 입력: - 2, 11, - 4, 13, - 5, - 2 ;출력: 20
분석: 상태 dp [i] 는 i 번 째 요소 로 끝 나 는 최대 필드 와
dp[0] : 0
dp[1] : 11 + dp[0] = 11
dp[2] : -4 + dp[1] = 7
dp[3] : 13 + dp[2] = 20
dp[4] : -5 + dp[3] = 15
dp[5] : -2 + dp[4] = 13
             dp[0] = 0
      :dp[i] = ar[i] + dp[i-1]

코드: 
import java.util.Arrays;

public class sum {
    public static void main(String[] args) {
        int[] arr = new int[]{-2,11,-4,13,-5,-2};
        int[] dp = new int[arr.length];
        int sum = maxSegmentSum(arr,dp);
        System.out.println (Arrays.toString (dp));
        System.out.println (sum);
    }

    private static int maxSegmentSum(int[] arr, int[] dp) {
        dp[0] = arr[0];
        //         0
        if (dp[0] < 0){
            dp[0] = 0;
        }
        int max = dp[0];
        for (int i = 1; i < arr.length; i++) {
            dp[i] = arr[i] + dp[i-1];
            if(dp[i] < 0){
                dp[i] = 0;
            }
            //           max
            if(max < dp[i]){
                max = dp[i];
            }
        }
        return max;
    }
}

2. 삼각 배열 의 최대 값
설명:
/**
 *   :
 *        ,  :
 * 5
 * 12  6
 * 7   13  18
 * 12  14  10  9
 *          ,         ,           ,
 *        ,       ,                 ?
 *
  */

 
사고: 우 리 는 먼저 마지막 층 의 요 소 를 옮 겨 다 니 며 dp 에 저장 한 다음 에 마지막 두 번 째 열 에서 아래로 선택 할 수 있 습 니 다. 즉, 모든 수 는 세 가지 추가 가능 (마지막 층 요 소 를 선택) 이 있 습 니 다. 추 가 된 수 에서 최대 수 를 dp 에 저장 한 다음 에 한 층 씩 위로 옮 겨 다 니 면 모든 층 의 요소 가 최대 와 최대 화 를 구 할 수 있 습 니 다.
void func(int[] arr, int i, int j){     arr [i] [j] + func (arr [i + 1] [j]); / 아래 에 추가    arr [i] [j] + func (arr [+ 1] [j - 1]); / / 왼쪽으로 비스듬히    arr [i] [j] + func (arr [+ 1] [j + 1]); / / 오른쪽으로 비스듬히
}
코드: 

public class            {
    public static void main(String[] args) {
        int[][] arr = new int[][]{
                {5},
                {12, 6},
                {7, 13, 18},
                {12, 14, 10, 9}
        };
        int[][] dp = new int[arr.length][arr.length];
        int row = arr.length - 1;
        //          dp,     
        for (int i = 0; i < arr[row].length; i++) {
            dp[row][i] = arr[row][i];
        }
        int sum = maxSum (arr,dp);
        System.out.println (sum);
//        //  :
//        int max = func (arr,0,0,dp);
//        System.out.println (max);
    }

    /**
     *      
     */
    private static int maxSum(int[][] arr, int[][] dp) {
        //          (              dp)
        for (int i = arr.length - 1 - 1; i >= 0; i--) {
            for (int j = 0; j < arr[i].length; j++) {//            
                //    
                int n1 = arr[i][j] + dp[i+1][j];
                //     
                int n2 = arr[i][j] + dp[i+1][j+1];
                int n3 = 0;
                //     ,    
                if(j > 0){
                    n3 = arr[i][j] + dp[i+1][j-1];
                }
                //       dp
                dp[i][j] = Math.max (Math.max(n1,n2),n3);
            }
        }
        return dp[0][0];
    }

    /**
     *   
     * @param arr
     * @param i
     * @param j
     * @param dp
     * @return
     */
    private static int func(int[][] arr, int i, int j, int[][] dp) {
        //    
        if(i > arr.length-1 || j < 0 || j > arr[i].length-1){
            return 0;
        }
        //         
        if(dp[i][j] > 0){
            return dp[i][j];
        }
        int n1 = arr[i][j] + func(arr, i+1, j, dp);
        int n2 = arr[i][j] + func(arr, i+1, j-1, dp);
        int n3 = arr[i][j] + func(arr, i+1, j+1, dp);
        dp[i][j] = Math.max(Math.max(n1, n2), n3);
        return dp[i][j];
    }
}

3. LIS 최 장 비강 자 서열 문제 구하 기
 설명: 문자열 을 지정 합 니 다. 그 중에서 가장 긴 문자열 의 길 이 를 작은 것 에서 큰 것 으로 정렬 합 니 다.
/**
 *    dp[i]    i                 ,
 *        :dp(i) = max{1, dp(j)+1} 
 *   j dp[i]){
                        dp[i] = dp[j] + 1;
                    }
                }
                if(max < dp[i]){
                    max = dp[i];
                }
            }
            return max;
        }
    }

4. LCS 최 장 (연속 / 반드시 연속 되 지 않 음) 공공 하위 서열 문제 구하 기
   두 서열 의 최 장 공공 서열 (연속) 의 길 이 를 구하 십시오.
/**
 *    
 *   :dp[m][n]                
 *        :
 * dp[m][n]=1 + dp[m-1][n-1]   (str1[i]=str2[j])
 */
public class test {
    public static void main(String[] args) {
        String str1 = "helloworld";
        String str2 = "helxtld";
        int[][] dp = new int[str1.length () + 1][str2.length () + 1];
        int sum = func (str1, str2, dp);
        System.out.println (sum);
    }

    private static int func(String str1, String str2, int[][] dp) {
        int k = 0;
        int max = 0;
        for (int m = 1; m <= str1.length (); ++m) {
            for (int n = 1; n <= str2.length (); ++n) {
                if (str1.charAt (m - 1) == str2.charAt (n - 1)) {
                    dp[m][n] = 1 + dp[m - 1][n - 1]; //    
                }
                if (max < dp[m][n]) {
                    max = dp[m][n];
                    //             , k               
                    k = m;
                }
            }
        }
        //substring()                       
        System.out.println (str1.substring ((k-max),k));
        return max;
    }
}

실행 결과:
 우 리 는 공공 문자열 의 길이 와 공공 문자열 을 얻 을 수 있 습 니 다.
hel
3

두 서열 의 최 장 공공 하위 서열 (연속 되 지 않 음) 의 길 이 를 구하 십시오.
public class test {
    public static void main(String[] args) {
        String str1 = "helloworld";
        String str2 = "helxtld";
        int[][] dp = new int[str1.length ()+1][str2.length ()+1];
//        int lcs = func (str1, str2,str1.length ()-1,str2.length ()-1, dp);
        int lcs1 = func (str1,str2,dp);
//        System.out.println (lcs);
        System.out.println (lcs1);
//        for (int i = 0; i < dp.length; i++) {
//            for (int j = 0; j < dp[i].length; j++) {
//                System.out.print (dp[i][j] + " ");
//            }
//            System.out.println ();
//        }
    }
    }

    /**
     *      LCS
     * @param str1
     * @param str2
     * @param dp
     * @return
     */
    private static int func(String str1, String str2, int[][] dp) {
        /**
         * dp[m][n] : str1 m     ,str2 n     
         *        LCS   
         *
         * if(xm == yn)
         *    dp[m][n] = 1 + dp[m-1][n-1]
         * else {
         *    dp[m][n] = max{dp[m][n-1], dp[m-1][n]}
         * }
         */
        for(int m=1; m<=str1.length(); m++){
            for(int n=1; n<=str2.length(); n++){
                if(str1.charAt(m-1) == str2.charAt(n-1)){
                    dp[m][n] = 1 + dp[m-1][n-1]; //    
                } else {
                    if(dp[m][n-1] > dp[m-1][n]){
                        dp[m][n] = dp[m][n-1]; //   
                    } else {
                        dp[m][n] = dp[m-1][n]; //   
                    }
                }
            }
        }
        return dp[str1.length()][str2.length()];
    }

    /**
     *     
     * @param str1
     * @param str2
     * @param m
     * @param n
     * @param dp
     * @return
     */
    private static int func(String str1, String str2, int m, int n, int[][] dp) {
        if(m < 0 || n < 0){
            return 0;
        }

        if(dp[m][n] > 0){
            return dp[m][n];
        }

        if(str1.charAt(m) == str2.charAt(n)){
            dp[m][n] = 1 + func(str1, str2, m-1, n-1, dp);
            return dp[m][n];
        } else {
            int n1 = func(str1, str2, m, n-1, dp);
            int n2 = func(str1, str2, m-1, n, dp);
            if(n1 > n2){
                dp[m][n] = n1;
            } else {
                dp[m][n] = n2;
            }
            return dp[m][n];
        }
    }
}

위의 코드 는 가장 긴 공공 서브 시퀀스 의 길 이 를 인쇄 할 뿐 입 니 다. 가장 긴 공공 서브 시퀀스 의 요 소 를 인쇄 하려 면 dp 표 의 방향 을 기록 한 다음 에 역 추적 법 으로 요 소 를 인쇄 해 야 합 니 다. 코드 는 다음 과 같 습 니 다. 
 public static void main(String[] args) {
        String str1 = "helloworld";
        String str2 = "helxtld";
        int[][] dp = new int[str1.length () + 1][str2.length () + 1];
        //     ,  LCS     
        int[][] path = new int[str1.length () + 1][str2.length () + 1];
        int lcs = func (str1, str2, dp, path);
        System.out.println ("       :" + lcs);

        //  bp ,  bp   
        for (int i = 0; i < dp.length; i++) {
            for (int j = 0; j < dp[i].length; j++) {
                System.out.print (dp[i][j] + " ");
            }
            System.out.println ();
        }
        backstrace (str1, str1.length (), str2.length (), path);
    }

    //           ,       ,                
    private static void backstrace(String str1, int m, int n, int[][] path) {
        if (m < 0 || n < 0) {
            return;
        }
        if (path[m][n] == 1) {
            backstrace (str1, m - 1, n - 1, path);
            System.out.print (str1.charAt (m - 1));
        } else {
            if (path[m][n] == 2) {
                backstrace (str1, m, n - 1, path);
            } else {
                backstrace (str1, m - 1, n, path);
            }
        }
    }

    private static int func(String str1, String str2, int[][] dp, int[][] path) {
        for (int m = 1; m <= str1.length (); ++m) {
            for (int n = 1; n <= str2.length (); ++n) {
                if (str1.charAt (m - 1) == str2.charAt (n - 1)) {
                    dp[m][n] = 1 + dp[m - 1][n - 1]; //    
                    path[m][n] = 1;
                } else {
                    if (dp[m][n - 1] > dp[m - 1][n]) {
                        dp[m][n] = dp[m][n - 1]; //   
                        path[m][n] = 2;
                    } else {
                        dp[m][n] = dp[m - 1][n]; //   
                        path[m][n] = 3;
                    }
                }
            }
        }
        return dp[str1.length ()][str2.length ()];
    }
}

실행 결과:
       :5
0 0 0 0 0 0 0 0 
0 1 1 1 1 1 1 1 
0 1 2 2 2 2 2 2 
0 1 2 3 3 3 3 3 
0 1 2 3 3 3 4 4 
0 1 2 3 3 3 4 4 
0 1 2 3 3 3 4 4 
0 1 2 3 3 3 4 4 
0 1 2 3 3 3 4 4 
0 1 2 3 3 3 4 4 
0 1 2 3 3 3 4 5 
helld

 인쇄 된 bp 표 는 대각선 에서 증가 하 는 수, 즉 공공 하위 시퀀스 의 길 이 를 기록 합 니 다.
 

좋은 웹페이지 즐겨찾기