혹시 TreeMap TreeSet에서 element가 primitive일때 reverseOrder로 간단히 하려면.

TreeMap<Integer,Integer> tm = new TreeMap<>(Collections.reverseOrder());

 

  public static int[] mergeSortedArrays(int[] arr1, int[] arr2) {
        int[] result = new int[arr1.length + arr2.length];
        int i = 0, j = 0, k = 0;

        while (i < arr1.length && j < arr2.length) {
            if (arr1[i] < arr2[j]) {
                result[k++] = arr1[i++];
            } else {
                result[k++] = arr2[j++];
            }
        }

        while (i < arr1.length) {
            result[k++] = arr1[i++];
        }

        while (j < arr2.length) {
            result[k++] = arr2[j++];
        }

        return result;
    }
}
Posted by yongary
,

dynamic 프로그래밍은  로직만으로 계산이 어려워서
컴퓨터에게 반복적으로 계산도 시키고, 캐싱도 시키면서  캐싱된걸 이용해 나가면서 답을 구하는 방법이다.

 

문제 예제 1 . 숫자 n 만 주고, 가능한 모든 BST 개수 구하기.

   - BST(binary search tree: child는 max 2개이고, left child는 작은값, right child는 큰값) 

Posted by yongary
,

Object oriented 디자인 패턴


객체 지향 디자인 패턴(Object-Oriented Design Patterns)은 소프트웨어 개발에서 반복적으로 발생하는 문제들을 해결하기 위해 공통된 설계 방법을 제공하는 패턴들의 집합입니다. 이러한 패턴들은 객체 지향 프로그래밍에서 유용하게 사용될 수 있으며, 코드의 재사용성, 유지보수성, 확장성 등을 향상시킬 수 있습니다. 여기서는 몇 가지 대표적인 객체 지향 디자인 패턴에 대해 설명하겠습니다.

Singleton Pattern (싱글턴 패턴): 이 패턴은 오직 하나의 인스턴스만 생성하고, 그 인스턴스에 접근할 수 있는 전역적인 접근점을 제공합니다. 주로 리소스를 공유하거나 설정 정보와 같은 단일 객체를 공유해야 할 때 사용됩니다.

Factory Pattern (팩토리 패턴): 객체의 생성을 처리하는 패턴으로, 객체를 생성하기 위한 인터페이스를 정의하고, 서브 클래스에서 어떤 클래스의 인스턴스를 생성할지를 결정합니다. 이를 통해 객체 생성 코드를 클라이언트로부터 분리시킬 수 있습니다.

Observer Pattern (옵저버 패턴): 이벤트 발생 시 관찰자(옵저버)들에게 자동으로 알림을 보내는 패턴입니다. 주로 한 객체의 상태 변화에 따라 다른 객체들이 업데이트되어야 하는 상황에서 사용됩니다.

Strategy Pattern (전략 패턴): 알고리즘을 정의하고, 이를 사용하는 클라이언트와 분리시키는 패턴입니다. 각각의 알고리즘을 캡슐화하고, 런타임 시에 알고리즘을 변경할 수 있습니다.

Decorator Pattern (데코레이터 패턴): 객체의 기능을 동적으로 확장하기 위해 사용되는 패턴입니다. 기존 객체를 감싸는 데코레이터 클래스를 생성하여, 새로운 동작을 추가하거나 변경된 동작을 제공합니다.

Proxy Pattern (프록시 패턴): 실제 객체에 대한 대리자(Proxy)를 제공하는 패턴으로, 클라이언트와 실제 객체 사이에 중간 계층을 두어 추가적인 기능을 제공하거나 접근을 제어할 수 있습니다.

Template Method Pattern (템플릿 메서드 패턴): 알고리즘의 구조

 

Posted by yongary
,

점을 V(Vertex)
edge를 E라고 하면..

 

처음에 V를 쭉 더해놓고

다음부터는 BFS (혹은 DFS도 가능)

 

따라서 complexity는 O (V + E) 

 

https://www.geeksforgeeks.org/detect-cycle-undirected-graph/

cycle find 코드예제:

더보기
import java.util.*;

class Graph {
    private int V;
    private LinkedList<Integer>[] adj;

    Graph(int v) {
        V = v;
        adj = new LinkedList[v];
        for (int i = 0; i < v; ++i)
            adj[i] = new LinkedList();
    }

    void addEdge(int v, int w) {
        adj[v].add(w);
        adj[w].add(v);
    }

    boolean isCyclicUtil(int v, boolean[] visited, int parent) {
        visited[v] = true;
        for (Integer i : adj[v]) {
            if (!visited[i]) {
                if (isCyclicUtil(i, visited, v))
                    return true;
            } else if (i != parent) {
                return true;
            }
        }
        return false;
    }

    boolean isCyclic() {
        boolean[] visited = new boolean[V];
        for (int i = 0; i < V; ++i)
            if (!visited[i])
                if (isCyclicUtil(i, visited, -1))
                    return true;

        return false;
    }
}

public class CycleDetectionExample {
    public static void main(String[] args) {
        Graph g1 = new Graph(5);
        g1.addEdge(1, 0);
        g1.addEdge(0, 2);
        g1.addEdge(2, 1);
        g1.addEdge(0, 3);
        g1.addEdge(3, 4);
        
        if (g1.isCyclic())
            System.out.println("Graph contains cycle");
        else
            System.out.println("Graph doesn't contain cycle");
    }
}

코드예제임.

 

Digikstra 알고리듬.  근접한 distance 부터 하나씩 추가하는 알고리듬.

더보기
import java.util.*;

class Node implements Comparable<Node> {
    int id;
    int distance;
    
    public Node(int id, int distance) {
        this.id = id;
        this.distance = distance;
    }
    
    @Override
    public int compareTo(Node other) {
        return Integer.compare(this.distance, other.distance);
    }
}

public class DijkstraAlgorithmWithClass {
    public static void dijkstra(int[][] graph, int start) {
        int n = graph.length;
        int[] distance = new int[n];
        Arrays.fill(distance, Integer.MAX_VALUE);
        distance[start] = 0;
        
        PriorityQueue<Node> pq = new PriorityQueue<>();
        pq.offer(new Node(start, 0));
        
        while (!pq.isEmpty()) {
            Node curr = pq.poll();
            int node = curr.id;
            int dist = curr.distance;
            
            if (dist > distance[node]) continue;
            
            for (int neighbor = 0; neighbor < n; neighbor++) {
                int weight = graph[node][neighbor];
                if (weight > 0 && distance[node] + weight < distance[neighbor]) {
                    distance[neighbor] = distance[node] + weight;
                    pq.offer(new Node(neighbor, distance[neighbor]));
                }
            }
        }
        
        // 출력: 각 노드까지의 최단 경로 길이
        System.out.println("Node\tDistance");
        for (int i = 0; i < n; i++) {
            System.out.println(i + "\t" + distance[i]);
        }
    }
    
    public static void main(String[] args) {
        int[][] graph = {
            {0, 4, 0, 0, 0, 0, 0, 8, 0},
            {4, 0, 8, 0, 0, 0, 0, 11, 0},
            // 나머지 그래프 데이터도 입력
        };
        
        dijkstra(graph, 0);
    }
}
Posted by yongary
,

DFS with Stack

algorithm & type 2019. 11. 14. 21:48

BinaryTree를 DFS(depth first search)하기에는 recursion이 간편하다.

하지만 recursion 없이 stack을 이용하는 방법도 있는데, java코드로 표현하면 다음과 같다.

 

 

static void printDFS(Node node) {

        Stack<Node> stack = new Stack<>();

        Node temp = node;
        while (temp != null || !stack.isEmpty()) {

            //(THIS + Left)푸쉬 => left,this,right 출력.
            while (temp != null) {
                //this push
                stack.push(temp);
                //left traverse
                temp = temp.left;
            }

            //start print
            temp = stack.pop();
            print(temp); /////////////////////////////////////

            //right point : goto TOP
            temp = temp.right;
        }
    }
Posted by yongary
,

트라이(Trie)와 패트리샤 트리(Patricia Tree) 는 동일한 것이다. (라고 생각한다)

알파벳으로, 단어 검색을 가장 빠르게 하는 구조체로 보면 되는데,

이더리움에서는 이를 변형해서 머클패트리샤 트리를 사용하고 있다,



https://okky.kr/article/464145   여기서는 Patricia Tree라고 부르고 있다.

Posted by yongary
,

일반적으로 recursion(재귀함수)가 stack를 많이 사용하므로, 

tail recursion을 통해 stack을 적게 사용하는 방법이 좋다. 


간단한 factorial을 예로 든다면.. REF


int Factorial(int n)

{

return FactorialTail(n, 1);

}

int FactorialTail(int n, int acc)    // acc : accumulator의 약자

{

if (n == 1) return acc;

return FactorialTail(n - 1, acc * n);    //  일반 재귀에서의 n * Factorial(n-1)와 달리 반환값에서 추가 연산을 필요로 하지 않음

}




출처: http://bozeury.tistory.com/entry/꼬리-재귀-최적화Tail-Recursion [따..딱히 공부하려고 포스팅하는 건 아니니까..!]



하지만 java에서는 아직 tail recursion Optimization이 지원되지 않는다.

이유는 security등 각종 jdk코드에서 stack을 count한다던지,

 하는 이유때문이라고 하는데

자세한 내용은 여기: REF

Posted by yongary
,

Q 1개를 main으로 하고, 임시 Q 하나를 더 이용해서

stack을 구현. 항상 Q를 다 비우고 꺼꾸로 즉(stack pop 대비순서)로 넣어 놓음.

REF

 

Queue<Integer> q = new LinkedList<Integer>();
Queue<Integer> tmp = new LinkedList<Integer>();


