Lintcode: Minimum Adjustment Cost 解题报告

Minimum Adjustment Cost

Given an integer array, adjust each integers so that the difference of every adjcent integers are not greater than a given number target.

If the array before adjustment is A, the array after adjustment is B, you should minimize the sum of |A[i]-B[i]| 

注意

You can assume each number in the array is a positive integer and not greater than 100

样例

Given [1,4,2,3] and target=1, one of the solutions is [2,3,2,3], the adjustment cost is 2 and it's minimal. Return 2.

 

原题链接:http://lintcode.com/zh-cn/problem/minimum-adjustment-cost/#

 

SOL 1:

主页君现在最喜欢这种题目了。好兴奋啊!

好啦,我们先上第一个版本,递归版本:

当前可取的值是1-100,并且与上一个值是在target的差值以内。

这个版本肯定是超时啦。因为我们有大量的重复的计算,每一次从头至尾计算时,从某个index开始的某个取值的计算会反复进行。

 1 /**

 2      * @param A: An integer array.

 3      * @param target: An integer.

 4      */

 5     public static int MinAdjustmentCost1(ArrayList<Integer> A, int target) {

 6         // write your code here

 7         if (A == null) {

 8             return 0;

 9         }

10         

11         return rec(A, new ArrayList<Integer>(A), target, 0);

12     }

13     

14     /*

15      * SOL 1:

16      * 最普通的递归方法。

17      * */

18     public static int rec(ArrayList<Integer> A, ArrayList<Integer> B, int target, int index) {

19         int len = A.size();

20         if (index >= len) {

21             // The index is out of range.

22             return 0;

23         }

24         

25         int dif = 0;

26         

27         int min = Integer.MAX_VALUE;

28         

29         // If this is the first element, it can be from 1 to 100;

30         for (int i = 0; i <= 100; i++) {

31             if (index != 0 && Math.abs(i - B.get(index - 1)) > target) {

32                 continue;

33             }

34             

35             B.set(index, i);

36             dif = Math.abs(i - A.get(index));

37             dif += rec(A, B, target, index + 1);

38             min = Math.min(min, dif);

39             

40             // 回溯

41             B.set(index, A.get(index));

42         }

43         

44         return min;

45     }
View Code

 

SOL 2:

我们还是跟以前一样,加一个memory,减少重复计算。

轻松AC. M[i][j]的定义是:从index = i处开始往后所有的differ,并且A[i]的取值取为j + 1;

 1 /*

 2      * 递归2:

 3      * Rec + memory.

 4      * */

 5     /**

 6      * @param A: An integer array.

 7      * @param target: An integer.

 8      */

 9     public static int MinAdjustmentCost2(ArrayList<Integer> A, int target) {

10         // write your code here

11         if (A == null || A.size() == 0) {

12             return 0;

13         }

14         

15         int[][] M = new int[A.size()][100];

16         for (int i = 0; i < A.size(); i++) {

17             for (int j = 0; j < 100; j++) {

18                 M[i][j] = Integer.MAX_VALUE;

19             }

20         }

21         

22         return rec2(A, new ArrayList<Integer>(A), target, 0, M);

23     }

24     

25     public static int rec2(ArrayList<Integer> A, ArrayList<Integer> B, int target, int index, 

26            int[][] M) {

27         int len = A.size();

28         if (index >= len) {

29             // The index is out of range.

30             return 0;

31         }

32         

33         int dif = 0;

34         int min = Integer.MAX_VALUE;

35         

36         // If this is the first element, it can be from 1 to 100;

37         for (int i = 1; i <= 100; i++) {

38             if (index != 0 && Math.abs(i - B.get(index - 1)) > target) {

39                 continue;

40             }

41             

42             if (M[index][i - 1] != Integer.MAX_VALUE) {

43                 dif = M[index][i - 1];

44                 min = Math.min(min, dif);

45                 continue;

46             }

47             

48             B.set(index, i);

49             dif = Math.abs(i - A.get(index));

50             dif += rec2(A, B, target, index + 1, M);

51             

52             min = Math.min(min, dif);

53             

54             // Record the result.

55             M[index][i - 1] = dif;

56             

57             // 回溯

58             B.set(index, A.get(index));

59         }

60         

61         return min;

62     }
View Code

 

SOL 3:修改了一下,递归增加一个参数 : int x,表示在index 处A[i]取值为x,返回值的意义是,当此值取x时,从index往后,所有的diff之和。

这样的话,递归会看起来更加简洁一点儿。我们不需要记录上一个A[i]的取值。

 

 1 /*

 2      * SOLUTION 3 递归2:

 3      * Rec + memory.

 4      * 改进的递归版本

 5      * */

 6     /**

 7      * @param A: An integer array.

 8      * @param target: An integer.

 9      */

10     public static int MinAdjustmentCost3(ArrayList<Integer> A, int target) {

11         // write your code here

12         if (A == null || A.size() == 0) {

13             return 0;

14         }

15         

16         int[][] M = new int[A.size()][100];

17         for (int i = 0; i < A.size(); i++) {

18             for (int j = 0; j < 100; j++) {

19                 M[i][j] = Integer.MAX_VALUE;

20             }

21         }

22         

23         // 首个数字可以取1-100

24         int min = Integer.MAX_VALUE;

25         for (int i = 1; i <= 100; i++) {

26             min = Math.min(min, rec3(A, target, 0, i, M));

27         }

28         

29         return min;

30     }

31     

32     /*

33      * 将当前值设置为x能求得的最小解 

34      * */

35     public static int rec3(ArrayList<Integer> A, int target, int index, int x, 

36            int[][] M) {

37         int len = A.size();

38         if (index >= len) {

39             // The index is out of range.

40             return 0;

41         }

42         

43         if (M[index][x - 1] != Integer.MAX_VALUE) {

44             return M[index][x - 1];

45         }

46         

47         int bas = Math.abs(x - A.get(index));

48         int min = Integer.MAX_VALUE;

49         

50         // 对下一个值尝试取1-100

51         for (int i = 1; i <= 100; i++) {

52             // 下一个值的取值不可以超过abs

53             if (index != len - 1 && Math.abs(i - x) > target) {

54                 continue;

55             }

56             

57             // 计算dif 

58             int dif = bas + rec3(A, target, index + 1, i, M);

59             min = Math.min(min, dif);

60         }

61         

62         // Record the result.

63         M[index][x - 1] = min;

64         return min;

65     }
View Code

 

SOL 4:

LALA,主页君终于来打BOSS了。有了前面的递归的铺垫,把它转化为一个二维DP也就是水到渠成了。

D[i][v]: 把index = i的值修改为v,所需要的最小花费

我们引用一下九章算法黄老师课上的课件:

其实很简单,就是当前index为v时,我们把上一个index从1-100全部过一次,取其中的最小值(判断一下前一个跟当前的是不是abs <= target)

你可能感兴趣的:(code)