【问题标题】:Given a number, find the next higher number which has the exact same set of digits as the original number给定一个数字,找到与原始数字具有完全相同的数字集的下一个更高的数字
【发布时间】:2012-03-11 05:04:13
【问题描述】:

我刚刚搞砸了一次面试,面试题的进展几乎为零。谁能让我知道该怎么做?我尝试在线搜索但找不到任何东西:

给定一个数字,找到下一个相同的更大数字 一组数字作为原始数字。例如:给定 38276 返回 38627

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

面试官还建议尝试一次交换一个数字,但我无法弄清楚算法,只是盯着屏幕大约 20-30 分钟。不用说,我想我得继续找工作了。

编辑:不管怎样,我被邀请参加下一轮面试

【问题讨论】:

  • 不考虑太多至少一个开始将是蛮力计算数字的所有排列并获取大于输入数字的最小数字
  • 在 C++ 中你可以使用 next_permutation ;-)
  • 仅供参考,这就是我在大约 15 分钟内解决它的方法,几乎​​没有考虑过这个问题:我首先花了 5 分钟编写了一个蛮力算法,该算法刚刚创建了一组数字的所有可能排列,对它们进行排序,并显示它们。我花了 5 分钟查看 那个 数据,直到从列表中出现一个模式(这里的 O(n) 接受的解决方案在经过很短的时间后就变得清晰了),然后我花了 5 分钟编写了 O( n) 算法。
  • 一般来说,当你遇到困难时,想出算法来解决这类问题并不是一个坏方法——对一些小样本使用蛮力来创建大量数据,你可以然后用于更轻松地查看模式。
  • 我还想指出,如果你真的想不出一个有效的方法来做到这一点,什么都不做肯定会导致面试失败(并且在商业世界中,这是错过产品最后期限的好方法)。当你被卡住时,而不是放弃,你应该只是蛮力地强迫它并在顶部发表评论“TODO:重构性能”或类似的东西。如果我正在面试并且有人这样做,我不一定会让他们失望。至少他们想出了一些行之有效的方法,并且认识到那里有更好的东西,即使他们找不到。

标签: algorithm digits


【解决方案1】:

您可以像这样在O(n)(其中n 是位数)中执行此操作:

从右侧开始,您会找到第一对数字,使得左侧数字小于右侧数字。让我们用“digit-x”来指代左边的数字。在 digit-x 的右侧找到大于 digit-x 的最小数,并将其放在 digit-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的方式,它必须存在,见上文),@987654335 @ 按升序排序。

假设有一些数字(使用相同的数字)N',例如 AxB < N' < AyCN' 必须以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,其中BD 具有相同的数字。但是,B 是按降序排序的,因此 is 没有比它大的数字的字符串。因此我们不能有B < D。按照相同的步骤,我们看到如果z = y,我们就不能拥有D < C

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

【讨论】:

  • 不错的解决方案!有一个问题。说“大于 x 的最小数字”是 y。我们可以交换 x 和 y,然后反转 x.index+1 -> end 吗?
  • 数字 99999 会发生什么?
  • @Sterex,不只是 99999;任何数字已经按降序完全排序的数字都是最大值(例如,98765 也没有解决方案)。这很容易以编程方式检测,因为算法的第 1 步将失败(没有一对连续的数字,例如“左数小于右数”)。
  • @TMN: 9 大于 8,因此您将 9 移到 8 的左侧:9 832,然后将所有内容排序到 9 的右侧:9238
  • @Kent 要让您的解决方案发挥作用,您必须将找到大于 4 的最小数字改为右侧改为找到右侧大于4的最小数字。否则,例如,1234567849876 55 4321 将导致 1234567851234 54 6789(而不是 1234567851234 45 6789)。挑剔:-)
【解决方案2】:

一个几乎相同的问题出现为 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

您将数字分开,这样您就知道没有更大的数字具有相同的左侧部分,您将左侧部分增加了尽可能少的数量,并且您使剩余的右侧部分尽可能小,因此您可以确定这个新数字是可以用相同的数字集合组成的最小的较大数字。

【讨论】:

  • 那里的错字:我认为“-> 34721 621”应该是“-> 34724 621”?
  • @bjnord 很好。固定的。不知道我是如何做到的 - 在后续行中是正确的。
  • +1 最佳答案在这里。直观且快速。 (这也是我在纸上解决这个问题时想到的那个;))
  • @Neel - 在步骤 C 中,我们要排序的数字按降序排列,除了我们在步骤 B 中交换的数字。要对它们进行排序,我们实际上只需要反转它们并得到将数字交换到正确的位置。这就是 BlueRaja 所描述的。
  • @Dhavaldave 有什么问题?在步骤 A 你得到“12”和“3”。在步骤 B 中,您得到“13”和“2”。在步骤 C 中没有任何变化。在步骤 D 你得到“132”。您不会得到答案的唯一情况是数字已经是可能的最大值,例如“321”。在这种情况下,步骤 A 会为您提供“”和“321”,并且您不能继续使用拆分左侧的空序列。
【解决方案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++ 中,您可以进行如下排列: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 等输入?谢谢。
  • 我现在通过将 'list() 添加到 iis=...' 来为 python 3 修复它。案例 111 和 531 没有解决方案,但我的实现返回 111 和 531。您可以通过更改 i == 0 行将其更改为您发现更好的例外。
  • 谢谢。我实际上是在另一个方向循环,所以我被 i == 0 弄糊涂了,而在我的情况下,它应该是 i == len(iis)
【解决方案4】:

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

排序后的38276中的数字列表为23678

排序后的38627中的数字列表为23678

蛮力递增、排序和比较

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

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

如果你在这上面花了 30 分钟,但至少没有想出一个蛮力的方法,我也不会雇用你。

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

【讨论】:

  • 嗯,我的第一条评论是“我可以蛮力但是......”。如果真的没有算法解决方案,我有点失望
  • 如果我是面试官,我不会对蛮力的方法这么满意。
  • @benjamin han,有算法解决方案。只需从右开始不断交换数字,直到找到结果。之前不需要计算所有的置换。
  • 肯定有比蛮力更好的解决方案,例如ardendertat.com/2012/01/02/…
  • @BrokenGlass 绝对是一个更好的解决方案。我刚刚提出这个想法,然后你发布了算法。
【解决方案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】:

      取一个数字并将其拆分为数字。所以如果我们有一个 5 位数字,我们就有 5 位数字:abcde

      现在把 d 和 e 交换一下,和原来的数字比较,如果更大,你就有答案了。

      如果它不是更大,交换 e 和 c。现在比较一下,如果它更小,再次交换 d 和 e(注意递归),取最小。

      继续进行,直到找到更大的数字。通过递归,它应该是大约 9 行方案,或 20 行 c#。

      【讨论】:

        【解决方案9】:

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

        这是我的 java 版本。在我检查其他贡献者的 cmets 之前,我花了大约 3 个小时从弄清楚模式到完全完成代码。很高兴看到我的想法和其他人完全一样。

        O(n) 解决方案。老实说,如果时间只有 15 分钟,并且需要在白板上完成完整的代码,我将无法通过这次面试。

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

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

        我在代码中添加了详细注释,并在每个步骤中添加了大 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
        

        【讨论】:

        • 万一 123 会是什么答案?实际上,您的代码在 132 出现时不会生成输出
        【解决方案10】:

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

        【讨论】:

          【解决方案11】:

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

          【讨论】:

            【解决方案12】:

            解决方案(Java 中)可能如下(我相信这里的朋友可以找到更好的解决方案):
            从字符串末尾开始交换数字,直到获得更大的数字。
            IE。首先开始向上移动较低的数字。然后是下一个更高的数字,以此类推,直到您达到下一个更高的数字。
            然后对其余的进行排序。 在您的示例中,您将得到:

            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。为什么,应该是什么?
            • 好吧.. 下一个更高的数字? :) 那是要求,不是吗?
            • @BlueRaja - Danny Pflughoeft:感谢您的帮助。我将代码更改如下:将最小的数字提前(产生更高的数字)并对其余的进行排序
            【解决方案13】:

            如果你使用 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会发生什么? :-)
            【解决方案14】:

            我在回答这个问题时对蛮力算法一无所知,所以我从另一个角度接近它。我决定搜索这个数字可能被重新排列的所有可能的解决方案,从 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
            

            【讨论】:

            【解决方案15】:

            我只用两个数字对此进行了测试。他们工作了。 作为 IT 经理 8 年直到去年 12 月退休,我关心三件事: 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
            

            【讨论】:

              【解决方案16】:

              有关如何执行此操作的精彩文章,请参阅 Knuth 的“The Art of Computer Programming: Generating all Permutations”(.ps.gz) 中的“算法 L”。

              【讨论】:

                【解决方案17】:

                这是我的代码,是this example的修改版

                图书馆:

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

                【讨论】:

                  【解决方案18】:

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

                  我无法为这种方法想出一个矛盾的测试用例。

                  【讨论】:

                  • 它可以工作,但速度极慢。这是一种指数时间算法,可以在线性时间内解决。
                  【解决方案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】:

                          又一个 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);
                              }
                          
                          }
                          

                          【讨论】:

                            【解决方案24】:

                            我们需要找到最右边的位 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;
                            }
                            

                            【讨论】:

                              【解决方案25】:
                              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");
                              }
                              

                              【讨论】:

                                【解决方案26】:

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

                                【讨论】:

                                  【解决方案27】:

                                  我知道这是一个非常古老的问题,但我仍然没有在 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;
                                      }
                                  }
                                  

                                  【讨论】:

                                  • 我检查了您的代码并收到了错误的结果,例如,如果我们有数字 1234126,我们预计会收到 1234162,但我们收到的是 6432211。
                                  【解决方案28】:

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

                                  由于 cmets 很多,所以最好将其复制到文本编辑器中。 谢谢!

                                  【讨论】:

                                    【解决方案29】:

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

                                    【讨论】:

                                      【解决方案30】:
                                      #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;
                                      }
                                      

                                      【讨论】:

                                        猜你喜欢
                                        • 1970-01-01
                                        • 2022-11-10
                                        • 1970-01-01
                                        • 2023-03-15
                                        • 1970-01-01
                                        • 1970-01-01
                                        • 1970-01-01
                                        • 2012-08-26
                                        • 1970-01-01
                                        相关资源
                                        最近更新 更多