我刚刚搞砸了一次面试,而且我的面试问题几乎毫无进展。

给定一个数,找出下一个与之完全相同的更大的数 作为原始数字的数字集。例如:给定38276返回 38627

我想从找到第一个比个位小的数字的下标开始。然后我将旋转子集中的最后一个数字,这样它是由相同的数字组成的下一个最大的数字,但卡住了。

面试官还建议我试着一次换一个数字,但我搞不懂算法,只能盯着屏幕看20-30分钟。不用说,我想我还得继续找工作。


当前回答

Ruby的解决方案

def next_bigger(num)
  char_array = num.to_s.split('')
  return -1 if char_array.uniq.size == 1

  arr, target_idx, target_char = [], nil, nil
  # get first left-digit less than the right from right side
  (char_array.count - 1).times do |i|
    arr.unshift(char_array[-(i+1)])

    if char_array[-(i+2)] < char_array[-(i+1)]
      target_idx = char_array.count - (i + 2)
      target_char = char_array[-(i+2)]
      arr.unshift(char_array[-(i+2)])
      break
    end
  end
  return -1 unless target_idx

  # first smallest digit larger than target_char to the right
  ((target_char.to_i + 1)..9).to_a.each do |ch|
    if arr.index(ch.to_s)
      flip_char = arr.delete_at(arr.index(ch.to_s))
      # sort the digits to the right of flip_char
      arr.sort!
      # place flip_char to the left of target_char
      arr.unshift(flip_char)
      break
    end
  end

  (char_array[0...target_idx] + arr).join().to_i
end

其他回答

import java.util.Scanner;
public class Big {

    public static void main(String[] args) {


        Scanner sc = new Scanner(System.in);
        System.out.print("Enter the number ");
        String str = sc.next();
        int t=0;

        char[] chars  = str.toCharArray();



        for(int i=str.length()-1,j=str.length()-2;j>=0;j--)
        {


                if((int)chars[i]>(int)chars[j])
                {
                    t = (int)chars[i];
                    chars[i] = chars[j];
                    chars[j]=(char)t;

                    for(int k=j+1;k<str.length()-1;k++)
                    {
                        for(int l=k+1;l<str.length();l++)
                        {
                            if(chars[k]>chars[l])
                            {
                                int m = (int)chars[k];
                                chars[k] = chars[l];
                                chars[l]=(char)m;
                            }
                        }
                    }

                    break;
                }






        }
        System.out.print("The next Big number is: ");

        for(int i=0;i<str.length();i++){
            System.out.print(chars[i]);
        }
        sc.close();
    }


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

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

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

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

下面用一个例子总结一下这个方法:

34722641

A.将数字序列分成两部分,使右边的部分尽可能长,同时保持递减顺序:

34722 641

(如果整个数字是递减的,就没有比这个数字更大的数字了。)

在这一点上,你知道没有从左边开始的更大的数了,因为右边的剩余数字已经尽可能大了。

责任。选择第一个序列的最后一位:

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

你把这个数字分开,这样你就知道没有更大的数字具有相同的左边部分,你把左边部分增加了尽可能小的量,你让剩下的右边部分尽可能小,所以你可以确保这个新数字是用相同的数字集合可以得到的最小的更大的数字。

至少,这里有几个基于字符串的暴力解决方案的例子,你应该能够马上想到:

38276中的数字排序为23678

38627排序的数字列表是23678

蛮力增量,排序和比较

沿着蛮力解决方案将转换为字符串 然后用这些数字强行找出所有可能的数字。

从它们中创建int,把它们放在一个列表中并排序, 获取目标条目之后的下一个条目。

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

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