Учитывая число, найдите следующее большее число, которое имеет тот же самый набор цифр, что и исходный номер
Я просто бомбил интервью и делал почти нулевой прогресс по моему собеседованию. Может ли кто-нибудь дать мне знать, как это сделать? Я пробовал искать в Интернете, но ничего не мог найти:
Учитывая число, найдите следующее более высокое число, которое имеет то же самое набор цифр в качестве исходного номера. Например: при возврате 38276 38627
Я хотел начать с определения индекса первой цифры (справа), которая была меньше, чем одна цифра. Затем я бы повернул последние цифры в подмножестве так, чтобы это было следующее самое большое число, состоящее из одних и тех же цифр, но застряло.
Интервьюер также предложил попробовать поменять цифры по одному, но я не мог понять алгоритм и просто смотрел на экран примерно 20-30 минут. Само собой разумеется, я думаю, что мне придется продолжать охоту за работой.
изменить: за что его стоит, меня пригласили на следующий раунд интервью
Ответы
Ответ 1
Вы можете сделать это в O(n)
(где n
- количество цифр):
Начиная с правой стороны, вы обнаружите первую пару цифр, так что левая цифра меньше, чем правая цифра. Позвольте ссылаться на левую цифру на "digit-x". Найдите наименьшее число, большее, чем цифра-x справа от цифры-x, и поместите его сразу слева от цифры-x. Наконец, отсортируйте оставшиеся цифры в порядке возрастания - так как они уже были в порядке убывания, все, что вам нужно сделать, это изменить их (за исключением цифры-x, которую можно поместить в нужное место в O(n)
).
Пример сделает это более понятным:
123456784987654321
start with a number
123456784 987654321
^the first place from the right where the left-digit is less than the right
Digit "x" is 4
123456784 987654321
^find the smallest digit larger than 4 to the right
123456785 4 98764321
^place it to the left of 4
123456785 4 12346789
123456785123446789
^sort the digits to the right of 5. Since all of them except
the '4' were already in descending order, all we need to do is
reverse their order, and find the correct place for the '4'
Доказательство корректности:
Позвольте использовать заглавные буквы для определения цифр и строчных цифр. Синтаксис AB
означает "конкатенация строк A
и B
". <
- лексикографическое упорядочение, которое совпадает с целым порядком, когда разрядные строки имеют одинаковую длину.
Наше исходное число N имеет вид AxB
, где x
- одна цифра, а B
сортируется по убыванию.
Число, найденное нашим алгоритмом, AyC
, где y ∈ B
- наименьшая цифра > x
(она должна существовать из-за выбора x
, см. Выше), а C
сортируется по возрастанию.
Предположим, что существует некоторое число (с использованием тех же цифр) N'
, что AxB < N' < AyC
. N'
должен начинаться с A
, иначе он не может попасть между ними, поэтому мы можем записать его в форме AzD
. Теперь наше неравенство AxB < AzD < AyC
, что эквивалентно xB < zD < yC
, где все три цифры содержат одни и те же цифры.
Чтобы это было верно, мы должны иметь x <= z <= y
. Поскольку y
- наименьшая цифра > x
, z
не может быть между ними, поэтому либо z = x
, либо z = y
. Скажите z = x
. Тогда наше неравенство xB < xD < yC
, что означает B < D
, где оба B
и D
имеют одинаковые цифры. Однако B сортируется по убыванию, поэтому нет строки с теми цифрами, которые больше ее. Таким образом, мы не можем иметь B < D
. Следуя тем же шагам, мы видим, что если z = y
, мы не можем иметь D < C
.
Поэтому N'
не может существовать, что означает, что наш алгоритм правильно находит следующее наибольшее число.
Ответ 2
Почти идентичная проблема возникла как проблема с кодовой замятием и имеет здесь решение:
http://code.google.com/codejam/contest/dashboard?c=186264#s=a&a=1
Здесь приведено краткое описание метода с использованием примера:
34722641
а. Разделите последовательность цифр на две части, чтобы правая часть была как можно дольше, оставаясь в порядке убывания:
34722 641
(Если все число находится в порядке убывания, больше не нужно делать число без добавления цифр.)
B.1. Выберите последнюю цифру первой последовательности:
3472(2) 641
В .2. Найдите наименьшую цифру во второй последовательности, которая больше, чем она:
3472(2) 6(4)1
В .3. Поменяйте их:
3472(2) 6(4)1
->
3472(4) 6(2)1
->
34724 621
С. Сортируйте вторую последовательность в порядке возрастания:
34724 126
Д. Готово!
34724126
Ответ 3
Здесь компактное (но отчасти грубое) решение в Python
def findnext(ii): return min(v for v in (int("".join(x)) for x in
itertools.permutations(str(ii))) if v>ii)
В C++ вы можете сделать перестановки следующим образом: fooobar.com/questions/32043/... (это тот же алгоритм, что и в itertools)
Здесь реализация верхнего ответа, описанного Weeble и BlueRaja, (другие ответы). Я сомневаюсь там что-нибудь лучше.
def findnext(ii):
iis=list(map(int,str(ii)))
for i in reversed(range(len(iis))):
if i == 0: return ii
if iis[i] > iis[i-1] :
break
left,right=iis[:i],iis[i:]
for k in reversed(range(len(right))):
if right[k]>left[-1]:
right[k],left[-1]=left[-1],right[k]
break
return int("".join(map(str,(left+sorted(right)))))
Ответ 4
Как минимум, вот пара примеров грубой силы String на основе решений, которые вы должны были бы придумать прямо с головы:
список цифр в 38276
отсортирован - 23678
список цифр в 38627
отсортирован как 23678
Приращение грубой силы, сортировка и сравнение
Вдоль решений грубой силы будет преобразован в строку
и скопировать все возможные числа, используя эти цифры.
Создайте все из них, поместите их в список и отсортируйте,
введите следующую запись после целевой записи.
Если вы потратили на это 30 минут и по крайней мере не придумали хотя бы подход грубой силы, я бы тоже не нанял вас.
В деловом мире решение, которое является неэлегантным, медленным и неуклюжим, но выполняет свою работу, всегда более ценно, чем никакое решение вообще, факт, который в значительной степени описывает деловое программное обеспечение all неэлегантный, медленный и неуклюжий.
Ответ 5
function foo(num){
sortOld = num.toString().split("").sort().join('');
do{
num++;
sortNew = num.toString().split("").sort().join('');
}while(sortNew!==sortOld);
return num;
}
Ответ 6
Ваша идея
Я хотел начать с определения индекса первой цифры (справа), которая была меньше, чем одна цифра. Затем я бы повернул последние цифры в подмножестве так, чтобы это было следующее самое большое число, состоящее из одних и тех же цифр, но застряло.
довольно хорошо, на самом деле. Вам просто нужно учитывать не только последнюю цифру, но и все цифры меньшей значимости, чем в настоящее время. Поскольку до того, как это достигнуто, у нас есть монотонная последовательность цифр, то есть самая правая цифра, меньшая, чем ее правая сосед. Рассматривать
1234675
^
Следующее большее число с одинаковыми цифрами
1234756
Найденная цифра заменяется на последнюю цифру - наименьшую из считанных цифр - и оставшиеся цифры расположены в порядке возрастания.
Ответ 7
Я уверен, что ваш собеседник пытался мягко подтолкнуть вас к чему-то вроде этого:
local number = 564321;
function split(str)
local t = {};
for i = 1, string.len(str) do
table.insert(t, str.sub(str,i,i));
end
return t;
end
local res = number;
local i = 1;
while number >= res do
local t = split(tostring(res));
if i == 1 then
i = #t;
end
t[i], t[i-1] = t[i-1], t[i];
i = i - 1;
res = tonumber(table.concat(t));
end
print(res);
Не обязательно самое эффективное или элегантное решение, но оно решает приведенный пример в два цикла и свопирует цифры по одному, как он предполагал.
Ответ 8
Это очень интересный вопрос.
Вот моя версия java. Возьмите меня около 3 часов, чтобы выяснить шаблон, чтобы полностью закончить код, прежде чем я проверил комментарии других участников. Рад видеть, что моя идея совсем не похожа на других.
O (n). Честно говоря, я проиграю это интервью, если время будет всего 15 минут и потребует полного завершения кода на белой доске.
Вот несколько интересных моментов для моего решения:
- Избегайте сортировки.
- Избегайте операции со строкой
- Достижение сложности O (logN)
Я поставил подробный комментарий в моем коде и Big O на каждом шагу.
public int findNextBiggestNumber(int input ) {
//take 1358642 as input for example.
//Step 1: split the whole number to a list for individual digital 1358642->[2,4,6,8,5,3,1]
// this step is O(n)
int digitalLevel=input;
List<Integer> orgNumbersList=new ArrayList<Integer>() ;
do {
Integer nInt = new Integer(digitalLevel % 10);
orgNumbersList.add(nInt);
digitalLevel=(int) (digitalLevel/10 ) ;
} while( digitalLevel >0) ;
int len= orgNumbersList.size();
int [] orgNumbers=new int[len] ;
for(int i=0;i<len;i++){
orgNumbers[i ] = orgNumbersList.get(i).intValue();
}
//step 2 find the first digital less than the digital right to it
// this step is O(n)
int firstLessPointer=1;
while(firstLessPointer<len&&(orgNumbers[firstLessPointer]>orgNumbers[ firstLessPointer-1 ])){
firstLessPointer++;
}
if(firstLessPointer==len-1&&orgNumbers[len-1]>=orgNumbers[len-2]){
//all number is in sorted order like 4321, no answer for it, return original
return input;
}
//when step 2 step finished, firstLessPointer pointing to number 5
//step 3 fristLessPointer found, need to find to first number less than it from low digital in the number
//This step is O(n)
int justBiggerPointer= 0 ;
while(justBiggerPointer<firstLessPointer&& orgNumbers[justBiggerPointer]<orgNumbers[firstLessPointer]){
justBiggerPointer++;
}
//when step 3 finished, justBiggerPointer pointing to 6
//step 4 swap the elements of justBiggerPointer and firstLessPointer .
// This is O(1) operation for swap
int tmp= orgNumbers[firstLessPointer] ;
orgNumbers[firstLessPointer]= orgNumbers[justBiggerPointer] ;
orgNumbers[justBiggerPointer]=tmp ;
// when step 4 finished, the list looks like [2,4,5,8,6,3,1] the digital in the list before
// firstLessPointer is already sorted in our previous operation
// we can return result from this list but in a differrent way
int result=0;
int i=0;
int lowPointer=firstLessPointer;
//the following pick number from list from the position just before firstLessPointer, here is 8 -> 5 -> 4 -> 2
//This Operation is O(n)
while(lowPointer>0) {
result+= orgNumbers[--lowPointer]* Math.pow(10,i);
i++;
}
//the following pick number from list from position firstLessPointer
//This Operation is O(n)
while(firstLessPointer<len) {
result+= orgNumbers[firstLessPointer++ ]* Math.pow(10,i);
i++;
}
return result;
}
Вот результат, запущенный в Intellj:
959879532-->959892357
1358642-->1362458
1234567-->1234576
77654321-->77654321
38276-->38627
47-->74
Ответ 9
Возьмите число и разделите его на цифры. Итак, если у нас есть 5-значное число, у нас есть 5 цифр: abcde
Теперь замените d и e и сравните с исходным номером, если он больше, вы получите свой ответ.
Если он не больше, замените e и c. Теперь сравните, и если он будет меньше swap d и e снова (обратите внимание на рекурсию), возьмите наименьший.
Продолжайте, пока не найдете большее число. С рекурсией он должен работать как около 9 строк схемы, или 20 из С#.
Ответ 10
Выполнение javascript алгоритма @BlueRaja.
var Bar = function(num){
num = num.toString();
var max = 0;
for(var i=num.length-2; i>0; i--){
var numArray = num.substr(i).split("");
max = Math.max.apply(Math,numArray);
if(numArray[0]<max){
numArray.sort(function(a,b){return a-b;});
numArray.splice(-1);
numArray = numArray.join("");
return Number(num.substr(0,i)+max+numArray);
}
}
return -1;
};
Ответ 11
Решение (на Java) может быть следующим (я уверен, что друзья здесь могут найти лучшее):
Начните менять цифры с конца строки до тех пор, пока не получите большее число.
То есть сначала начните движение вверх по нижней цифре. Затем следующий более высокий и т.д., пока вы не нажмете следующий выше.
Затем сортируйте остальные.
В вашем примере вы получите:
38276 --> 38267 (smaller) --> 38627 Found it
^ ^ ^
public static int nextDigit(int number){
String num = String.valueOf(number);
int stop = 0;
char [] chars = null;
outer:
for(int i = num.length() - 1; i > 0; i--){
chars = num.toCharArray();
for(int j = i; j > 0; j--){
char temp = chars[j];
chars[j] = chars[j - 1];
chars[j - 1] = temp;
if(Integer.valueOf(new String(chars)) > number){
stop = j;
break outer;
}
}
}
Arrays.sort(chars, stop, chars.length);
return Integer.valueOf(new String(chars));
}
Ответ 12
Я тестировал только два числа. Они работали.
Как ИТ-менеджер в течение 8 лет до выхода на пенсию в декабре прошлого года, я заботился о трех вещах:
1) Точность: хорошо, если она работает - всегда.
2) Скорость: должна быть приемлемой для пользователя.
3) Ясность: Я, наверное, не такой умный, как ты, но я плачу тебе. Обязательно объясните, что вы делаете, на английском языке.
Омар, удачи в будущем.
Sub Main()
Dim Base(0 To 9) As Long
Dim Test(0 To 9) As Long
Dim i As Long
Dim j As Long
Dim k As Long
Dim ctr As Long
Const x As Long = 776914648
Dim y As Long
Dim z As Long
Dim flag As Boolean
' Store the digit count for the original number in the Base vector.
For i = 0 To 9
ctr = 0
For j = 1 To Len(CStr(x))
If Mid$(CStr(x), j, 1) = i Then ctr = ctr + 1
Next j
Base(i) = ctr
Next i
' Start comparing from the next highest number.
y = x + 1
Do
' Store the digit count for the each new number in the Test vector.
flag = False
For i = 0 To 9
ctr = 0
For j = 1 To Len(CStr(y))
If Mid$(CStr(y), j, 1) = i Then ctr = ctr + 1
Next j
Test(i) = ctr
Next i
' Compare the digit counts.
For k = 0 To 9
If Test(k) <> Base(k) Then flag = True
Next k
' If no match, INC and repeat.
If flag = True Then
y = y + 1
Erase Test()
Else
z = y ' Match.
End If
Loop Until z > 0
MsgBox (z), , "Solution"
End Sub
Ответ 13
Если вы программируете на С++, вы можете использовать next_permutation
:
#include <algorithm>
#include <string>
#include <iostream>
int main(int argc, char **argv) {
using namespace std;
string x;
while (cin >> x) {
cout << x << " -> ";
next_permutation(x.begin(),x.end());
cout << x << "\n";
}
return 0;
}
Ответ 14
При ответе на этот вопрос я ничего не знал об алгоритме грубой силы, поэтому подошел к нему с другой стороны. Я решил поискать весь спектр возможных решений, в которые можно переставить это число, начиная с number_given + 1 до максимального доступного числа (999 для трехзначного числа, 9999 для четырехзначного и т.д.). Я сделал подобный поиск палиндрома со словами, отсортировав номера каждого решения и сравнив его с отсортированным числом, указанным в качестве параметра. Затем я просто вернул первое решение в массиве решений, так как это было бы следующим возможным значением.
Вот мой код в Ruby:
def PermutationStep(num)
a = []
(num.to_s.length).times { a.push("9") }
max_num = a.join('').to_i
verify = num.to_s.split('').sort
matches = ((num+1)..max_num).select {|n| n.to_s.split('').sort == verify }
if matches.length < 1
return -1
else
matches[0]
end
end
Ответ 15
Для хорошей записи о том, как это сделать, см. " Алгоритм L" в Knuth " Искусство программирования: Создание всех перестановок" (.ps.gz).
Ответ 16
Вот мой код, это измененная версия этот пример
Библиотека:
class NumPermExample
{
// print N! permutation of the characters of the string s (in order)
public static void perm1(String s, ArrayList<String> perm)
{
perm1("", s);
}
private static void perm1(String prefix, String s, ArrayList<String> perm)
{
int N = s.length();
if (N == 0)
{
System.out.println(prefix);
perm.add(prefix);
}
else
{
for (int i = 0; i < N; i++)
perm1(prefix + s.charAt(i), s.substring(0, i)
+ s.substring(i+1, N));
}
}
// print N! permutation of the elements of array a (not in order)
public static void perm2(String s, ArrayList<String> perm)
{
int N = s.length();
char[] a = new char[N];
for (int i = 0; i < N; i++)
a[i] = s.charAt(i);
perm2(a, N);
}
private static void perm2(char[] a, int n, ArrayList<String> perm)
{
if (n == 1)
{
System.out.println(a);
perm.add(new String(a));
return;
}
for (int i = 0; i < n; i++)
{
swap(a, i, n-1);
perm2(a, n-1);
swap(a, i, n-1);
}
}
// swap the characters at indices i and j
private static void swap(char[] a, int i, int j)
{
char c;
c = a[i]; a[i] = a[j]; a[j] = c;
}
// next higher permutation
public static int nextPermutation (int number)
{
ArrayList<String> perm = new ArrayList<String>();
String cur = ""+number;
int nextPerm = 0;
perm1(cur, perm);
for (String s : perm)
{
if (Integer.parseInt(s) > number
&& (nextPerm == 0 ||
Integer.parseInt(s) < nextPerm))
{
nextPerm = Integer.parseInt(s);
}
}
return nextPerm;
}
}
Тест:
public static void main(String[] args)
{
int a = 38276;
int b = NumPermExample.nextPermutation(a);
System.out.println("a: "+a+", b: "+b);
}
Ответ 17
Добавьте 9 к указанному n значению числа. Затем проверьте, находится ли он в пределах лимита (первое (n + 1) цифровое число). Если это тогда, проверьте, являются ли цифры нового номера такими же, как цифры в исходном номере.
Повторите добавление 9 до тех пор, пока оба условия не будут истинными.
Остановите алгоритм, когда число выходит за пределы.
Я не мог придумать противоречивый тестовый пример для этого метода.
Ответ 18
#include<stdio.h>
#include<cstring>
#include<iostream>
#include<string.h>
#include<sstream>
#include<iostream>
using namespace std;
int compare (const void * a, const void * b)
{
return *(char*)a-*(char*)b;
}
/*-----------------------------------------------*/
int main()
{
char number[200],temp;
cout<<"please enter your number?"<<endl;
gets(number);
int n=strlen(number),length;
length=n;
while(--n>0)
{
if(number[n-1]<number[n])
{
for(int i=length-1;i>=n;i--)
{
if(number[i]>number[n-1])
{
temp=number[i];
number[i]=number[n-1];
number[n-1]=temp;
break;
}
}
qsort(number+n,length-n,sizeof(char),compare);
puts(number);
return 0;
}
}
cout<<"sorry itz the greatest one :)"<<endl;
}
Ответ 19
Простое решение с использованием python:
def PermutationStep(num):
if sorted(list(str(num)), reverse=True) == list(str(num)):
return -1
ls = list(str(num))
n = 0
inx = 0
for ind, i in enumerate(ls[::-1]):
if i < n:
n = i
inx = -(ind + 1)
break
n = i
ls[inx], ls[inx + 1] = ls[inx + 1], ls[inx]
nl = ls[inx::-1][::-1]
ln = sorted(ls[inx+1:])
return ''.join(nl) + ''.join(ln)
print PermutationStep(23514)
Вывод:
23541
Ответ 20
public static void findNext(long number){
/* convert long to string builder */
StringBuilder s = new StringBuilder();
s.append(number);
int N = s.length();
int index=-1,pivot=-1;
/* from tens position find the number (called pivot) less than the number in right */
for(int i=N-2;i>=0;i--){
int a = s.charAt(i)-'0';
int b = s.charAt(i+1)-'0';
if(a<b){
pivot = a;
index =i;
break;
}
}
/* if no such pivot then no solution */
if(pivot==-1) System.out.println(" No such number ")
else{
/* find the minimum highest number to the right higher than the pivot */
int nextHighest=Integer.MAX_VALUE, swapIndex=-1;
for(int i=index+1;i<N;i++){
int a = s.charAt(i)-'0';
if(a>pivot && a<nextHighest){
nextHighest = a;
swapIndex=i;
}
}
/* swap the pivot and next highest number */
s.replace(index,index+1,""+nextHighest);
s.replace(swapIndex,swapIndex+1,""+pivot);
/* sort everything to right of pivot and replace the sorted answer to right of pivot */
char [] sort = s.substring(index+1).toCharArray();
Arrays.sort(sort);
s.replace(index+1,N,String.copyValueOf(sort));
System.out.println("next highest number is "+s);
}
}
Ответ 21
Ниже приведен код для генерации всех перестановок числа.. хотя нужно сначала преобразовать это целое число в строку с использованием String.valueOf(integer).
/**
*
* Inserts a integer at any index around string.
*
* @param number
* @param position
* @param item
* @return
*/
public String insertToNumberStringAtPosition(String number, int position,
int item) {
String temp = null;
if (position >= number.length()) {
temp = number + item;
} else {
temp = number.substring(0, position) + item
+ number.substring(position, number.length());
}
return temp;
}
/**
* To generate permutations of a number.
*
* @param number
* @return
*/
public List<String> permuteNumber(String number) {
List<String> permutations = new ArrayList<String>();
if (number.length() == 1) {
permutations.add(number);
return permutations;
}
// else
int inserterDig = (int) (number.charAt(0) - '0');
Iterator<String> iterator = permuteNumber(number.substring(1))
.iterator();
while (iterator.hasNext()) {
String subPerm = iterator.next();
for (int dig = 0; dig <= subPerm.length(); dig++) {
permutations.add(insertToNumberStringAtPosition(subPerm, dig,
inserterDig));
}
}
return permutations;
}
Ответ 22
#include<bits/stdc++.h>
using namespace std;
int main()
{
int i,j,k,min,len,diff,z,u=0,f=0,flag=0;
char temp[100],a[100]`enter code here`,n;
min=9999;
//cout<<"Enter the number\n";
cin>>a;
len=strlen(a);
for(i=0;i<len;i++)
{
if(a[i]<a[i+1]){flag=1;break;}
}
if(flag==0){cout<<a<<endl;}
else
{
for(i=len-1;i>=0;i--)if(((int)a[i-1])<((int)a[i]))break;
for(k=0;k<i-1;k++)cout<<a[k];
for(j=i;j<len;j++)
{
if(((int)a[j]-48)-((int)a[i-1]-48)>0)
{
diff=((int)a[j]-48)-((int)a[i-1]-48);
if(diff<min){n=a[j];min=diff;}
}
}
cout<<n;
for(z=i-1;z<len;z++)
{
temp[u]=a[z];
u++;
}
temp[u]='\0';
sort(temp,temp+strlen(temp));
for(z=0;z<strlen(temp);z++){if(temp[z]==n&&f==0){f=1;continue;}cout<<temp[z];}
}
return 0;
}
Ответ 23
Вот моя реализация этого в Ruby:
def foo num
num = num.to_s.chars.map(&:to_i)
return num.join.to_i if num.size < 2
for left in (num.size-2).downto(0) do
for right in (num.size-1).downto(left+1) do
if num[right]>num[left]
num[left],num[right] = num[right],num[left]
return (num[0..left] + num[left+1..num.size-1].sort).join.to_i
end
end
end
return num.join.to_i
end
p foo 38276
#will print: 38627
Ответ 24
Еще одна реализация Java, запускаемая из коробки и завершенная с помощью тестов.
Это решение представляет собой O (n) пространство и время, используя хорошее старое динамическое программирование.
Если вы хотите использовать bruteforce, есть 2 вида грубой силы:
-
Перепишите все вещи, затем выберите min выше: O (n!)
-
Подобно этой реализации, но вместо DP, выполняйте шаг заселения
Карта indexToIndexOfNextSmallerLeft будет работать в O (n ^ 2).
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class NextHigherSameDigits {
public long next(final long num) {
final char[] chars = String.valueOf(num).toCharArray();
final int[] digits = new int[chars.length];
for (int i = 0; i < chars.length; i++) {
digits[i] = Character.getNumericValue(chars[i]);
}
final Map<Integer, Integer> indexToIndexOfNextSmallerLeft = new HashMap<>();
indexToIndexOfNextSmallerLeft.put(1, digits[1] > digits[0] ? 0 : null);
for (int i = 2; i < digits.length; i++) {
final int left = digits[i - 1];
final int current = digits[i];
Integer indexOfNextSmallerLeft = null;
if (current > left) {
indexOfNextSmallerLeft = i - 1;
} else {
final Integer indexOfnextSmallerLeftOfLeft = indexToIndexOfNextSmallerLeft.get(i - 1);
final Integer nextSmallerLeftOfLeft = indexOfnextSmallerLeftOfLeft == null ? null :
digits[indexOfnextSmallerLeftOfLeft];
if (nextSmallerLeftOfLeft != null && current > nextSmallerLeftOfLeft) {
indexOfNextSmallerLeft = indexOfnextSmallerLeftOfLeft;
} else {
indexOfNextSmallerLeft = null;
}
}
indexToIndexOfNextSmallerLeft.put(i, indexOfNextSmallerLeft);
}
Integer maxOfindexOfNextSmallerLeft = null;
Integer indexOfMinToSwapWithNextSmallerLeft = null;
for (int i = digits.length - 1; i >= 1; i--) {
final Integer indexOfNextSmallerLeft = indexToIndexOfNextSmallerLeft.get(i);
if (maxOfindexOfNextSmallerLeft == null ||
(indexOfNextSmallerLeft != null && indexOfNextSmallerLeft > maxOfindexOfNextSmallerLeft)) {
maxOfindexOfNextSmallerLeft = indexOfNextSmallerLeft;
if (maxOfindexOfNextSmallerLeft != null && (indexOfMinToSwapWithNextSmallerLeft == null ||
digits[i] < digits[indexOfMinToSwapWithNextSmallerLeft])) {
indexOfMinToSwapWithNextSmallerLeft = i;
}
}
}
if (maxOfindexOfNextSmallerLeft == null) {
return -1;
} else {
swap(digits, indexOfMinToSwapWithNextSmallerLeft, maxOfindexOfNextSmallerLeft);
reverseRemainingOfArray(digits, maxOfindexOfNextSmallerLeft + 1);
return backToLong(digits);
}
}
private void reverseRemainingOfArray(final int[] digits, final int startIndex) {
final int[] tail = Arrays.copyOfRange(digits, startIndex, digits.length);
for (int i = tail.length - 1; i >= 0; i--) {
digits[(digits.length - 1) - i] = tail[i];
}
}
private void swap(final int[] digits, final int currentIndex, final int indexOfNextSmallerLeft) {
int temp = digits[currentIndex];
digits[currentIndex] = digits[indexOfNextSmallerLeft];
digits[indexOfNextSmallerLeft] = temp;
}
private long backToLong(int[] digits) {
StringBuilder sb = new StringBuilder();
for (long i : digits) {
sb.append(String.valueOf(i));
}
return Long.parseLong(sb.toString());
}
@Test
public void test() {
final long input1 = 34722641;
final long expected1 = 34724126;
final long output1 = new NextHigherSameDigits().next(input1);
assertEquals(expected1, output1);
final long input2 = 38276;
final long expected2 = 38627;
final long output2 = new NextHigherSameDigits().next(input2);
assertEquals(expected2, output2);
final long input3 = 54321;
final long expected3 = -1;
final long output3 = new NextHigherSameDigits().next(input3);
assertEquals(expected3, output3);
final long input4 = 123456784987654321L;
final long expected4 = 123456785123446789L;
final long output4 = new NextHigherSameDigits().next(input4);
assertEquals(expected4, output4);
final long input5 = 9999;
final long expected5 = -1;
final long output5 = new NextHigherSameDigits().next(input5);
assertEquals(expected5, output5);
}
}
Ответ 25
Нам нужно найти правильный бит 0, за которым следует 1, и перевернуть это правое большинство из 0 бит в 1.
например, скажем, наш вход 487, который является 111100111 в двоичном формате.
мы переворачиваем правое большинство 0, у которого есть 1 после него
поэтому мы получаем
111101111
но теперь у нас есть лишний 1 и один меньше 0, поэтому мы уменьшаем число 1 справа от флип
бит на 1 и увеличить значение 0 бит на 1, что дает
111101011 - двоичный код 491
int getNextNumber(int input)
{
int flipPosition=0;
int trailingZeros=0;
int trailingOnes=0;
int copy = input;
//count trailing zeros
while(copy != 0 && (copy&1) == 0 )
{
++trailingZeros;
//test next bit
copy = copy >> 1;
}
//count trailing ones
while(copy != 0 && (copy&1) == 1 )
{
++trailingOnes;
//test next bit
copy = copy >> 1;
}
//if we have no 1 (i.e input is 0) we cannot form another pattern with
//the same number of 1 which will increment the input, or if we have leading consecutive
//ones followed by consecutive 0 up to the maximum bit size of a int
//we cannot increase the input whilst preserving the original no of 0 and
//1 in the bit pattern
if(trailingZeros + trailingOnes == 0 || trailingZeros + trailingOnes == 31)
return -1;
//flip first 0 followed by a 1 found from the right of the bit pattern
flipPosition = trailingZeros + trailingOnes+1;
input |= 1<<(trailingZeros+trailingOnes);
//clear fields to the right of the flip position
int mask = ~0 << (trailingZeros+trailingOnes);
input &= mask;
//insert a bit pattern to the right of the flip position that will contain
//one less 1 to compensate for the bit we switched from 0 to 1
int insert = flipPosition-1;
input |= insert;
return input;
}
Ответ 26
int t,k,num3,num5;
scanf("%d",&t);
int num[t];
for(int i=0;i<t;i++){
scanf("%d",&num[i]);
}
for(int i=0;i<t;i++){
k=(((num[i]-1)/3)+1);
if(k<0)
printf("-1");
else if(num[i]<3 || num[i]==4 || num[i]==7)
printf("-1");
else{
num3=3*(2*num[i] - 5*k);
num5=5*(3*k -num[i]);
for(int j=0;j<num3;j++)
printf("5");
for(int j=0;j<num5;j++)
printf("3");
}
printf("\n");
}
Ответ 27
Вот реализация Java
public static int nextHigherNumber(int number) {
Integer[] array = convertToArray(number);
int pivotIndex = pivotMaxIndex(array);
int digitInFirstSequence = pivotIndex -1;
int lowerDigitIndexInSecondSequence = lowerDigitIndex(array[digitInFirstSequence], array, pivotIndex);
swap(array, digitInFirstSequence, lowerDigitIndexInSecondSequence);
doRercursiveQuickSort(array, pivotIndex, array.length - 1);
return arrayToInteger(array);
}
public static Integer[] convertToArray(int number) {
int i = 0;
int length = (int) Math.log10(number);
int divisor = (int) Math.pow(10, length);
Integer temp[] = new Integer[length + 1];
while (number != 0) {
temp[i] = number / divisor;
if (i < length) {
++i;
}
number = number % divisor;
if (i != 0) {
divisor = divisor / 10;
}
}
return temp;
}
private static int pivotMaxIndex(Integer[] array) {
int index = array.length - 1;
while(index > 0) {
if (array[index-1] < array[index]) {
break;
}
index--;
}
return index;
}
private static int lowerDigitIndex(int number, Integer[] array, int fromIndex) {
int lowerMaxIndex = fromIndex;
int lowerMax = array[lowerMaxIndex];
while (fromIndex < array.length - 1) {
if (array[fromIndex]> number && lowerMax > array[fromIndex]) {
lowerMaxIndex = fromIndex;
}
fromIndex ++;
}
return lowerMaxIndex;
}
public static int arrayToInteger(Integer[] array) {
int number = 0;
for (int i = 0; i < array.length; i++) {
number+=array[i] * Math.pow(10, array.length-1-i);
}
return number;
}
Вот тесты модулей
@Test
public void nextHigherNumberTest() {
assertThat(ArrayUtils.nextHigherNumber(34722641), is(34724126));
assertThat(ArrayUtils.nextHigherNumber(123), is(132));
}
Ответ 28
Я знаю, что это очень старый вопрос, но все же я не нашел простой код в С#. Это может помочь ребятам, которые посещают интервью.
class Program
{
static void Main(string[] args)
{
int inputNumber = 629;
int i, currentIndexOfNewArray = 0;
int[] arrayOfInput = GetIntArray(inputNumber);
var numList = arrayOfInput.ToList();
int[] newArray = new int[arrayOfInput.Length];
do
{
int temp = 0;
int digitFoundAt = 0;
for (i = numList.Count; i > 0; i--)
{
if (numList[i - 1] > temp)
{
temp = numList[i - 1];
digitFoundAt = i - 1;
}
}
newArray[currentIndexOfNewArray] = temp;
currentIndexOfNewArray++;
numList.RemoveAt(digitFoundAt);
} while (arrayOfInput.Length > currentIndexOfNewArray);
Console.WriteLine(GetWholeNumber(newArray));
Console.ReadKey();
}
public static int[] GetIntArray(int num)
{
IList<int> listOfInts = new List<int>();
while (num > 0)
{
listOfInts.Add(num % 10);
num = num / 10;
}
listOfInts.Reverse();
return listOfInts.ToArray();
}
public static double GetWholeNumber(int[] arrayNumber)
{
double result = 0;
double multiplier = 0;
var length = arrayNumber.Count() - 1;
for(int i = 0; i < arrayNumber.Count(); i++)
{
multiplier = Math.Pow(10.0, Convert.ToDouble(length));
result += (arrayNumber[i] * multiplier);
length = length - 1;
}
return result;
}
}
Ответ 29
Очень простая реализация с использованием Javascript, следующего по величине числа с одинаковыми цифрами
/*
Algorithm applied
I) Traverse the given number from rightmost digit, keep traversing till you find a digit which is smaller than the previously traversed digit. For example, if the input number is "534976", we stop at 4 because 4 is smaller than next digit 9. If we do not find such a digit, then output is "Not Possible".
II) Now search the right side of above found digit ‘d’ for the smallest digit greater than ‘d’. For "534976″, the right side of 4 contains "976". The smallest digit greater than 4 is 6.
III) Swap the above found two digits, we get 536974 in above example.
IV) Now sort all digits from position next to ‘d’ to the end of number. The number that we get after sorting is the output. For above example, we sort digits in bold 536974. We get "536479" which is the next greater number for input 534976.
*/
function findNext(arr)
{
let i;
//breaking down a digit into arrays of string and then converting back that array to number array
let arr1=arr.toString().split('').map(Number) ;
//started to loop from the end of array
for(i=arr1.length;i>0;i--)
{
//looking for if the current number is greater than the number next to it
if(arr1[i]>arr1[i-1])
{// if yes then we break the loop it so that we can swap and sort
break;}
}
if(i==0)
{console.log("Not possible");}
else
{
//saving that big number and smaller number to the left of it
let smlNum =arr1[i-1];
let bigNum =i;
/*now looping again and checking if we have any other greater number, if we have one AFTER big number and smaller number to the right.
A greater number that is of course greater than that smaller number but smaller than the first number we found.
Why are doing this? Because that is an algorithm to find next higher number with same digits.
*/
for(let j=i+1;j<arr1.length;j++)
{//What if there are no digits afters those found numbers then of course loop will not be initiated otherwise...
if(arr1[j]> smlNum && arr1[j]<arr1[i])
{// we assign that other found number here and replace it with the one we found before
bigNum=j;
}
} //now we are doing swapping of places the small num and big number , 3rd part of alogorithm
arr1[i-1]=arr1[bigNum];
arr1[bigNum]=smlNum;
//returning array
//too many functions applied sounds complicated right but no, here is the trick
//return arr first then apply each function one by one to see output and then further another func to that output to match your needs
// so here after swapping , 4th part of alogorithm is to sort the array right after the 1st small num we found
// to do that first we simple take part of array, we splice it and then we apply sort fucntion, then check output (to check outputs, pls use chrome dev console)
//and then simply the rest concat and join to main one digit again.
return arr1.concat((arr1.splice(i,arr1.length)).sort(function(a, b){return a-b})).join('');
// Sorry to make it too long but its fun explaining things in much easier ways as much as possible!!
}
}
findNext(1234);
Так как есть много комментариев, так что лучше скопировать его в текстовый редактор.
Спасибо!
Ответ 30
Есть много хороших ответов, но я не нашел достойной реализации Java. Вот мои два цента:
public void findNext(int[] nums) {
int i = nums.length - 1;
// nums[i - 1] will be the first non increasing number
while (i > 0 && nums[i] <= nums[i - 1]) {
i--;
}
if (i == 0) {
System.out.println("it has been the greatest already");
} else {
// Find the smallest digit in the second sequence that is larger than it:
int j = nums.length - 1;
while (j >= 0 && nums[j] < nums[i - 1]) {
j--;
}
swap(nums, i - 1, j);
Arrays.sort(nums, i, nums.length);
System.out.println(Arrays.toString(nums));
}
}
public void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}