因此,最近我正在检查编码挑战之一。这个问题很吸引人,所以只想知道在时间和空间复杂度上是否有更好的方法。
问题:给定数字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
注意:当数量很大时,上述解决方案将花费更多时间
答案 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