public void push(int d) {
    if (q.size() == 0) {
        q.add(d);
    }else {
        //deque q->tmp
        while (q.size() > 0) {
            tmp.add( q.poll() );
        }

        q.add(d);

        //tmp->q
        while (tmp.size() > 0 ){
            q.add(tmp.poll());
        }

    }
}

public Integer pop(){
    return q.poll();   //poll returns null,  while remove throws exception.
}

 

Posted by yongary
,

<Self-Balanced Tree>

B-Tree:      2개 이상의 child를 가짐..    


2-3 B-Tree   (I think - 2 max, 3 Node) 

        • Every non-leaf node has either 2 or 3 children.
        • All leaves are at the same depth.
        • Information (keys and associated data) is stored only at leaves

        • 부모는 leftMax, middleMax를 저장. (left children's Max, middle children's Max)

        • non-leaf nodes have 2 or 3 children (never 1 )

        • Insert Operations: (value k)
          (2가지 예외)
          - T is empty일 때, 싱글 node with k 생성. 
          - T is 1 node(m) 일 때 : (1 parent, 2 child node로)
                                       => 1.node(n)k포함 생성,  
                                            2.new 내부node (with n,m are child node) 생성
                                             + leftMax,middleMax 세팅.
          (general)
          - insert(T,k) 



ㅁ 2-3-4 Tree : 3개의 data와 4개의 child node를 가질 수 있다. 



<Self-Balanced Binary Tree>

Red-Black Tree: Ref1 ,  

root는 블랙노드

레드노드(temp노드)가 항상 블랙child를 가짐.
삽입시에 레드노드를 삽입하는데, 레드-레드 될 경우 회전으로 해결.


특징: 최장거리 노드도 최단거리의 2배가 이하임. 


AVL Tree:  Refwiki - Height balanced 이진트리 - 각 two child간의 depth가 1 밖에 차이가 안남.
      - depth가 좋으 므로 Red-Black Tree보다 탐색속도가 좋음.

- 특징: 4가지 회전 방식이 존재함 (할아버지 노드까지만 보면 됨)

   LL/RR은 한번만 회전.  LR/RL은 2번 회전. 


Splay Tree  

         - self balanced이면서 속도도 빠름.  이 역시 위 둘과 같이 회전으로 balancing. 

         - 최근 access한 값을 다시 access 할 수 있도록 배치.

  - cache나 gc에 자주 쓰임.

  - zig (parent  root, x is child) , zig-zig (p!=root, p,x 같은 방향), zig-zag (p!=root p,x다른 방향) case 존재.   

 

         

      [기본 회전 알고리듬] Ref

  Root Pv C A B

Pivot = Root.OS (O=Opposite side) Pivot설정. Root.OS = Pivot.RS (R= Rotate side) Pivot.RS를 1.detach Pivot.RS = Root Pivot.RS를 2.Set Root = Pivot Root설정.

   
회전시 left,right가 계속 바뀌므로 java reflection을 쓰면 좋을 것 같네요.
   left, right child를 이름으로  가져오게...  reflection REF

Class aClass = MyObject.class Field field = aClass.getField("someField"); //for node : MyObject node = new MyObject(); Object value = field.get(node); field.set(node, value);



<other tree>

Cartesian Tree ref1txt

 - Heap Tree와 비슷하게 min(or max)값이 제일 위에 있으나, complete tree가 아님.

 - 한번 구성하면 끝날 듯( self balanced가 아님)



KD Tree : k dimensional Tree이다. left-child에 tree하나, right-child에 tree하나 가 관리되는데..
                 recurive하게 여러개의 tree가 계속 관리될 수 있다. 



Huffman Tree: 압축알고리듬 허프만 코드- (확률빈도가 높은 char을 짧은 bit로 관리하는 코드 방식. )
                         를 생성할때 사용하는 binary Tree이다. 

                          왼쪽이 0, 오른쪽이 1 간단하다. 빈도수가 낮은것부터 밑에서 tree를 만든다. 





Heap Tree:  complete binary tree (즉  포화트리에서 마지막 자식은 왼쪽노드부터 채움)

  - heap Tree Java 알고리듬: 

k 의 parent는  k/2;    k의 2자식은  2k 와 2k + 1.  (array로 구현하고 첫자리를 비움. array size는 2^(h+1) 이 되겠죠.)


  최상위 root에는 최소값(Min Heap)이나 최대값(Max Heap)을 관리.

  - complete binary tree는 배열로 관리 가능함.  h로 관리되겠죠. 2^(h+1) -1 개가 max 노드개수임.  

  -Priority Queue 가 Heap으로 구현됨. (단, 이 때는 중복 허용)


  

insert: 일단 마지막 leaf에 넣고.. 자리바꾸기. 

  removeMax:  최상위 삭제하고, 마지막 leaft를 최상위로 배치.. (그 후 자리바꾸기)

  




Posted by yongary
,

 

http://bigocheatsheet.com/  참고

 

 

