Advanced optimization for algorithms and data structure in programming.

Continueing with  数据结构和算法&刷题题记 but should be writen in English. This is an article for optimizing process on the algorithm compare to the previous.

DFA: The fixed format input can be resolved by DFA(deterministic finite automaton). The No.65 Valid Number is a classic example, so do as the complier. The essence is tranfering the status to next definited position that present the next action. If matched, then take action otherwise stop and quit from the process.

private int[][] DFAtable = new int[][]{
// 43.5e34
// /+-/0-9/./Ee/end { 0, 1, 2, 3,-1}//0 begin ,{-1,-1, 2,-1,-1}//1 +- ,{ 8,-1, 2, 3, 5}//2 number ,{-1,-1, 4,-1,-1}//3 . ,{ 8,-1, 4,-1, 5}//4 number ,{-1,-1, 6,-1,-1}//5 Ee ,{ 8, 7, 6,-1,-1}//6 number ,{ 8,-1, 6,-1,-1}//7 +- ,{ 8,-1,-1,-1,-1}//8 end };

 

The benefits is that the DFA is more clear and apparent than the previous method due to the table directs the whole process. The weekness is the table may be difficult to understand.

Recursion:

Mostly, the recursion process would be much fast and cost less. But consider the each invoking stack costs at least 4KB by memory. If the input is too large to accomandate the whole stacks, the program will throw error as out of memory. To reduce the memory occupation, reassemble the call stacks will provide more space for calculation. The No.772 is well to demonstrate the process. Apparently, each resursion could be expanded as stack call process. And the weakness comes as slower speed.

    public int calculateByStack() {
        //store the variables
        Stack<Integer> numStack = new Stack<Integer>();
        Stack<Character> oprandStack = new Stack<Character>();
        
        //sum is the total amount.
        //prev is the previous number that ready for operation.
        //num is the current number that has made out by char just recent.
        int sum=0, prev=0, current=0;
        char c = 0, prevOprand = '+';
        while(!isEmpty()) {
            c = nextChar();
            
            if (Character.isDigit(c)) {
                current = current*10 + c - '0';
            }else if (c=='(') {
                //store the data into stack.
                numStack.push(sum);
                numStack.push(prev);
                numStack.push(current);
                oprandStack.push(c);
                oprandStack.push(prevOprand);

                //initial the variables for new cycle.
                sum=prev=current=0;
                c = 0;prevOprand = '+';
                //this is the old solution under the recursion.
//                num = calculate(s);
            }else if (Symbols[c]) {//match calculation symbol 
                //calculate
                switch(prevOprand) {
                case '+':
                    sum+=prev;prev=current;break;
                case '-':
                    sum+=prev;prev=-current;break;
                case '*':
                    prev*=current;break;
                case '/':
                    prev=prev==0?0:(prev/current);break;
                }
                if (c==')') {
                    //recover variables from the stack for the old cycle.
                    current=sum+=prev;
                    
                    numStack.pop();
                    prev=numStack.pop();
                    sum=numStack.pop();

                    prevOprand=oprandStack.pop();
                    c=oprandStack.pop();
                    continue;
                }
                //set oprand for next cycle.
                prevOprand=c;current=0;
            }
        }
        //final. because the prev has set to compact the positive and negative value. so just plus.
        return sum+prev;
    }
    
    public int calculateByRecursion() {
        //sum is the total amount.
        //prev is the previous number that ready for operation.
        //num is the current number that has made out by char just recent.
        int sum=0, prev=0, current=0;
        char c = 0, prevOprand = '+';
        while(!isEmpty()) {
            c = nextChar();
            
            if (Character.isDigit(c)) {
                current = current*10 + c - '0';
            }else if (c=='(') {
                current = calculateByRecursion();
            }else if (Symbols[c]) {//match calculation symbol 
                //calculate
                switch(prevOprand) {
                case '+':
                    sum+=prev;prev=current;break;
                case '-':
                    sum+=prev;prev=-current;break;
                case '*':
                    prev*=current;break;
                case '/':
                    prev=prev==0?0:(prev/current);break;
                }
                if (c==')') {break;}
                //set oprand for next cycle.
                prevOprand=c;current=0;
            }
        }
        //final. because the prev has set to compact the positive and negative value. so just plus.
        return sum+prev;
    }

 

Retreive:

For some question regarding to process array in O(n) time cost, the better way to avoid O(n*n) is to retreive the array by two direction that is from the begain to the end and from the end to the begain. The variables which generated in the process, could be used as reduce the time complexisibility.

Enumerate:

To list all possible combinations for a listed array, cut the slice into left and right piece than merge two part together when they are returned.

 

posted on 2021-01-06 15:42  過眼云煙  阅读(76)  评论(0)    收藏  举报

导航