1. 程式人生 > >667. Beautiful Arrangement II-- 類比526 但不能用back tracking

667. Beautiful Arrangement II-- 類比526 但不能用back tracking

get system case dex 得出 res bool 數組 back

667 是很坑爹的一個題目,乍一看和 526 如出一轍,

526. Beautiful Arrangement 題意: 構造 [1,n]的排列,讓每個 a[index] % index ==0 或者 index %a[index] ==0, 基本和 46 題一樣,就是構造排列。

667題意:

給定兩個整數nk,構建一個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