编码挑战

时间:2019-10-18 05:19:46

标签: ruby algorithm

因此,最近我正在检查编码挑战之一。这个问题很吸引人,所以只想知道在时间和空间复杂度上是否有更好的方法。

问题:给定数字x,其中x为正数>0。找到具有相同位数的最近的最小数字。如果存在,则返回最小的数字,否则打印“最近的最小数字不存在”。 相同数字位数的意思是,如果数字为12345,那么具有这些数字位数(在这种情况下,数字位数为5),因此找不到最接近的较小数字。虽然可以说可以是1234,但是位数不相同。找到最接近的最小数字时,您需要使用所有数字

因此,以下是一些示例

数字:8563 输出:8536

数7385 输出7358

数:3857 输出:3785

编号:123 输出:不存在最近的最小数字

number = gets.to_i
flag = 1
numbers_array =  number.digits.permutation(Math.log10(number).to_i + 1).sort
numbers_array.each_with_index do |e, index| 
  if e.join.to_i == number
    print numbers_array[index - 1]
    flag = 0
    break
  end
end
if flag == 1
  puts "Nearest Smallest Number not exist"
end

注意:当数量很大时,上述解决方案将花费更多时间

3 个答案:

答案 0 :(得分:2)

检查以下内容,

def lowest_digit(n)
    digits, index = n.to_s.chars, nil
    str = digits.reverse
    z = str[1..-1].each_with_index.inject([str[0]]) { |m,(a,i)| m << a; index = i if a > m[-2]; break m if a > m[-2]; m }
    z_num = z.reverse.join
    if digits.reverse == z
      "Nearest Smallest Number not exist"
    else
      digits[0..(-3-index)].join + z.permutation(z.length).to_a.map(&:join).select { |x| x < z_num }.max
    end
end

lowest_digit 32964563245279143273348345
 => "32964563245279143273345843"

答案 1 :(得分:1)

def largest_smaller(n)
  rv = recurse(n.digits.reverse)
  return nil if rv.nil?
  rv.join.to_i
end

def recurse(remaining_digits, unused_digits = remaining_digits)
  first_remaining, *rest_remaining = remaining_digits

  return (unused_digits.first < first_remaining ? unused_digits : nil) if
    rest_remaining.empty?

  a = remaining_digits.select { |d| d <= first_remaining }.sort.reverse
  return nil if a.empty?

  a.each_index do |i|
    j = unused_digits.find_index { |d| d == a[i] }
    rest_unused = (unused_digits.dup.tap { |a| a.delete_at(j) }).sort.reverse
    return [a[i]] + rest_unused if a[i] < first_remaining
    rv = recurse(rest_remaining, rest_unused)
    return [a[i]] + rv unless rv.nil?
  end
  nil
end

largest_smaller 8563
  #=>           8536
largest_smaller 7385
  #=>           7358
largest_smaller 3857
  #=>           3785
largest_smaller 123
  #=>           nil
largest_smaller 32964563245279143273348345
  #=>           32964563245279143273345843 

所有这些操作瞬间完成。我将在稍后提供该算法的说明。

答案 2 :(得分:1)

这个想法类似于生成数组的下一个排列。

假设我们有一个排列

a1, a2, a3 ... an

它的前面的排列是什么?

观察: 第一个排列(最小的排列)将具有以下属性:

a1 <= a2 <= a3 ... <= an

最后一个排列将具有以下属性:

a1 >= a2 >= a3 ... >= an.

根据这种观察,我们可以轻松地从给定的排列中来回

如果我们可以找到以下位置的k,请从最后一个元素迭代到第一个元素:

ak , ak + 1, and ak > ak + 1

让我们从ak + 1 ... an中找到最大的数字,我们称它为ax的{​​{1}},然后用ax < ak替换ax,现在我们有了

ak

对于[...],我们应该做的是按降序对它们进行排序。 Wallah,我们找到了解决问题的办法。

示例:

a1, a2, ... ax, [...]

Java代码:

1, 2, 4, 3 => k = 3, x = 4 -> Ans = 1, 2, 3, 4

1, 2, 5, 5, 3, 4 => k = 4, x = 6 -> Ans = 1, 2, 5, 4, 5, 3 

时间复杂度:public void prevPermutation(int[]data){ for(int i = data.length - 2; i >= 0; i--){ if(data[i] > data[i + 1]){ int index = i + 1; for(int j = i + 2; j < data.length; j++){ if (data[j] > data[index] && data[j] < data[i]){ index = j; } } int tmp = data[i]; data[i] = data[index]; data[index] = tmp; sortDescending(data, i + 1, data.length); break; } } } public void sortDescending(int[]data, int from, int to){ int[]copy = Arrays.copyOfRange(data, from, to); Arrays.sort(copy); for(int i = from; i < to; i++){ data[i] = copy[to - i - 1]; } } O (n log n)是位数。

实时演示:https://ideone.com/ZLaSa0

稍好一点的版本:n时间复杂度 https://ideone.com/RvmymX