667. Beautiful Arrangement II-- 类比526 但不能用back tracking
Posted keepac
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了667. Beautiful Arrangement II-- 类比526 但不能用back tracking相关的知识,希望对你有一定的参考价值。
667 是很坑爹的一个题目,乍一看和 526 如出一辙,
526. Beautiful Arrangement 题意: 构造 [1,n]的排列,让每个 a[index] % index ==0 或者 index %a[index] ==0, 基本和 46 题一样,就是构造排列。
667题意:
给定两个整数n
和k
,构建一个n
个元素数组,数组要满足一下要求:
假设数组[a1,a2....an]
那么[|a2-a1|,|a3-a2|.....]
包含k
个不同的整数。如果有多个数组输出任意一个数组。1<=k<n<=10000
看到题目误以为和526 类似, 准备用back tracking 构造, 但复杂度为 n! , 如果数据范围为 1000, 那么 1000! 不管如何剪枝,都会TLE,TLE的code 如下,写的竟然有板有眼。
class Solution { public int[] constructArray(int n, int k) { if(n-1<k) return new int[0]; int[] nums = new int[n]; List<Integer> result = new ArrayList<>(); for(int i=0; i<n; i++){ nums[i] = i+1; } dfs(result, nums, new boolean[n], k, new HashSet<>()); for(int i=0; i<result.size(); i++) nums[i] = result.get(i); return nums; } private boolean dfs(List<Integer> result, int[] nums, boolean[] used, int k , Set<Integer> set){ if(result.size() == nums.length && set.size() == k){ System.out.println(result); return true; } if(result.size() >= nums.length) return false; boolean flag = false; for(int i=0; i<nums.length; i++){ if(!used[i]){ int size = result.size(); int abs = 0; boolean added = false; if(result.size()>0){ abs = Math.abs(result.get(size-1) - nums[i]); if(!set.contains(abs) && set.size()+1 >k) { continue;} set.add(abs); added = true; } result.add(nums[i]); used[i] = true; flag = flag || dfs(result,nums,used,k,set); if(flag) return true; result.remove(result.size()-1); used[i] = false; if(added) set.remove(abs); } } return flag; } }
仔细分析一下题目, n 个数 可以排不同差值的组合, 最大 n-1, 最小为1, 所以范围为 [1~n-1], 如果 K > N-1 显然不可解。
比如 n=9, k=5
可以构造 : 1,9,2,8, + 3,4,5,6,7
n=9,k=4, 可以构造: 1,9,2 + [8,7,6,5,4,3]
假设 left = 1, right = n
对于 K , 可以先放k-1 个数来构造, 1,n,2,n-1。。。 , 剩下的数字 递增或者递减即可
观察上面的case 可以得出 k为odd 时, 接下来 数字为 从left 递增, k为even 时,接下来数字为从right 递减,code 如下, 复杂度为 o(n):
class Solution { public int[] constructArray(int n, int k) { if(k>n-1) return null; int[] result = new int[n]; int left =1; int right = n; int cons = k-1; for(int i=0;i<n; i++){ if(cons>=0){ if(i%2 ==0) result[i] = right--; else result[i] = left++; cons--; } else { if(k%2==0) { result[i] = left++; } else result[i] = right--; } } return result; } }
以上是关于667. Beautiful Arrangement II-- 类比526 但不能用back tracking的主要内容,如果未能解决你的问题,请参考以下文章