Merge sort(합병 소트):  O(nlogn)  단점 O(n)스페이스 필요.  Ref-Site

  - 반씩 분할하는 divide & conquer 소트의 일종.

  -  merge_sort (int[] arr, int low, int high) {

            int mid=0;

    if (low < high) {

        mid = (low+high) / 2;

        merge_sort(arr, low, mid);

        merge_sort(arr, mid+1, high);

        

        merge(arr, low, mid, high); // 이 안에서 스페이스 필요. 

    }

     }

  - qSort는 최악에 O(n^2)이지만 실제로는 평균적으로는 qSort가 20%정도 빠르다고 함.

     => qSort 최악의 경우:  pivot을 정할때.. pivot이 최대값이면..  글케 됨.

 

 

Radix sort(̧기수 정렬) :  Ref-Site

  - O(pN) 이며, 2^20(백만개)정도의 숫자를 소팅할때 16진수로 한다고 치면 4자리 수이므로
    4번 * N  정도로 할 수 있어  일반 정렬 O(n logn) =  O(n * 20) 보다 훨씬 빠른 경우가 발생한다.

 

 

 

Insertion Sort(삽입 정렬):  Ref-Site

 - O(N^2) 이지만 구현이 매우 간단하고,  길이가 짤을 때 속도가 좋고 안정적이라는 장점이 있다. 

 

c코드-참고 

void insertion_sort (int *data, int n ) { 
	int i, j, remember; 
    for ( i = 1; i < n; i++ ) { 
    	j=i; 
        remember = data[i]; 
        while ( --j >= 0 && data[j] > remember) 
        	data[j+1] = data[j]; //쭉 copy
            
        data[j+1] = remember; 
     }
 }

 

참고: 자바에서는 리스트의 기본 정렬 방식으로 

1) Merge Sort를 사용하거나 

2) tuned depending on the datatypes  Quick Sort를 사용 

+ 개체수가 7개 이하일 때 Insertion Sort 방식을 사용한다.

 

==============Data Structure=================

 

 

Heap:  complete binary tree (즉  포화트리에서 마지막 자식은 왼쪽노드부터 채움)

  최상위 root에는 최소값(Min Heap)이나 최대값(Max Heap)을 관리.

  - complete binary tree는 배열로 관리 가능함.  h로 관리되겠죠. 2^(h+1) -1 개가 max 노드개수임.

 

  -Priority Queue 가 Heap으로 구현됨.

  -median을 구하기에 가장 최적의 자료구조는

  바로
  Min Heap과 Max Heap을 동시에 하나씩 관리하는 것이다.

 

  예를 들어 100까지의 숫자가 있다면  Max Heap으로 50까지 관리하고,  Min Heap을 51부터 관리하면 
  median이 50 or 51 or 50.5 로 바로 구할 수 있다. 

 

 

Trie : REF2  Ref-Site   

    text 추천에 가장 많이 사용되는 변형된 Tree 로서, 마지막 노드에서만 숫자(접근빈도)를 관리한다.

    - 일반적으로 Root에는 데이타를 관리하지 않으며, mutliNary tree이다.
    - 마지막에 숫자를 관리하지 않아도 서치에는 유용하다. O(L)탐색, 생성은 O(M*L),  M은 단어수, L은 가장 긴 단어길이.

    

 

참고:

HashTable : O(1+N/B)  (B=bucket)

 

Posted by yongary
,

<Tree traverse>

java에서 binary tree는 간단히 node class로 구현이 된다.

그 후, traverse에는 2가지 방식이 있는데..

 

 

DFS: Depth First Search - 깊이 부터 서치하는 일반적인 방식.

이렇게 node로 구성된 BinaryTree 를 DFS로 traverse하는 방법에는 2가지가 있는데 

 

