JS | 教练,我想做习题17

🚀 前言

大家好呀,我是毛小悠,可以叫我二毛,在家中排行老二,是一名前端开发工程师。

本系列文章旨在通过练习来提高JavaScript的能力,一起愉快的做题吧。😀😀😀

以下每道题,二毛我都有尝试做一遍。建议限时训练,比如限定为半小时,如果半小时内想不出来,可以结合文章末尾的参考答案来思考。

求关注求点赞👍~~~😘😘😘

📖 题目1:受约束的GCD

将为您提供两个数字n和k,您的任务将是返回总和为n且具有最大可能GCD的k位数组。

例如,假设n = 12,k = 3,则有许多可能的3位数组之和等于12,例如[1,2,9],[2,3,7],[2,4, 6],…等。在所有可能性中,具有最高GCD的可能性为[2,4,6]。因此,solve(12,3)= [2,4,6]。

还要注意,数字不能在子数组内重复,因此[1,1,10]是不可能的。最后,如果没有这样的数组,则返回一个空数组。

习题代码:

function solve(n,k){
//..
};

📖 题目2:排列

您将获得N个k位整数。您必须重新排列整数中的数字,以便最大和最小数字之间的差异最小。所有整数均应按照相同的规则重新排列。

输入:
输入包含N个k位正整数(写为字符串)的数组。初始整数和数字重新排列后的整数都允许前导零。

输出:
返回一个数字:按照相同规则将所有整数重新排列后,最大和最小数字之间的最小差值。

例子:

['5237', 
 '2753', 
 '7523', 
 '5723',     =>  2700 
 '5327', 
 '2537']

