프로그래밍의 아름다움[02]_계속하다
14031 단어 프로그래밍의 아름다움
해법 5,
생각:
1. 빠른 배열의 분치 사상을 채택하여 먼저 무서수 중의 랜덤수를 취하여 무서수를 1, 2 두 부분으로 나누는데 그 중에서 1부의 점수는 이 랜덤수 집합보다 작고 2부의 점수는 이 랜덤수 집합보다 크다.
2. 만약에 제1부분의 수(이 랜덤 수를 더한) 개수가 K라면 바로 앞의 K 개수를 되돌려주면 원하는 것이다.첫 번째 부분의 수가 K보다 크면 첫 번째 분수의 최대 K 수를 찾습니다.1부 점수 개수가 K보다 작으면 2부 점수 중 가장 큰 K-length 개수를 찾고,length는 1부 점수 개수를 찾습니다.
이 알고리즘의 시간 복잡도는 O(n*logn)로 빠른 배열과 마찬가지로 이 정렬 알고리즘은 무작위 수의 선택에 의존하여 불안정성을 가진다.
계산:
1. 전체 수조에 대해 분할 알고리즘(간단하게 첫 번째 수를 분할 랜덤수로 직접 추출할 수 있음).
2. 분할된 후 1부의 분수 개수가 K–1이면 수조 앞의 K 개수가 요구된다.만약 분할된 후 1부의 분수 개수가 K–1보다 작으면 2부의 분수 중 K–split의 최대 수를 찾아낸다.분할된 후 1부 점수가 K–1보다 크면 1부 점수 중 K개의 최대 수를 찾습니다.
코드:
private int partition(int[] arr, int begin, int end) {
int key = begin, tmp;
for(int low = begin, high = end; low < high; ) {
if(arr[low] < arr[high]) {
tmp = arr[low]; //swap arr[low] and arr[high]
arr[low] = arr[high];
arr[high] = tmp;
if(key == low) {
low++;
key = high;
} else {
high--;
key = low;
}
} else {
if(key == low) {
high--;
} else {
low++;
}
}
}
return key;
}
public void topK4(int []arr, int begin, int end, int k) {
int split = partition(arr, begin, end);
if((split - begin + 1) == k) {
return;
} else if(split - begin + 1 < k) {
topK4(arr, split + 1, end, k - (split - begin) - 1);
} else {
topK4(arr, 0, split - 1, k);
}
}
사고방식: 다중 병합 사고방식을 이용하여 먼저 무서수를 M등분으로 나누어 매등분 내의 수를 정렬한다(간단하게 빠른 배열을 사용할 수 있고 그 시간 복잡도는 Q*logQ, 그 중에서 Q는 매등분 내의 수의 개수). 그리고 패자수를 병합 정렬하여 매등분수에서 최대수를 추출하여 잎노드로 병합 정렬하고 노드와 아버지 노드를 비교한다.loser는 아버지 노드에 남는다.winner는 계속해서 더 높은 등급의 비교를 진행할 수 있다.
계산:
1. 무서수에 대해 M 등분의 구분을 한다.
2. 각 등분수 중 최대수를 순서대로 꺼내서 패자 나뭇잎 노드로siftup을 하고 winner 노드를 출력하며 이 승자 노드가 있는 등분에서 현재 최대수를 꺼내서 winner를 교체한다. 출력된 winner 노드의 개수가 K가 될 때까지.
public class LoseTree {
private int[] branches;
private int[] nodes;
public void getNumFromBuffer(List<Integer> buffer, int bufferIndex) throws Exception { //get number
if(buffer.size() == 0) {
throw new Exception("the buffer is null");
}
branches[bufferIndex] = buffer.remove(0);
}
public int competitionBranch(int branchIndex) {
int father = (nodes.length + branchIndex - 1) / 2;
while(father >= 0) {
if(branches[nodes[father]] > branches[branchIndex]) { //swap the nodes[father] and the branchIndex
int tmp = nodes[father];
nodes[father] = branchIndex;
branchIndex = tmp;
}
if(father == 0) break;
else father = (father - 1) / 2;
}
return branchIndex;
}
public int getBranch(int branchIndex) {
return branches[branchIndex];
}
public int init(List<Integer>[] buffers) throws Exception {
branches = new int[buffers.length];
for(int i = 0; i < branches.length; i++) {
getNumFromBuffer(buffers[i], i);
}
nodes = new int[branches.length - 1];
int max = -1;
for(int i = 0; i < branches.length; i++) {
if(max < branches[i]) { max = i; }
}
for(int i = 0; i < nodes.length; i++) {
nodes[i] = max;
}
int winnerIndex = 0;
for(int i = 0; i < nodes.length; i++) {
winnerIndex = competitionBranch(i);
}
return winnerIndex;
}
public LoseTree() {
}
}
@SuppressWarnings({ "unchecked", "rawtypes"})
public List<Integer>[] createBuffer(int[] arr, int k) {
List[] buffers = arr.length % k == 0 ? new List[arr.length / k] : new List[arr.length / k + 1];
for(int i = 0; i < buffers.length; i++) {
buffers[i] = new ArrayList();
}
for(int i = 0; i < arr.length; i++) {
buffers[i / k].add(arr[i]);
}
int addition = arr.length % k;
if(addition != 0) {
int end = arr.length / k;
for(int i = addition; i < k; i++) {
buffers[end].add(0);
}
}
for(int i = 0; i < buffers.length; i++) {
Collections.sort(buffers[i], Collections.reverseOrder());
}
return buffers;
}
public List<Integer> topK(int []arr, int k) throws Exception {
List<Integer>[] buffers = createBuffer(arr, k);
if(buffers.length == 1) {
return buffers[0];
}
LoseTree loseTree = new LoseTree();
int winnerIndex = loseTree.init(buffers);
List<Integer> topKArr = new ArrayList<Integer>();
for(int i = 0; i < k - 1; i++) {
winnerIndex = loseTree.competitionBranch(winnerIndex);
topKArr.add(loseTree.getBranch(winnerIndex));
loseTree.getNumFromBuffer(buffers[winnerIndex], winnerIndex);
}
winnerIndex = loseTree.competitionBranch(winnerIndex);
topKArr.add(loseTree.getBranch(winnerIndex));
return topKArr;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
프로그래밍의 아름다움[02]_계속하다2. 제목: 많은 무질서한 수 중에서 (먼저 서로 같지 않다고 가정하고) 그 중에서 가장 큰 K개의 수를 선택한다. 1. 빠른 배열의 분치 사상을 채택하여 먼저 무서수 중의 랜덤수를 취하여 무서수를 1, 2 두 부분...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.