给定一个数字,找到下一个更大的数字,该数字与原始数字具有完全相同的数字集


226

我只是轰炸了一次采访,在采访问题上取得了几乎零进展。谁能让我知道该怎么做?我尝试在线搜索,但找不到任何内容:

给定一个数字,找到下一个更大的数字,该数字与原始数字具有完全相同的数字集。例如:给定38276返回38627

我想从找到小于该位数的第一个数字的索引开始(从右边开始)。然后,我将轮换子集中的最后一个数字,以使其成为由相同数字组成的下一个最大数字,但卡住了。

面试官还建议尝试一次交换一位数字,但我无法弄清楚算法,只能盯着屏幕看20到30分钟。不用说,我认为我将不得不继续寻找工作。

编辑:出于什么价值,我被邀请参加下一轮采访


15
无需过多考虑,起码至少是蛮力计算数字的所有排列并获取大于输入数字的最小数字
BrokenGlass 2012年

13
在C ++中,您可以只使用next_permutation;-)
thedayturns 2012年

9
仅供参考,这是我在大约15分钟内几乎没有想到的情况下解决问题的方法:我首先花了5分钟编写了蛮力算法,该算法仅创建了一组数字的所有可能排列,对其进行排序并显示出来。我花了5分钟浏览这些数据,直到从列表中出现一个模式(经过短时间的查找,这里的O(n)接受的解决方案才变得清晰),然后我花了5分钟对O(n)算法进行了编码。
李·李

1
通常,这对于在遇到问题时提出解决此类问题的算法来说不是一个坏方法-对一些较小的样本使用蛮力来创建大量数据,然后可以使用这些数据更轻松地查看模式。
李·李

19
我还想指出,如果您真的不知道这样做的有效方法,那么无所事事肯定会导致面试失败(在商业世界中,这无疑是错过产品截止日期的一种方法) 。当您陷入困境而不是放弃时,您应该只是蛮力将其强加,并在顶部的“ TODO:为性能而重构”之类的内容上发表评论。如果我正在面试并且有人这样做,我并不一定会让他们失败。至少他们想出了一些可行的方法,并且意识到即使找不到它们,也存在更好的方法。
Ben Lee

Answers:


272

您可以这样输入O(n)n位数是):

从右边开始,找到第一个数字对,以使左边的数字小于右边的数字。让我们用“ digit-x”来指代左数字。在数字-x的右边找到大于数字-x的最小数字,并将其放在数字-x的左侧。最后,将其余数字按升序排序-由于它们已经按降序排列,因此您要做的就是将它们反转(保存digit-x,可以将其放置在中的正确位置O(n)

一个示例将使这一点更加清楚:

123456784987654321
以数字开头

123456784 987654321
         ^左数小于右数的从右到右的第一位  
         数字“ x”为4

123456784 987654321
              ^在右侧找到大于4的最小数字

123456785 4 98764321
        ^将其放在4的左侧

123456785 4 12346789
123456785123446789
         ^将数字右边的5排序。因为除 
         “ 4”已经按降序排列,我们要做的就是 
         颠倒顺序,找到正确的'4'位置

正确性证明:

让我们用大写字母定义数字字符串,并用小写字母表示数字。语法的AB含义是“字符串AB” 的串联<是字典顺序,当数字字符串长度相等时,它与整数顺序相同。

我们的原始数字N的形式为AxB,其中x是一位数字,并B以降序排序。
我们的算法找到的数字是AyC,其中y ∈ B是最小数字> x (由于x选择的方式而必须存在,请参见上文),并且C以升序排序。

假设有一些数字(使用相同的数字)N'使得AxB < N' < AyCN'必须以开头,A否则它不能落在它们之间,因此我们可以将其编写为形式AzD。现在我们的不等式是AxB < AzD < AyC,它等于xB < zD < yC三个数字字符串都包含相同数字的地方。

为了使这一点成为现实,我们必须有x <= z <= y。由于y是最小的数字> xz所以不能在它们之间,所以z = xz = y。说z = x。然后我们的不平等xB < xD < yC,这意味着B < D其中两个BD具有相同的数字。然而,B是降序排序,所以没有字符串与比它大的数字。因此我们不能拥有B < D。遵循相同的步骤,我们看到if z = y不能拥有D < C

因此N'不存在,这意味着我们的算法正确找到了下一个最大的数字。


7
不错的解决方案!有一个问题。说“大于x的最小数字”是y。我们可以只交换x和y,然后反转x.index + 1-> end吗?
肯特

8
数字99999会怎样?
Sterex

19
@Sterex,不只是99999;数字已经按降序完全排序的任何数字都是最大值(例如,98765也没有解决方案)。由于算法的第1步将失败(不存在连续的数字对,因此“左数字小于右数字”),这很容易通过编程方式进行检测。
Ben Lee

3
@TMN:9大于8,所以您将9移到8的左侧:9 832然后将所有内容都移到9的右侧:9238
BlueRaja-Danny Pflughoeft 2012年

4
@Kent为您的解决方案的工作,你将不得不改变找到最小的数字大于4 右边,以寻找最小位数大于4时,从右侧。否则,例如1234567849876 55 4321将产生1234567851234 54 6789(而不是1234567851234 45 6789)。
挑剔

94

一个几乎相同的问题出现为Code Jam问题,在这里有一个解决方案:

http://code.google.com/codejam/contest/dashboard?c=186264#s=a&a=1

这是使用示例的方法摘要:

34722641

A.将数字序列一分为二,以便右侧部分尽可能长,同时保持降序排列:

34722 641

(如果整个数字按降序排列,那么不增加数字就不能做更大的数字。)

B.1。选择第一个序列的最后一位:

3472(2) 641

B.2。在第二个序列中找到大于它的最小数字:

3472(2) 6(4)1

B.3。交换它们:

3472(2) 6(4)1
->
3472(4) 6(2)1
->
34724 621

C.将第二个序列按升序排序:

34724 126

D.完成!

34724126

1
那里的错字:我认为“-> 34721 621”应该是“-> 34724 621”吗?
2012年

1
@bjnord好收获。固定。不知道我该如何处理-在随后的几行中是正确的。
Weeble 2012年

+1最佳答案在这里。直观,快速。(这也是我在纸上进行研究时想到的那个);)
Muhd

