简体   繁体   English

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

[英]Find next highest unique number from the given digits

Given a set of n symbols, a size k, and a combination of length k of non-repeating characters from the symbol set, write only an ITERATIVE algorithm to print the next highest unique number that can be made. 给定一组n个符号,大小k和符号集中非重复字符的长度k的组合,只需编写一个ITERATIVE算法即可打印下一个最高的唯一数字。

Ex: 例如:

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

Here's a pseudocode algorithm to do this: 这是执行此操作的伪代码算法:

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

When you are iterating (backwards) across the digits you do not have to check the lowest available every time, instead you can check the last checked digit versus the current, if it is less, skip to the next digit while adding the current to available, if it is more then check the available to find the lowest(higher than current) possible and fill in the rest with lowest from queue. 在数字上进行向后(向后)迭代时,您不必每次都检查最低的可用数字,而是可以检查最后一个与当前数字相对的数字(如果较小),请跳至下一个数字,同时将当前数字添加到可用数字中。 ,如果更多,请检查可用于查找可能的最低价(高于当前价),然后使用队列中最低的价位填充其余价位。

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

This way you only have to look at the available symbols once, and you are only comparing at most k times. 这样,您只需要查看一次可用的符号,并且最多只能进行k次比较。

Try this method out: 试试这个方法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM