May 23

(IBM DW)코드 트레이닝 Part2. 알고리즘과 성능 - 트랙백

분류: DS/Algorithm 태그: ,, Heart @ 12:11 오전

Trackback : http://dev.heartsavior.net/archives/139/trackback/

IBM developerWorks에서 재밌는 기사를 보아서 회사 일도 얼추 끝냈고 해서 잠깐 시간 내서 풀어봤다.
음… 문제는 상당히 쉽다. 학부 1~2학년 과제 수준인 것 같다.
물론 그냥 풀 때의 얘기이고, 다른 알고리즘 방법을 찾는다던지 하면 더 걸릴 수도 있을 듯…
다른 알고리즘 찾는 건 시간 날 때 해봐야지. 일단 일반적인 알고리즘으로 1~4를 해결했다.

솔직히 얘기하자면, 문제를 읽어보자 마자 일반적인 알고리즘이 생각났고 새로운 알고리즘 찾는 게 귀찮았다.
(그래서 일반적인 알고리즘으로 푼 것이다. ㅜ.ㅜ 그리고 다른 방법이 딱히 생각나지도 않는다. 다른 방법이 있긴 한건가…;;)
음… 이러면 안되는데…

내 풀이 ..

퀴즈 1. Both

    public static ArrayList both(ArrayList xs, ArrayList ys) {
            ArrayList bothList = new ArrayList();
            Object y = null;
            // 먼저 첫 번째 리스트를 몽땅 저장
            bothList.addAll(xs);
            Iterator elems = ys.iterator();
            while( elems.hasNext() ) {
                y = elems.next();
                // 첫 번째 리스트에 값이 없을 경우에만 추가
                if( !xs.contains(y) )
                    bothList.add(y);
            }
            return bothList;
        }

: 코드를 보면 알겠지만 Either()랑 거의 똑같다 -_-;;

퀴즈 2. fastEither

    public static ArrayList fastEither(ArrayList xList, ArrayList yList) {
        ArrayList eitherList = new ArrayList();
        final int xSize = xList.size();
        final int ySize = yList.size();
        Comparable x, y;
        int order, xpos, ypos;
        xpos = ypos = 0;
        while( xpos < xSize && ypos < ySize ) {
            x = (Comparable)xList.get(xpos);
            y = (Comparable)yList.get(ypos);
            order = x.compareTo(y);
            if( order < 0 ) {            // x가 작음
                xpos++;
            } else if( order > 0 ) {    // y가 작음
                ypos++;
            } else {                    // x = y
                eitherList.add(x);
                xpos++;
                ypos++;
            }
        }
        return eitherList;
    }

: 마찬가지로 코드를 보면 알겠지만 fastBoth()랑 거의 똑같다 -_-;;

퀴즈 3. isSubstring

    public static boolean isSubstring(char[] left, char[] right) {
        final int leftCount = left.length;
        final int rightCount = right.length;
        for( int i = 0 ; i < rightCount ; i++ ) {
            if( left[0] == right[i] ) {
                boolean same = true;
                for( int j = 1 ; j < leftCount ; j++ ) {
                    if( left[j] != right[i+j] ) {
                        same = false;
                        break;
                    }
                }
                if( true == same )
                    return true;
            }
        }
        return false;
    }

: 첫 글자 일치하면 2, 3, … , n 번째 글자까지 맞는지 확인

퀴즈 4. match

    public class MatchTest {
        private static final String KIND_OF_BRACKETS_LEFT = "([<{";
        private static final String KIND_OF_BRACKETS_RIGHT = ")]>}";
 
        public static boolean isLeftBrackets(char ch) {
            if( -1 == KIND_OF_BRACKETS_LEFT.indexOf(ch) )
                return false;
 
            return true;
        }
 
        public static boolean isRightBrackets(char ch) {
            if( -1 == KIND_OF_BRACKETS_RIGHT.indexOf(ch) )
                return false;
 
            return true;
        }
 
        public static boolean isBracketMatch(char leftBracket, char rightBracket) {
            int leftBracketIdx = KIND_OF_BRACKETS_LEFT.indexOf(leftBracket);
            int rightBracketIdx = KIND_OF_BRACKETS_RIGHT.indexOf(rightBracket);
 
            if( (-1 == leftBracketIdx) || (-1 == rightBracketIdx) )
                return false;
 
            return (leftBracketIdx == rightBracketIdx);
        }
 
        public static boolean matchUseStack(char[] cs) {
            final int length = cs.length;
            if( 0 == length )
                return false;        // 길이가 0인 경우도 짝이 없다고 가정함
 
            /*
             * ArrayList로 할 수도 있지만 배열 사이즈가 어느 정도 정해져 있기 때문에 이렇게 함
             * cs의 크기가 크다면 ArrayList가 나을 수도 있음(하지만 ArrayList를 사용하면 Object로 저장해야 함)
             *
             * Stack의 길이는 cs의 길이의 반이면 됨, 그 이상 넘어가면 짝이 있을 수 없음.
             */
            int stackLen = length / 2;
 
            char[] stack = new char[stackLen];
 
            int stackIdx = 0;
            for( int i = 0 ; i < length ; i++ ) {
                char ch = cs[i];
 
                if( isLeftBrackets(ch) ) {
                    // Stack에 집어넣음
                    if( stackIdx >= stackLen ) {
                        // Stack이 꽉 찼음. 짝이 없음을 의미
                        return false;
                    }
 
                    stack[stackIdx] = ch;
                    stackIdx++;
 
                } else if( isRightBrackets(ch) ) {
                    // Stack에서 하나를 빼서 비교
                    if( stackIdx >= 0 ) {
                        stackIdx--;
                        char stackCh = stack[stackIdx];
 
                        // 꺼낸 괄호가 짝이 아니면 짝이 아님을 리턴
                        if( !isBracketMatch(stackCh,ch) )
                            return false;
                    } else {
                        // Stack에서 꺼낼 왼쪽 괄호가 없음. 짝이 없음을 의미
                        return false;
                    }
                }
                // 괄호 종류가 아니면 무시
            }
            return true;
        }
 
        public static boolean match(char[] cs) {
            return matchUseStack(cs);
        }
 
        public static void main(String[] args) {
            char[] first = { '(', '[', '<', '{', '}', '>', ']', ')' };
            char[] second = { '(', '[', '<', '{', '>', '}', ']', ')' };
            char[] third = { '(', 'a', 'c', ')', '[', '{', '}', ']' };
 
            System.out.println( match(first) ); // yes
            System.out.println( match(second) ); // no
            System.out.println( match(third) ); // yes
        }
    }

: Stack을 이용해서 left-bracket은 Stack에 쭉 넣고, right-bracket이 나오면 Stack에서 꺼내서 비교하는 알고리즘(이라고 하기도 민망;;)

Leave a Reply