1
@Neel-在步骤C中,我们要排序的数字是降序排列的,除了在步骤B中交换的数字。要对它们进行排序,我们实际上只需要反转它们并将交换的数字放到正确的位置即可。这就是BlueRaja所描述的。
2013年

1
@Dhavaldave有什么问题?在步骤A中,您将获得“ 12”和“ 3”。在步骤B中,您将获得“ 13”和“ 2”。在步骤C中,没有任何变化。在步骤D中,您将获得“ 132”。唯一无法获得答案的情况是,该数字已经是可能的最大值,例如“ 321”。在这种情况下,步骤A会为您提供“”和“ 321”,并且您无法对拆分左侧使用空序列。
2013年

14

这是Python中的紧凑型(但部分是蛮力的)解决方案

def findnext(ii): return min(v for v in (int("".join(x)) for x in
    itertools.permutations(str(ii))) if v>ii)

在C ++中,您可以进行如下排列:https : //stackoverflow.com/a/9243091/1149664(与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)))))

有机会有人可以更新此消息吗?如显示的那样,似乎在Python 3中不起作用type 'map' has no len()。我只是将第二行更改为iis=list(map(int,str(ii)))。有人可以解释这if i == 0: return ii句话吗?为什么对111或531这样的输入起作用?谢谢。
Bowen Liu

我现在通过在iis = ...上添加´list()来修复python 3的问题。案例111和531没有解决方案,但是我的实现为此返回了111和531。您可以通过更改i == 0行来将其更改为发现更好的例外。
约翰·伦德伯格

谢谢。我实际上是朝另一个方向循环,所以我对i == 0感到困惑,而在我的情况下应该为i == len(iis)
Bowen Liu

8

至少,这里有几个基于字符串的蛮力示例解决方案示例,您应该能够想到:

38276排序的数字列表是23678

38627排序的数字列表是23678

蛮力增量,排序和比较

沿着蛮力解决方案将被转换为字符串,并使用这些数字将所有可能的数字蛮力化。

从全部中创建整数,将它们放在列表中并进行排序,在目标条目之后获得下一个条目。

如果您在此上花费了30分钟,并且至少没有提出至少一种蛮力方法,那么我也不会雇用您。

在商业世界中,一个笨拙,缓慢且笨拙但能完成工作的解决方案总比没有解决方案有价值,事实上,这几乎可以描述 所有商业软件,优雅,缓慢而笨拙。


1
好吧,我对蝙蝠的第一个评论是“我可以蛮力但是……”。如果真的没有算法解决方案,我会感到很失望
星期一

4
如果我是面试官,那么我不会对暴力破解感到满意。
艾哈迈德·萨利赫

@benjamin han,有算法解决方案。只需保持从右开始交换数字,直到找到结果。之前无需计算所有排列。
dantuch

7
当然有比蛮力,如更好的解决方案ardendertat.com/2012/01/02/...
BrokenGlass

@BrokenGlass绝对是一个更好的解决方案。我只是想出了这个主意,然后您发布了该算法。
2012年

5
function foo(num){
 sortOld = num.toString().split("").sort().join('');
 do{
    num++;
   sortNew = num.toString().split("").sort().join('');
 }while(sortNew!==sortOld);
 return num;
}

我想出了这个解决方案。如有任何疑问,请询问。
Ashikodi 2015年

4

你的想法

我想从找到小于该位数的第一个数字的索引开始(从右边开始)。然后,我将轮换子集中的最后一个数字,以使其成为由相同数字组成的下一个最大数字,但卡住了。

