最大半径问题

一个长度为n的数组,从中选取k个数字,若定义这k个数字的半径为排序后相邻两个数字之间的最小间隔,则k个数字所能达到的最大半径是多少?

如果k = 1,则半径为无穷大。

假设k > 0。

方法一:深度优先搜索。

class SolutionDFS {
	private int max = 0;
	public SolutionDFS(int[] nums, int k) {
		find(nums, 0, 0, k, 0);
	}
	private void find(int[] nums, int from, int step, int k, int min) {
		if (step == k) {
			max = Math.max(max,  min);
		} else if (step == 0) {
			find(nums, 1, step + 1, k, Integer.MAX_VALUE);
		} else if (step == k - 1) {
			find(nums, nums.length, step + 1, k, Math.min(min, nums[nums.length - 1] - nums[from - 1]));
		} else if (min > max) {
			for(int i = from; i + (k - step) <= nums.length; i++) {
				find(nums, i + 1, step + 1, k, Math.min(min, nums[i] - nums[from - 1]));
			}
		}
	}
	public int getSolution() {
		return max;
	}
}

方法二:递归+记忆化搜索。

class SolutionRecursive {
	
	private boolean[][] visit;
	private int[][] dp;
	private int[] nums;
	
	public SolutionRecursive(int[] nums, int k) {
		int n = nums.length;
		this.visit = new boolean[n + 1][k + 1];
		this.dp = new int[n + 1][k + 1];
		this.nums = nums;
		dp(n, k);
	}
	
	public int getSolution() {
		int n = dp.length - 1;
		int k = dp[n].length - 1;
		return dp[n][k];
	}
	
	private int dp(int n, int k) {
		if (visit[n][k]) return dp[n][k];
		visit[n][k] = true;
		if (n < k || k == 0) {
			dp[n][k] = 0;
			return dp[n][k];
		}
		if (k == 1) {
			dp[n][k] = Integer.MAX_VALUE;
			return dp[n][k];
		}
		int result = dp(n - 1, k);
		for(int i = k - 1; i < n; i++) {
			result = Math.max(result, Math.min(dp(i, k - 1), nums[n - 1] - nums[i - 1]));
		}
		dp[n][k] = result;
		return result;
	}
}

方法三:递推+动态规划。

class SolutionIterative {
	private int solution;
	
	public SolutionIterative(int[] nums, int k) {
		int[][] radius = new int[nums.length + 1][k + 1];
		for(int i = 1; i <= nums.length; i++) {
			radius[i][1] = Integer.MAX_VALUE;
			for(int j = 2; j <= k; j++) {
				radius[i][j] = radius[i - 1][j];
				for(int m = j - 1; m < i; m++) {
					radius[i][j] = Math.max(radius[i][j], Math.min(radius[m][j - 1], nums[i - 1] - nums[m - 1]));
				}
			}
		}
		solution = radius[nums.length][k];
	}
	
	public int getSolution() {
		return this.solution;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值