1. recursive   (좀 안좋은: 참고 )

       출력은: printInOrder(node) {
                        if (node!=null) {

                            printInOrder(node.left);

                            System.out.println(node.value);

                            printInOrder(node.right);
                        }      

 

2. loop 이용..    loop를 이용한 방법은 다음과 같다.  myREF  REF

 

    주로 stack이용.

 

BFS: Breadth First Search - 같은 depth에 있는 형제들 먼저 출력. (아래코드 참조) -Queue이용.

          q.add(root); 
          while (q.size() > 0) {
                node = q.poll();
                print ( node.value );
                if (node.left != null) q.add( node.left);
                if (node.right !=null) q.add (node. right);
           }

 

 

<Direct Graph Traverse>

 

Dijkstra :  Vertex(node)---edge--->  w 로 갈 때 각 Edge마다 Weight가 있는 경우, 적합.

 log(n^2)으로 vertex를 늘여가면서 가까운 Destination으로의 path를 찾아나간다.

핵심공식: distance[w] = min(distance[w], distance[u] + weight[u][w])

 

 

            (아래 표 참조 1에서 출발:)

           w    S               D(2)  D(3)  D(4)  D(5)

           1   S{1}            10    무한    30    100

           2   S{1,2}         10    60      30    100

 

   1에서 가까운 w를 하나씩 추가하면서 진행해 나가므로,  가까운 Vertex관리가 필요한데,

   A. (Linked)adjacent List 로 관리하거나

   B.  priority Queue로 관리할 수 있다.    (모든 Vertex에서 다해도 되지만, S 에 들어가는 거 위주로 해도 된다.)

 

 

 

BFS: tree에서 처럼 weight없이 탐색한다. 탐색방식은 Dijkstra와 근본적으로 같다.

 

 

 

<MST:min Spanning Tree>   REF

 

 

Prim 알고리듬:  O(n^2) => 보통 점만 주어질 땐,  link가 많으므로 이럴때 적합. 

  - 노드 하나를 기준으로  그 외부와 연결되는 가장 min 값을 연결한다.

  -  연결된 Set  과   그 외부 Set(외부를 전체 Set으로 보고) 또  가장 min 값을 연결한다.

   (구현이 간단함)


  내가 구현한 예제: disjointSet 이용.

더보기

 

int dist(int[] p1, int[] p2) {
        return Math.abs(p1[0] - p2[0]) + Math.abs(p1[1] - p2[1]);
    }

    class Node {
        int id; //1~5
        int dist;
        int pid1;
        int pid2;


        public Node(int pid1, int pid2,int id, int dist) {
            this.pid1 = pid1;
            this.pid2 = pid2;
            this.id = id;
            this.dist = dist;
        }
    }

    /** MAIN */
    public int minCostConnectPoints(int[][] points) {

        if (points.length <= 1 )  return 0;
        //4point case: 3*2 = 6개? (n-1!)

        int N = points.length;
        //20개 중 작은값 4개를 뽑아서 더하면 될듯. (단 이미연결된거 방지 체크)
        //int dists[] = new int[ N * (N-1)];

        PriorityQueue<Node> pq = new PriorityQueue<>(new Comparator<Node>() {
            @Override
            public int compare(Node n1, Node n2) {
                return n1.dist - n2.dist;
            }
        }
        );

        //10개 노드: 4 + 3+ 2+ 1
        int id = 0;
        for (int i = 0; i < N-1; i++) {
            for (int j = i+1; j < N; j++) {
                Node node = new Node( i, j, id++, dist(points[i], points[j]));
                pq.add(node);
            }
        }
        System.out.println( "Total NODE: :" + id);


        //필요 node는  (n-1)! -1 ///////////////////////
        int k = N - 1;


        int totDist = 0;

//        HashSet<Integer> hs = new HashSet<>();
        DjSet djSet = new DjSet(N);

        while (pq.size() > 0) {
            // while (k > 0) {
            Node node = pq.poll();
            System.out.println("node poll:" + k);

            //TODO check.
            if (!djSet.isConnected(node.pid1, node.pid2)) {

                //add node.pid1, node.pid2
                djSet.union(node.pid1, node.pid2);

                totDist += node.dist;
                k--;
            }
            //DjSet 도입이전 코드:  섬이 2개 생기면 이미 추가되어서 오류가 생김.
//            if ( !hs.contains(node.pid1) || !hs.contains(node.pid2)  ) {
//                //System.out.println(node.dist + "," + node.pid1 + "," + node.pid2 + ",");
//                hs.add(node.pid1);
//                hs.add(node.pid2);
//
//                totDist += node.dist;
//                k--;
//            }
        }

        return totDist;
    }

 


   구현에 DisjointSet(서로소 집합)과 union 이 필요할 것 같아서 링크 REF

 /////////// DjSet: find, union, isConnected ////////////////////////////
    class DjSet {

        int[] parent;
        int[] size;

        public DjSet(int n) {
            parent = new int[n];
            size = new int[n];
            for (int i = 0; i < n; i++) {
                parent[i] = i;
            }
        }

       
        //find parent //////////////
        int find(int x) { //union하면서 아직 update안된 parent들 udpate하면서 find
            if (parent[x] != x) {
                parent[x] = find(parent[x]); // 경로 압축: 부모를 찾아서 업데이트하면서 재귀적으로 호출
            }
            
            return parent[x];  // 노드 x의 부모 반환
        }

        boolean isConnected(int x, int y) {
            return find(x) == find(y);
        }

        void union(int x, int y) {
            int rootX = find(x);
            int rootY = find(y);

            if (rootX == rootY) return;

            if (size[rootX] > size[rootY]) parent[rootY] = rootX;
            else if (size[rootX] < size[rootY]) parent[rootX] = rootY;
            else {
                parent[rootY] = rootX;
                size[rootX]++;
            }

        }
    }


   구현에 DisjointSet(서로소 집합)과 union 이 필요할 것 같아서 링크 REF

 

Kruskal 알고리듬: O(eloge)    -  e 가 적당하다면 이 알고리듬이 훨씬 낫다. 

  - 일단 min Edge 들을 연결한다. (단 cycle이 안생기는 방식으로 연결)

 - 마지막엔   Set 과 Set 간 연결들이 필요.

 

 

<TSP: Travelling Salesman Problem>

모든 노드를 한번씩만 돌아서 다 돌때 최소 weight 찾는 문제로, 일반적으로 알고리듬이 없다. 

즉 모든 경우의 수를 다 해봐야 한다.  

 

 

 

 

   ====Tree BFS code  (순서없이 BFS Breadth First Search )======

위에 5줄이면 충분함.   detail을 포함한 세부구현은 아래 더보기 참조.

더보기
class Node{
    int value;
    Node left;
    Node right;

    public Node (){
        left=right=null;
    }

    public Node (int v){
        value = v;
    }
}

class Test {

    /* DFS */
    public void printInOrder(Node node){  //이함수는 DFS recursive test용 임.

        if (node != null){
            printInOrder(node.left);
            out(":" +node.value);
            printInOrder(node.right);
        }
    }
    
    /* simple class for Marking a New Line in the Queue
     */
    class NewLine extends Node{

    }
    
    /* print same depth nodes at the same line
     * @param binTree : root Node of binary Tree
     */
    public void printBFSTree(Node binTree){

        if (binTree == null) return;
        Queue<Node> queue = new LinkedList<Node>();
        
        queue.add( binTree );
        queue.add( new NewLine()); //depth seperator
        
        while (queue.size() > 0){

            Node node = queue.poll();
            
            if ( node instanceof NewLine) { //(Depth changed)
                System.out.println();   //print new Line
                if (queue.size() > 0)
                    queue.add(node);           //add NewLine for added sibling
            }else {                   //(general Node)
                //print Node's value
                System.out.print(node.value + " ");
            }
            
            if (node.left != null) {
                queue.add( node.left );
            }

            if (node.right != null) {
                queue.add( node.right );
            }
        }
    }
 

 

Posted by yongary
,

콤비네이션(C) 알고리듬 참조:  http://stackoverflow.com/questions/2201113/combinatoric-n-choose-r-in-java-math 

 

int nCk = 1;
       
for (int k = 0; k < K; k++) {
           
System.out.print(nCk + " ");
            nCk
= nCk * (n-k) / (k+1);
       
}

예) 5C3 =   5/1 * 4/2 * 3/3  =  10..

 

중복 콤비네이션(H) 참조: https://ko.wikipedia.org/wiki/%EC%A1%B0%ED%95%A9 

    개의 빈칸에 중복을 허용하여 개의 원소를 넣는 개수로 생각할 수 있다.?

      즉, 개의 칸막이를 두고 가지 경우를 임의의 순서로 배열하는 것.?

 

      nHk = (n+k-1)C(n-1) = (n+k-1)Ck

 

 

Posted by yongary
,

참고: java binarySearch예제

Comparator<Person> ageComparator = Comparator.comparingInt(Person::getAge);

int index = Arrays.binarySearch(people, new Person("Bob", 30), ageComparator);

(찾으면 >=0 못찾으면 -index-1 리턴)

 

 

아래는 없을땐 -1 리턴하는 java 코드들입니다.

 

<sort된 array내에서 exact매칭을 위한  BinSearch >

 

public int binSearch ( int A[],  int target ){

 

int low = 0;

int high = A.length -1;

int mid = 0;

 

while (low <= high ){

mid = (low+high)/2;

 

if       ( A[mid] < target)  low = mid+1;

else if ( A[mid] > target ) high = mid -1;

else 

return mid;

}

return -1;

}

 

<sort + rotate된 array내에서 exact매칭을 위한  BinSearch 
예) [4,5,6,7,8, 0,1,2,3] 에서 target이 2인경우 ==> 정 답: 7

