package com.interview.algorithms.dp; /** * Given an int array, find the sub arrays sum is equals or closest smaller to a given K * @author stefanie * * Solution: * opt[i][k] saves 0~i element sum smaller but closest to K. * opt[i][k] = max{ opt[i-1][k], opt[i-1][k-array[i]]+array[i] if k-array[i]>=0 } * * backtrace * when not the first and opt[i][j] > opt[i-1][j] means i-th element is selected. * when is the first element, if j = array[i], means i-th element is selected */ public class C12_27_SubArraysWithSumClosestToK { public static boolean[] find(int[] array, int K){ int len = array.length; boolean[] mark = new boolean[len]; //if K equals or larger than sum, return all the set int total = 0; for (int i = 0; i < len; i++) total += array[i]; if(total <= K) { for(int i = 0; i < len; i++) mark[i] = true; return mark; } //opt[i][k] saves 0~i element sum closest to k. int[][] sums = new int[len][K + 1]; for(int i = 0; i <= K; i++) sums[0][i] = 0; for (int i = 1; i < len; i++) { for(int k = 0; k < K + 1; k++){ if(k >= array[i]){ //i-th element is smaller than j //find a more close solution sums[i][k] = Math.max(sums[i-1][k], sums[i-1][k-array[i]] + array[i]); } else sums[i][k] = sums[i-1][k]; } } //backtrace the solution int k = K; int i = len - 1; while(i >= 0 && k > 0){ //when not the first and opt[i][j] > opt[i-1][j] means i-th element is selected. //when is the first element, if j = array[i], means i-th element is selected if(( i > 0 && sums[i][k] > sums[i-1][k]) || (i == 0 && k == array[i])){ mark[i] = true; k -= array[i]; } i--; } return mark; } }