アルゴリズムベース

43616 ワード

1.共通コード


1.1 character to integer

char c ='1';
int number = Character.getNumericValue(c);

1.2逆転数

public static int reverse(int n) {
  int reverse = 0;
  while(n != 0) {
    reverse *= 10;
    reverse += (n % 10);
    n = n / 10;
  }
  return reverse;
}

1.3逆転文字列

// 추가 공간을 사용하지 않는 방법 
public static String reverseString(String original) {
  char[] chs = original.toCharArray();
  int length = chs.length;
	    
  for(int i=0; i<length/2; i++) {
    // swap characters
    char tmp = chs[i];
    chs[i] = chs[length-1-i];
    chs[length-1-i] = tmp;
  }
  return new String(chs);
}

// 추가 공간을 사용 하는 방법
public static String reverseString(Strign original) {
  char[] chs = original.toCharArray();
  char[] result = new char[chs.length];
  
  for(int i=0; i<chs.length - 1; i++) {
    result[i] = chs[chs.length - i - 1];
  }
  return new String(result);
}

1.4 Swap

// 기본 스왑 
public void swap(int x, int y) {
  int tmp = x;
  x = y;
  y = tmp;
}

// XOR을 사용한 스왑 
// (피연산자의 수가 서로 다를 경우에만 1인 XOR의 성질을 이용해서 2진수로 풀어 계산 해보면 된다.)
public void swap(int x, int y) {
  x = x ^ y;
  y = x ^ y;
  x = x ^ y;
}
  • 注:リンク1
  • メモリンク2
  • 2.並べ替え


    2.1 Quick sort

  • 時間複雑度:最悪O(n^2)、平均O(n log n)
  • 運転説明
    a.リストから要素を選択します.この均一な要素を軸心と呼ぶ.
    b.ピボットを基準としてリストを2つの部分に分けます.1つは、ピボット前のピボット値より小さいすべての要素であり、もう1つは、ピボット後のピボット値より大きいすべての要素です.このようにリストを二つに分けることを分割と呼ぶ.分割が完了すると、ピボットは移動しません.
    c.分割された2つの小さなリストを再帰的に繰り返します.リストのサイズが0または1になるまで再帰的に繰り返します.
  •     public static void quickSort(int[] arr, int low, int high) {
             if(low >= high) return;
             
             // pick the pivot
             int middle = low + (high - low) / 2;
             int pivot = arr[middle];
             
             // make left < pivot and right > pivot
             int i = low, j = high;
             while(i <= j) {
                 while(arr[i] < pivot) {
                     i++;
                 }
                 while(arr[j] > pivot) {
                     j--;
                 }
                 if(i <= j) {
                     // swapping
                     int tmp = arr[i];
                     arr[i] = arr[j];
                     arr[k] = tmp;
                     i++;
                     j--;
                 }
             }
             if(low < j) {
                 quickSort(arr, low, j);
             }
             if(high > i) {
                 quickSort(arr, i, high);
             }
         }
  • List実施版(リファレンス)
  •  private List<Integer> quicksort(List<Integer> input){
    		if(input.size() <= 1){
    			return input;
    		}
    		
    		int middle = (int) Math.ceil((double)input.size() / 2);
    		int pivot = input.get(middle);
    
    		List<Integer> less = new ArrayList<Integer>();
    		List<Integer> greater = new ArrayList<Integer>();
    		
    		for (int i = 0; i < input.size(); i++) {
    			if(input.get(i) <= pivot){
    				if(i == middle){
    					continue;
    				}
    				less.add(input.get(i));
    			}
    			else{
    				greater.add(input.get(i));
    			}
    		}
    		return concatenate(quicksort(less), pivot, quicksort(greater));
    	}
    	
    	private List<Integer> concatenate(List<Integer> less, int pivot, List<Integer> greater){
    		List<Integer> list = new ArrayList<Integer>();
    		
    		for (int i = 0; i < less.size(); i++) {
    			list.add(less.get(i));
    		}
    		
    		list.add(pivot);
    		
    		for (int i = 0; i < greater.size(); i++) {
    			list.add(greater.get(i));
    		}
    		return list;
    	}

    2.2連結ソート

  • 時間複雑度:O(n long n)
  • 空間複雑度:O(n)
  • 運転説明
    a.リストの長さが0または1の場合、並べ替えられたものとみなす.そうでなければ、
    b.並べ替えられていないリストを半分に切り、2つの大きさに近い部分のリストに分けます.
    c.各部分のリストを再帰的に集計してソートする.
    d.2つの部分リストを1つのソートされたリストにマージします.
  • public class Mergesort {
            private int[] numbers;
            private int[] helper;
    
            private int number;
    
            public void sort(int[] values) {
                    this.numbers = values;
                    number = values.length;
                    this.helper = new int[number];
                    mergesort(0, number - 1);
            }
    
            private void mergesort(int low, int high) {
                    // check if low is smaller then high, if not then the array is sorted
                    if (low < high) {
                            // Get the index of the element which is in the middle
                            int middle = low + (high - low) / 2;
                            // Sort the left side of the array
                            mergesort(low, middle);
                            // Sort the right side of the array
                            mergesort(middle + 1, high);
                            // Combine them both
                            merge(low, middle, high);
                    }
            }
    
            private void merge(int low, int middle, int high) {
                    // Copy both parts into the helper array
                    for (int i = low; i <= high; i++) {
                            helper[i] = numbers[i];
                    }
    
                    int i = low;
                    int j = middle + 1;
                    int k = low;
                    // Copy the smallest values from either the left or the right side back
                    // to the original array
                    while (i <= middle && j <= high) {
                            if (helper[i] <= helper[j]) {
                                    numbers[k] = helper[i];
                                    i++;
                            } else {
                                    numbers[k] = helper[j];
                                    j++;
                            }
                            k++;
                    }
                    // Copy the rest of the left side of the array into the target array
                    while (i <= middle) {
                            numbers[k] = helper[i];
                            k++;
                            i++;
                    }
            }
    }

    3.探索


    3.1優先ナビゲーション幅(BFS)

  • 幅優先探索(Breadth-first search,BFS)は盲目的な探索方法であり、開始頂点に先にアクセスしてから、開始頂点に近いすべての頂点にアクセスする方法である.アクセスしていないすべての頂点に対して、アクセスしないまで幅優先検索を適用します.OPEN Listは、レベル順にアクセスするにはキューを使用する必要があります.
  • の利点
  • からターゲットノードへの最短パスを保証します.
  • の欠点
  • 経路が長い場合、ナビゲーションバーが急激に増加するにつれて、より多くの記憶空間が必要になる.
  • 解が存在しない場合、有限図(finitegraph)にとって、すべての図はナビゲーション後に失敗に終わる.
  • 無限図(無限図)の場合、永遠に解が見つからず、終わりません.
  • public static void bfs(int[][] mat, int startVertex) {
      Queue<Integer> queue = new LinkedList<>();
      boolean[] visited = new boolean[mat[startVertex].length];
    
      visited[startVertex] = true;
      queue.add(startVertex);
    
      int e = 0, i = 0;
      while(!queue.isEmpty()) {
        e = queue.remove();
        i = e;
        while(i <= mat[startVertex].length) {
          if(mat[e][i] == 1 && !visited[i]) {
            queue.add(i);
            visited[i] = true;
          }
          i++;
        }
      }
    }

    3.2 DFS(深度優先ナビゲーション)

  • は盲目的な探索方法であり,探索ツリーが最近追加したノードを選択し,そのノードに適用可能な動作サブノードの1つを適用し,追加したサブノードがターゲットノードであるまで前サブノードの追加過程を繰り返す.
  • の利点
  • は、現在のパス上のノードを記憶するだけで、記憶領域の需要は小さい.
  • ターゲットノードが深い段階にある場合、迅速に解くことができる.
  • の欠点
  • 年の経路がない可能性があります.したがって、実際には、ターゲットノードが見つからずに予め指定された任意の深さにのみブラウズする場合、以下のパスに沿ってブラウズする方法が有用である可能性があります.
  • が得られなかった年が最短経路の保障となった.これは,ターゲットに到達する経路が多いという問題に対して,深さ優先探索は1年で探索を終了し,このとき得られる解は最適解ではない可能性があることを意味する.
  •  int map[][], visit[];
    
    void dfs(int vertexSize, int v) { 
      int i;
      visit[v] = 1; // root node
      for(i=1; i<=vertexSize; i++) {
        if(map[v][i] == 1 && !visit[i]) {
          dfs(i);
        }
      }
    }