从给定的数字中查找下一个最高的唯一数字

Posted

技术标签:

【中文标题】从给定的数字中查找下一个最高的唯一数字【英文标题】:Find next highest unique number from the given digits 【发布时间】:2011-12-21 15:12:57 【问题描述】:

给定一组 n 个符号、大小为 k 以及符号集中长度为 k 的非重复字符的组合,只编写一个迭代算法来打印可以生成的下一个最高唯一数。

例如:

Symbols =[1,2,3,4,5]
size = 3;
given combination = 123, result = 124
given combination = 254, result = 312

【问题讨论】:

优秀的面试官可以判断你是否对这些事情有预设的反应。如果您必须解决问题,他们会更喜欢它,因为他们可以看到您解决问题的过程,这比仅仅知道解决方案更重要。 我给出了一个这样的解决方案,采用可用数字的排序双端队列,用可用数字初始化,1.以个位开头,检查是否有更高的数字可用,如果是则替换其他,把这个可用列表中的数字并检查十位数字 2. 如果您发现一个大于当前数字的数字,请替换它,并开始从队列中插入较小的数字。这样可以提高效率吗?有什么缺陷吗? example.. 123 available : 45 check 3 .. 用 4 替换 254 可用:13 check 4 .. 1,3 我可能会使用 TreeSet 而不是队列,因为无论如何您总是从头开始迭代。否则这就是我提出的解决方案。 我会编码和解码一个组合号码。 (每个可能组合的数字)这使得递增变得微不足道。 【参考方案1】:

这是一个伪代码算法:

int n = length(Symbols);
int k = length(A);
// TRACK WHICH LETTERS ARE STILL AVAILABLE
available = sort(Symbols minus A);
// SEARCH BACKWARDS FOR AN ENTRY THAT CAN BE INCREASED
for (int i=k-1; i>=0; --i) 
    // LOOK FOR NEXT SMALLEST AVAILABLE LETTER
    for (int j=0; j<n-k; ++j) 
        if (A[i] < available[j]) 
            break;
        
    
    if (j < n-k) 
        // CHANGE A[i] TO THAT, REMOVE IT FROM AVAILABLE
        int tmp = A[i];
        A[i] = available[j];
        available[j] = tmp;
        // RESET SUBSEQUENT ENTRIES TO SMALLEST AVAILABLE
        for (j=i+1; i<k; ++j) 
            A[j] = available[i+1-j];
        
        return A;
      else 
         // A[i] MUST BE LARGER THAN AVAILABLE, SO APPEND TO END
         available = append(available,A[i]);
     

【讨论】:

我给出了同样的答案! ..面试官说我可以优化一下!!!看我帖子的评论!【参考方案2】:
public class IncrementSybmols 
    public static void main(String[] args) throws Throwable 
        List<Integer> syms = Arrays.asList(1,2,3,4,5);

        test(syms, 3, Arrays.asList(1,2,3), Arrays.asList(1,2,4));
        test(syms, 3, Arrays.asList(2,5,4), Arrays.asList(3,1,2));

        test(syms, 3, Arrays.asList(4,3,5), Arrays.asList(4,5,1));
        test(syms, 3, Arrays.asList(5,4,2), Arrays.asList(5,4,3));
        test(syms, 3, Arrays.asList(5,4,3), null);
    

    private static void test(List<Integer> syms, int n, List<Integer> in, List<Integer> exp) 
        List<Integer> out = increment(syms, n, in);
        System.out.println(in+" -> "+out+": "+( exp==out || exp.equals(out)?"OK":"FAIL"));
    

    private static List<Integer> increment(List<Integer> allSyms, int n, List<Integer> in)
        TreeSet<Integer> availableSym = new TreeSet<Integer>(allSyms);
        availableSym.removeAll(in);

        LinkedList<Integer> current = new LinkedList<Integer>(in);

        // Remove symbols beginning from the tail until a better/greater symbols is available.
        while(!current.isEmpty())
            Integer last = current.removeLast();
            availableSym.add(last);

            // look for greater symbols
            Integer next = availableSym.higher(last);
            if( next != null )
                // if there is a greater symbols, append it
                current.add(next);
                availableSym.remove(next);
                break;
            
        

        // if there no greater symbol, then *shrug* there is no greater number
        if( current.isEmpty() )
            return null;

        // fill up with smallest symbols again
        while(current.size() < n)
            Integer next = availableSym.first();
            availableSym.remove(next);
            current.add(next);
        

        return current;
    

【讨论】:

【参考方案3】:

当您在数字之间迭代(向后)时,您不必每次都检查可用的最低数字,而是可以检查最后一个检查的数字与当前的数字,如果它更少,则在添加时跳到下一个数字当前到可用,如果更多,则检查可用以找到可能的最低(高于当前)并用队列中的最低填充其余部分。

i.e. 254

current = 4      // 4 < 1,3  so no higher available
last_checked = 4 // available = 1, 3, 4
current = 5      // 4 < 5 so no higher available
last_checked = 5 // available = 1, 3, 4, 5
current = 2      // 5 > 2 so search available for lowest possible(higher than 2) = 3
set 3,_,_        // Then just add lowest elements until full: 3,1,2 = 312

这样您只需查看可用符号一次,最多只比较 k 次。

【讨论】:

【参考方案4】:

试试这个方法:

public int nextCombo(int[] symbols, int combo, int size) 
    String nc = "";
    symbols = java.util.Arrays.sort(symbols);
    for (int i = 0; i < size; i++) nc += Integer.toString(symbols[symbols.length - 1]);
    if (Integer.parseInt(nc) == combo) return combo; //provided combo is the largest possible so end the method
    nc = "";
    int newCombo = 0;
    while (newCombo < combo)  //repeat this process until the new combination is greater than the provided one
        for (int i = 0; i < size; i++)  //keep appending numbers from the symbol array onto the new combo until the size limit is reached
            nc += Integer.toString(symbols[(int) Math.floor(Math.random() * size)]);
        
        newCombo = Integer.parseInt(nc);
    
    return newCombo;

【讨论】:

以上是关于从给定的数字中查找下一个最高的唯一数字的主要内容,如果未能解决你的问题,请参考以下文章

使用分治法从给定列表中查找第二小的数字

查找具有给定总和的数字列表的所有组合

在不使用条件语句的情况下查找三个随机生成的数字中的最高、第二高和最低

查找给定数字的下一个较大的字谜

神经网络,用于查找数字序列中的模式

查找向量中的第一个缺失元素