【问题标题】:Find The Smallest - Codewars Challenge - Javascript找到最小的 - Codewars 挑战 - Javascript
【发布时间】:2019-11-06 19:25:45
【问题描述】:

试图解决这个问题Codewars challenge

你有一个由数字组成的正数 n。您最多可以做一个操作:选择数字中的一个数字的索引,在该索引处删除该数字,然后将其插入到另一个数字或数字的同一位置,以便找到您可以获得的最小数字。

任务:根据语言返回一个数组、元组或字符串(参见“示例测试”):

1) 你得到的最小数

2)你取的数字d的索引i,i尽量小

3) 插入数字 d 的索引 j(尽可能小)以获得最小的数字。

例子:

smallest(261235) --> [126235, 2, 0] or (126235, 2, 0) or "126235, 2, 0"

其他例子:

209917, [29917, 0, 1]
285365, [238565, 3, 1]
269045, [26945, 3, 0]
296837, [239687, 4, 1]

所以,为了获得可能的最小数字,我们需要从数字中删除最小的数字并将其放在数字的前面,对吗?

function smallest (n) {
  //turn n into an array
  let array = String(n).split("").map(Number);
  
  let smallest = Math.min(...array);
  
  //find index of smallest in original array
  let index = array.indexOf(smallest);
  
  //remove smallest from original array, move it to front
  array.splice(index, 1);
  array.unshift(smallest);
  let newNumber = Number(array.join(""));

  //return array of new number, index of where the smallest was, 
  //and index of where the smallest is now
  return ([newNumber, index, 0]);
}
console.log(smallest(239687));

我的答案是返回正确的数字,但是大约一半的时间,它没有返回正确的索引i 和索引j

编辑:最新尝试:

function smallest (n) {

  let array = Array.from(String(n)).map(Number);
  let original = Array.from(String(n)).map(Number);
  let sorted = Array.from(String(n)).map(Number).sort((a, b) => a - b);

  let swapValueOne = [];
  let swapValueTwo = [];

  for (let i = 0; i < array.length; i++) {
    if (array[i] !== sorted[i]) {
      swapValueOne.push(sorted[i]);
      swapValueTwo.push(original[i]);
      break;
    }
  }

  swapValueOne = Number(swapValueOne);
  swapValueTwo = Number(swapValueTwo);
  
  let indexOne = original.indexOf(swapValueOne);
  let indexTwo = original.indexOf(swapValueTwo);

  //remove swapValue
  array.splice(indexOne, 1);
  //insert swapValue
  array.splice(indexTwo, 0, swapValueOne);

  return ([Number(array.join("")), indexOne, array.indexOf(swapValueOne)]);

}

console.log(smallest(296837));

^ 有时它会给出正确的数字和正确的交换索引,有时数字和交换索引都是错误的。

【问题讨论】:

  • 第二个测试看起来不正确。 testing(209917, [29917, 0, 1]); 但是找到的索引应该是1,应该插入到索引0
  • 描述指定“[29917, 1, 0] 也可以是一个解决方案,但是 [29917, 1, 0] 中的索引 i 大于 [29917, 0, 中的索引 i 1].",所以有一种方法可以消除歧义。

标签: javascript arrays sorting numbers


【解决方案1】:

将最小的元素放在前面(我们称之为“贪婪”解决方案)是非最优的。考虑n = 296837 的情况,就像你上一个测试用例一样。您的代码返回[296837, 0, 0],因为它发现2 是最小的数字并将其移到前面(基本上什么都不做)。如您的示例所示,有一个更好的方法:[239687, 4, 1],即将3 移动到数组中的第一个索引。

您需要重新制定策略,使其不贪婪以找到全局最优值。

如果还是卡住了,可以试试以下方法:

数字不能包含 多位数字——为什么不尝试所有可能的交换?

【讨论】:

  • 好的,您可以创建一个包含所有可能组合的数组,然后对它们进行排序以找到最小值,然后确定需要进行哪些交换才能达到该值... .(?)
  • 你可能想多了。排序不是找到最小值所必需的,无论如何我们都可以安全地忽略最小值并强行使用它。如果我们有一个 10 位数字,比如说,我们可以交换多少个可能的索引 ij(包括 i == j)? JS 中最大的安全整数只有 16 位,因此二次解法非常快(少于 150 次迭代)。还有进一步的优化,但从这开始就足以天真地解决问题,这应该始终是您在编码挑战中首先想到的。
【解决方案2】:

这里有一个小想法可能会有所帮助。

如果你有这样的数字:

239687

你可以用这个最小的数字是排序的数字:

236789

在原来的数字中,2和3已经在正确的位置。如果从左边的数字和排序的数字开始,你发现的第一个区别就是需要交换的数字。需要与排序列表中对应的数字交换:

orig   2 3 9 6 8 7 -- 6 needs to go before 9
       | | x       
sorted 2 3 6 7 8 9

下一个排序的数字上面是6,但原来有9。你需要在9之前插入6。

对于算法,您可以对数字进行排序并找到第一个差异的索引(从左侧开始)。这是您的返回值之一(示例中为 2)。现在在原始(索引3)中找到sorted[2](即6)的索引。将值插入原始数组中,就完成了。

【讨论】:

  • 所以在我的编辑中,我添加了一个 sn-p 以获得从左侧开始的第一个差异 - 对吗?
  • 是的,我觉得这很合理。还有findIndex(),短一点。
  • 请看我最近的尝试。有时数字是对的,但索引是错误的,有时一切都是错误的。也许我在原始数组中插入(交换)值的方式有问题,我不确定。
【解决方案3】:

找到第一个未排序元素的方法并不能正确解决所有情况,例如,如果数字是 300200,第一个未排序的数字是 3,如果你在那个地方放一个 0,取决于你移动了什么 0得到:

(0)30020 (0)30020 (0)30200 (0)30200

所有的答案都是错误的,因为你要做的就是把 3 放在数字的末尾来得到

(000)2003

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-21
    • 2020-10-12
    • 2019-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多