['010',
 '909',      =>  3
 '012]

['00',
 '57',       =>  75
 '76']

注意:
在第一个样本中,如果我们将数字重新排列为(3,1,4,2),则第二个和第四个数字将分别等于5237和2537(对于这样的数字顺序)。
在第二个示例中,如果我们交换第二个数字和第一个数字,我们将得到整数100、99和102。

习题代码:

function permutations(s) {
  
}

答案

🍗 题目1的答案

参考答案1:

function solve(n, k) {
  let minMult = k * (k + 1) / 2
  let maxGCD = n / minMult | 0
  if (!maxGCD) return []
  
  while (n % maxGCD) maxGCD--
  let result = Array.from({length: k-1}, (_,i) => maxGCD * (i+1))
  result.push(n - k * (k-1) * maxGCD / 2)
  return result
}

参考答案2:

const solve=(n,k)=>(r=>r?Array.from({length:k-1},(_,i)=>(i+1)*r).concat(n-(k-1)*k*r/2):[])((m=>Array.from({length: m},(_,i)=>m-i).filter(e=>(n-(k-1)*k*e/2)%e==0)[0])(Math.floor(n/(k*(k+1)/2))));

参考答案3:

function solve(n,k){
  for (var i = n; i > 0; i--) {
    if (n % i === 0 && i * k * (k+1) / 2 <= n) {
      return [...[...Array(k-1)].map((_, j) => i * (j+1)), n - (i * k * (k-1) / 2)];
    }
  }
  return [];
}

参考答案4:

function solve(n,k){
  let gcd = n;
  let results = [];

  function factorial(interval, count = k){
    let increment = interval;
    let acc = 0;
    while (count > 0) {
      acc += increment;
      increment += interval;
      count--;
    }
    return acc;
  }

  if (factorial(1) > n) return [];

  while (true) {
    if (factorial(gcd) <= n){
      let diff = n - factorial(gcd, k-1);
  
      if (diff%gcd === 0) {
        let temp = gcd;
        for (let i = 0; i < k-1; i++) {
          results.push(temp);
          temp += gcd;
        }
        results.push(diff);
      }
  
      else {
        let temp = gcd;
        for (let i = 0; i < k; i++) {
          results.push(temp);
        }
      }

      if (results.reduce((a,c)=> a+c) === n) break;
      results = [];
    }
    gcd--;
  }

  return results;
}

参考答案5:

function solve(n,k){
   var sol = null;
   for ( var i = 1; i < n; ++i ) {
      if ( n == i || n % i == 0 ) {
         var sum = k*(k+1)/2*i;
         if ( sum > n ) {
            break;
         } else {
            sol = i;
         }
      }
   }
   
   var retval = [];
   if ( sol === null ) {
      return retval;
   }
   
   var rest = n;
   var count = sol;
   for ( var i = 0; i < k-1; ++i ) {
      retval.push(count);
      rest -= count;
      count += sol;
   }
   retval.push(rest);

   return retval;
}

🍗 题目2的答案

参考答案1:


// https://github.com/gkucmierz/algorithms/blob/master/js/generate_permutations.js
const genPermutations = size => {
  const perms = [];
  const gen = (res, used, shift) => {
    if (used === size) {
      perms.push(res);
    }
    for (let i = 0; i < (size-used); ++i) {
      gen([...res, shift[i]], used + 1, [...shift.slice(0, i), ...shift.slice(i + 1)]);
    }
  };
  gen([], 0, new Array(size).fill(0).map((_, i) => i));
  return perms;
};

function permutations(s) {
  const perms = genPermutations(s[0].length);
  return perms.reduce((smallest, perm) => {
    let [min, max] = [Infinity, 0];
    s.map(str => {
      const val = +perm.map(i => str[i]).join``;
      if (val < min) min = val;
      if (val > max) max = val;
    });
    return Math.min(smallest, max - min);
  }, Infinity);
}

参考答案2:

function* permute(array, currArr=[], skip=[]){
  for( let itr=0; itr<array.length; itr++ ){
    if( skip.includes(itr) ) continue
    yield* permute(array, [...currArr, array[itr]], [...skip, itr])
  }
  if(currArr.length == array.length) yield currArr;
}

function* baz(start, stop, step=1){
  for( let itr=start; itr<stop; itr+=step ){ yield itr }
}

function permutations(array){
  let noLen = array[0].length
  let orders = permute([...baz(0, noLen)])
  let rtn = Infinity;
  for( let order of orders ){
    let re_order = array.map(noStr => parseInt(order.map(val => noStr[val]).join('')) );
    let x = Math.max(...re_order) - Math.min(...re_order);
    rtn = rtn < x ? rtn : x;
  }
  return rtn
}

参考答案3:

Array.prototype.concatMap = function(fn) { return [].concat(...this.map(fn)); };
Array.prototype.without = function(i) { return [].concat(this.slice(0,i),this.slice(i+1)); };
Array.prototype.permutations = function(n) { return n ? this.concatMap( (v,i) => this.without(i).permutations(n-1).map( w => [v,...w] ) ) : [[]] ; };

const permutations = a => Math.min(...Array.from( a[0], (_,i) => i ).permutations(a[0].length).map( perm => a.map( v => Number( perm.map( i => v[i] ).join("") ) ) ).map( a => Math.max(...a) - Math.min(...a) )) ;

参考答案4:

function permutations(s) {
  var perms = [], len = s[0].length;
  (function f(lst,elems=[]){
    if(elems.length===len) {perms.push(elems); return;}
    for(let i=0; i<lst.length; i++) {
      let t=lst.slice(), e=t.splice(i,1);
      f(t,elems.concat(e));
    }
  })([...Array(len)].map((_,i)=>i));
  return Math.min(...perms.map(r=>s.map(n=>+r.map(i=>n[i]).join(''))).map(r=>Math.max(...r)-Math.min(...r)));
}

参考答案5:

function permutations(arr) {
  let best=Infinity;
  for(let idx of genPermIdx(arr[0])){
    let x=arr.map(s=>+idx.map(i=>s[i]).join(''));
    let a=Math.min(...x), b=Math.max(...x);
    best=best>b-a?b-a:best;
  }
  return best;
}

function* genPermIdx(s){
  
  const dfs=function*(arr,perm=[]){
    if(!arr.length) yield perm;
    else{
      let i=-1;
      for(let v of arr){ i++;
        perm.push(v);
        yield* dfs(arr.slice(0,i).concat(arr.slice(i+1)),perm);
        perm.pop();
      }
    }
  }
  let arr=Array.from(s,(_,i)=>i);
  yield* dfs(arr);
}

🍁后序

本系列会定期更新的,题目会由浅到深的逐步提高。

求关注求点赞 👍~~🍭🍭🍭

可以关注我的公众号:前端毛小悠。欢迎阅读

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值