public int search(int[] nums, int target) {
        int low = 0;
        int high = nums.length - 1;
        int mid = 0;

        while (low <= high) {
            mid = (low + high) /2;
            
            if (nums[mid] == target) return mid;
            
            //left half sorted
            else if (nums[low] <= nums[mid] ) {
                //target이 left 존재 (mid제외)
                if (nums[low] <= target && nums[mid] > target) {
                    high = mid - 1;
                } 
                else low = mid + 1;
            }
            //right half sorted
            else {
                //target이 right에 존재 (mid 제외)
                if (nums[mid] < target && nums[high] >= target )
                    low = mid + 1;
                else
                    high = mid - 1;     
            }
        }
        return -1;
    }

 

 

<LE를  위한  BinSearch >  : LE - lessthan or Equal을 만족하는 최대 index 리턴.  

 

// A:{1,2,5, 9, 10}, target:7 =>   index:2 return이 목표.

public int binSearchLE ( int A[],  int target ){    

int low = 0;

int high = A.length -1;

int mid = 0;

 

while (low <= high) {

mid = (low+high)/2;

 

if       ( A[mid] < target)  low = mid+1;

else if ( A[mid] > target ) high = mid -1;

else 

return mid;

}

 

if ( mid>0 ) {   

if (A[mid] < target )    //LE CHeck

return mid;

 

if (A[mid] > target && A[mid-1] < target ) 

return mid-1; 

}

if (mid==0){  //mid가 0일경우는 어떡하나?

if (A[0] < target) return 0;

}

 

return -1;

}

 

   ======> 마지막 2개의 if를 간단히 3줄로도 줄일 수 있음.