真的很好 您不仅需要考虑最后一位,而且还考虑所有比当前考虑的重要性低的数字。从此之前,我们就拥有一个单调的数字序列,即最右边的数字比其右边的邻居小。看待

1234675
    ^

具有相同数字的下一个较大数字是

1234756

找到的数字交换为最后一个数字-所考虑的数字中的最小数字-其余数字按升序排列。


4

我相当确定您的面试官正试图将您轻轻地推向以下方向:

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);

不一定是最有效或最优雅的解决方案,但它可以按两个周期解决提供的示例,并像他建议的那样一次交换一个数字。


2

取一个数字并将其拆分为数字。因此,如果我们有5位数字,那么我们有5位数字:abcde

现在交换d和e并与原始数字进行比较,如果它更大,则您有答案。

如果不大,请交换e和c。现在比较一下,如果交换d和e较小(请注意递归),则取最小。

继续进行直到找到更大的数字为止。通过递归,它应该可以解决大约9行方案,或者20行c#。


2

这是一个非常有趣的问题。

这是我的Java版本。在我检查其他贡献者的评论之前,请花大约3个小时从模式中完全完成代码。很高兴看到我的想法与其他人完全一样。

O(n)解决方案。老实说,如果时间只有15分钟,并且要求在白板上完成代码,我将使这次面试失败。

以下是我的解决方案的一些有趣之处:

  • 避免任何排序。
  • 完全避免字符串操作
  • 实现O(logN)空间复杂度

我在代码中添加了详细注释,并在每个步骤中添加了BigO。

  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

万一123会是什么答案?实际上日子会把你的代码不会产生输出,同时它shold来到132
Dhaval戴夫

2

@BlueRaja算法的javascript实现。

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;
};

1

下面的解决方案(使用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));
}

@yi_H:输出为。63872为什么呢?
Cratylus 2012年

好..下一个更高的数字?:)那是要求,不是吗?
Karoly Horvath'2

@BlueRaja-Danny Pflughoeft:谢谢您的帮助。我将代码更改如下:先移动最少位的数字(产生更大的数字),然后对其余部分进行排序
Cratylus 2012年

1

如果您使用C ++进行编程,则可以使用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;
}

如果我输入会100怎样?:-)
jweyrich

1

在回答这个问题时,我对蛮力算法一无所知,因此我从另一个角度进行了研究。我决定搜索这个数字可能重新排列的整个可能解决方案的范围,从number_given + 1到可用的最大数字(3位数字为999、4位数字为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

该解决方案的时间复杂度是多少?
Nitish Upreti 2014年

@ Myth17我不确定,因为我从未测试过。如果你想,虽然算起来,看看这个帖子stackoverflow.com/questions/9958299/...
耶利米麦柯迪

1

PHP代码

function NextHigherNumber($num1){
$num = strval($num1);
$max = 0;
for($i=(strlen($num)-2); $i>=0; $i--){
    $numArrayRaw = substr($num, $i);
    $numArray = str_split($numArrayRaw);
    $max = max($numArray);
    if ($numArray[0] < $max){
        sort( $numArray, SORT_NUMERIC );
        array_pop($numArray);
        $numarrstr = implode("",$numArray);
        $rt = substr($num,0,$i) . $max . $numarrstr;
        return $rt;
    }
}
return "-1";
}
echo NextHigherNumber(123);

0

我只用两个数字测试过。他们工作了。作为去年12月退休的IT经理,有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


0

这是我的代码,它是此示例的修改版本

图书馆:

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);
}

0

在给定的n位数字上加9。然后检查它是否在限制范围内(第(n + 1)个数字)。如果是,请检查新编号中的数字是否与原始编号中的数字相同。重复加9,直到两个条件都成立。当数字超出限制时,停止算法。

对于这种方法,我无法提出一个矛盾的测试用例。


1
它可以工作,但是非常慢。这是一种指数时间算法,可以在线性时间内解决。
interjay 2013年

0

另一个使用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

0
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);
        }

    }

0

下面的代码生成数字的所有排列。尽管必须先使用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;
}

0
#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;
}

0

另一个Java实现,可以即开即用,并通过测试完成。该解决方案是使用良好的旧动态编程的O(n)时空。

如果要暴力破解,则有两种暴力破解:

  1. 摆放所有东西,然后再挑高一点:O(n!)

  2. 类似于此实现,但代替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);
    }

}

0

我们需要找到最右边的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's (i.e input is 0) we cannot form another pattern with 
    //the same number of 1's which will increment the input, or if we have leading consecutive
    //ones followed by consecutive 0's up to the maximum bit size of a int
    //we cannot increase the input whilst preserving the original no of 0's and
    //1's 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;
}

0
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");
}

0

这是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));
}

0

我知道这是一个非常老的问题,但是仍然没有在C#中找到简单的代码。这可能对参加面试的人有所帮助。

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;
    }
}

0

使用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);

由于评论很多,因此最好将其复制到文本编辑器中。谢谢!


0

有很多好的答案,但是我没有找到一个不错的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;
}

0
#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;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.