【2019春招准备:9.算法进阶】

【内容】
topK
DP
red-black-tree
trie字典树
【补充】

  1. topK

!如果 k 很小,例如10以内的话,则利用冒泡堆排都可以,毕竟 k 和 logk 相差不大,但是冒泡相对简单。
!如果 k 比较大,则不适合用冒泡,考虑堆排和快排,一个是nlogk,一个是 2n - (2n/2^logn),一般而言是快排比较快,但是如果数组会动态变化的话,堆排比较好,因为插入复杂度可以控制在logk,而快排是k。

时间复杂度 空间复杂度 评价
冒泡 O ( K N ) O(KN) OKN 1或者K O ( N l o g ( K ) ) O(N log(K)) ONlogK相差不大,但是简单
小顶堆 O ( N l o g ( K ) ) O(N log(K)) ONlogK K:存放新的小顶堆 适用于单线程环境
快排 O ( N ) O(N) ON O ( 1 ) O(1) O(1)

求K个最大值用小顶堆,求K个最小值用大顶堆

package q3_sort;

import java.util.Arrays;

/**
 * 新建一个小顶堆 初始化放入前K个 遍历后面N-K个 如果大于堆顶 将堆顶
 * 
 * @author ziboris
 * @date 2018年11月26日 下午4:48:21
 *
 */

public class Test3_topK_heap {

	static final int n = 3;// top的个数
	static final int m = 20;// 数据集的原始个数
	static final int a[] = new int[m];

	static int topK[] = new int[n + 1];

	public static void downAdjust(int low, int high) {
		int i = low;
		int j = i * 2;
		while (j <= high) {
			if (j + 1 <= high && topK[i] > topK[j + 1])
				j = j + 1;
			if (topK[i] > topK[j]) {
				int temp = topK[i];
				topK[i] = topK[j];
				topK[j] = temp;
				i = j;
				j = j * 2;
			} else {
				break;
			}
		}
	}

	public static void get_topk() {
		// init初始化小顶堆
		for (int i = n / 2; i >= 1; --i) {
			downAdjust(i, n);
		}

		for (int i = n; i < a.length - 1; ++i) {
			if (a[i] > topK[1]) {
				topK[1] = a[i];
				for (int j = n / 2; j >= 1; --j) {
					downAdjust(j, n);
				}
			}
		}
	}

	public static void main(String[] args) {
		for (int i = 0; i < m; ++i) {
			a[i] = (int) (Math.random() * 100);
		}

		for (int i = 1; i <= n; ++i) {
			topK[i] = a[i - 1];
		}
		System.out.println("original:" + Arrays.toString(a));
		get_topk();
		System.out.println("topK:" + Arrays.toString(topK));
	}
}

快排

public static int Partition(int low, int high) {
	int i = low, j = high, x = a[low];
	if (low < high) {
		while (i < j) {
			while (i < j && a[j] >= x)
				--j;
			if (i < j)
				a[i++] = a[j];

			while (i < j && a[i] < x)
				++i;
			if (i < j)
				a[j--] = a[i];
		}
		a[i] = x;
	}
	return i;
};

public static int get_topk(int start, int end, int k) {
	int index = 0;

	if (start < end) {
		index = Partition(start, end);
		if (index == k) {
			for (int i = 0; i < k; ++i) {
				topK[i] = a[i + 1];
			}
		} else if (index < k) {
			index = get_topk(index + 1, end, k - index);
		} else {
			index = get_topk(start, index - 1, k);
		}
	}

	return index;
}

你可能感兴趣的:(面试,Java)