if (arr[mid] < target) return mid;

else if (mid > 0 && arr[mid] > target && arr[mid-1] < target)
return mid -1;

 

//// low,high trace ///////////////////////

0,4 -> mid:2   if

3,4 -> mid:3   else_if

3,3 -> (mid:3) else_if

=> low,high가 마지막 loop이므로 이때 one more check가 필요. 

   return -1;  

 

 

 

<GE를  위한  BinSearch >  : GE - grea than or Equal을 만족하는 최소 index 리턴. 

 

// A:{1,2,5, 9, 10}, target:7 =>   index:3  return이 목표.

public int binSearchGE ( int A[],  int target ){    

int low = 0;

int high = A.length -1;

int mid = 0;

 

while (low <= high) {

mid = (low+high)/2;

 

if       ( A[mid] < target)  low = mid+1;

else if ( A[mid] > target ) high = mid -1;

else 

return mid;

}

 

if ( mid < A.length-1 ) {  

      if ( A[mid] < target &&  A[mid+1] > target ) 

return mid+1;

 

if  (A[mid] > target )  //GE CHeck

return mid;

 }

 

if (mid==A.length-1){  //?

if (A[mid] > target) 

return (A.length-1);

}

return -1;

}

 

//// low,high trace ///////////////////////

0,4 -> mid:2   if

3,4 -> mid:3   else_if

3,3 -> (mid:3) else_if

=> low,high가 마지막 loop이므로 이때 one more check가 필요. 

   return -1;  

Posted by yongary
,

/*

usage: 

MyJson mj = new MyJson(aLineString);   // {"key1:value1","key2:value2"} 

        String offTime = mj.get("key1") ;

*/



class MyJson{

private HashMap<String, String> hm = new HashMap<String,String>();

public MyJson(String json){

String normal = json.replaceAll("[{\"}]", ""); //remove {,", }

System.out.println("(normal)"+normal);

String[] kvset = normal.split(",\\s*");  // comma + (*:space exist or not)

for( String s : kvset){

String kv[] = s.split(":");

if( kv.length==2)

hm.put(kv[0], kv[1]);

else{

System.err.println("Json Parse err(may have only key) "+s);

}

}

}

public String get(String key){

return hm.get(key);

}

}

Posted by yongary
,

=============My BucketSort. Example===================

 

import java.util.HashMap;
import java.util.LinkedList;
import java.util.ListIterator;



public class BucketSort {

private HashMap<Integer, LinkedList> hMap;
/*
input: unSorted Array, #bucket(number of Bucket)
process: bucket sorting Using #bucket
return: sorted Array.
*/
public Integer[] bucketSort(Integer data[], int numBucket){
Integer[] ret = new Integer[data.length];
hMap = new HashMap<Integer, LinkedList>();



for (int i: data) {
Integer key = numBucket * (i / numBucket); //분모가 maxInt 가 맞을듯.(16.6)

==> 그냥 i%numBucket가 맞을 듯한데.. 좀더 보자.(2017.10)

LinkedList<Integer> prevList;



//make new List and add to HashMap.. when there's no data
if ( (prevList = hMap.get(key)) == null ) {
LinkedList<Integer> list = new LinkedList<Integer>();
list.add(i);
hMap.put(key,list);
}else{ //prevList traverse and add i to apporate position
ListIterator<Integer> it = prevList.listIterator();

boolean added = false; //added flag prevents Concurrent Modify Error.
while (it.hasNext()) { //at least 1 element. SO always on this loop.
if (it.next() > i ) { //Add to Proper position
prevList.add(it.previousIndex(),i);
added = true;
break;
}
}
if (!added)
prevList.add(i); //Add to End

}//else
} //for



//to array.
int k=0;
for (int j=0; j< numBucket; j++){
Integer key = numBucket*j;
LinkedList<Integer> list = hMap.get(key);

if (list!=null) {
ListIterator<Integer> it = list.listIterator();

while (it.hasNext())
ret[k++] = it.next();
}
}

return ret;
}

/////////MAIN /////////////////
public static Integer datas[]={77, 11, 22, 55, 44, 33, 99, 88, 21, 23, 37, 41, 81, 91, 74, 19, 30, 40 };

public static void main(String args[]){

BucketSort b = new BucketSort();
Integer[] data = b.bucketSort(datas, 10);

for ( int i : data)
System.out.print(i+",");
}
}


Posted by yongary
,

Quick Sort using java Generic.

==>   <T extends Comparable> working. <T implements Comparable> not working.

 (Java Generic을 이용해서 Quick Sort를 구현하여보았는데..

            ==>  <T extends Comparable> 이건 동작하는데 <T implements Comparable>은 동작하지 않음)

public class QSortGen<T extends Comparable> {  


void swap(T data[], int i, int j){
T tmp = data[i];
data[i]=data[j];
data[j]=tmp;
}

public void qSort( T[] data, int st, int end){
if (st == end || end < 0) return;

T pivot=data[end]; //Pivot is End (temporary)

int j=end-1;
int i=0;
while (i<j) {
while ( i<j && data[i].compareTo(pivot) < 0 ) i++;
while ( j>i && data[j].compareTo(pivot) > 0) j--;
if (i < j)
swap(data, i, j);
};

System.out.println( "new Pivot:" +i + ","+j);

//IF pivot Largest ?
if ( j == end-1 && data[j].compareTo(pivot) < 0 ) // (j == end-1) =>sometimes wrong. when only 3 data.
qSort(data, 0, end-1);

//General pivot
else {
swap(data, i ,end); //i is real Pivot
qSort(data, 0, i-1); //left divide and conquer:recursive
qSort(data, j+1, end); //right divide and comquer:recursive
}
}

/////////MAIN /////////////////
public static String datas[]={"adf", "kk", "bb", "aa", "dd", "cc", "ff" };

public static void main(String args[]){
QSortGen<String> q = new QSortGen<String>();
q.qSort(datas, 0, datas.length-1);

for( String a : datas)
System.out.println(a);
}
}


Posted by yongary
,

Quick Sort (java)

algorithm & type 2016. 1. 31. 00:34

[int Array기반 간단한 QuickSort]

- http://www.algolist.net/Algorithms/Sorting/Quicksort 참고.

=>c++ 코드 참조하면.. 한번소트 후에, 끝나면 i가 j보다 크군요..

(j=2, i=3) 이때, j포함 왼쪽. i포함 오른쪽 돌려야 함.

public void quickSort(int arr[], int left, int right) { int i = left, j = right; int tmp; int pivotValue = arr[(left + right) / 2]; /* partition */ while (i <= j) { while (arr[i] < pivotValue) i++; while (arr[j] > pivotValue) j--; if (i <= j) { tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; i++; j--; } }; /* recursion */ if (left < j) quickSort(arr, left, j); if (i < right) quickSort(arr, i, right); } public static void main(String args[]){ SortSearch s = new SortSearch(); int A[] = new int[] {9,8,7,6,5,4,3,2,1}; s.quickSort(A, 0, A.length-1); for (int a : A){ System.out.println(a); }

}




-----------아래 건은 연습용------------------

[Simple Quick Sort Example.. with String Array]

- using End element as a temporary Pivot.


 

public class QuickSort {


void swap(String data[], int i, int j){
String tmp = data[i];
data[i]=data[j];
data[j]=tmp;
}

public void qSort( String[] data, int st, int end){
if (st == end || end < 0) return;

String pivot=data[end];
//Pivot is End (temporary)

int j=end-1;
int i=0;
while (i<j) {
while ( i<j && data[i].compareTo(pivot) < 0 ) i++;
while ( j>i && data[j].compareTo(pivot) > 0) j--;
if (i < j)
swap(data, i, j);
};

System.
out.println( "new Pivot:" +i + ","+j);

//IF pivot Largest ?
if ( j == end-1 && data[j].compareTo(pivot) < 0 ) // (j == end-1) =>sometimes wrong. when only 3 data.
qSort(data, 0, end-1);

//General pivot
else {
swap(data, i ,end);
//i is real Pivot
qSort(data, 0, i-1); //left divide and conquer:recursive
qSort(data, j+1, end); //right divide and comquer:recursive
}
}

/////////main
public static String datas[]={"adf", "kk", "bb", "aa", "dd", "cc", "ff" };
public static void main(String args[]){
QuickSort q =
new QuickSort();
q.qSort(
datas, 0, datas.length-1);

for( String a : datas)
System.
out.println(a);
}
}


Posted by yongary
,

일반적으로 정렬 중에 가장 빠른 알고리듬은 quick sort로서 O(N*logN)의 평균속도를 가지고 있다.

 

하지만, 분포가 어느정도 균등한 자료의 경우

버킷 소트를 하게 되면 O(n)으로 정렬을 할 수 있다.

 

Hash의 개념을 사용하게 되며..  그림은 REF-SITE  참조.

 

 

단점: 버킷을 미리 만들어 둬야 하므로 메모리 소비가 좀 있고

그 외 최악의 속도는 O(n)*버킷내 정렬시간 이 되므로 O(n**2)까지도 갈 수 있다.

(어차피 quick sort도 O(n**2)까지 갈 수 있으므로.  자료가 적당하다면 일반적으로 quick sort보다 속도는 좋은 것 같다 ).

Posted by yongary
,