1、旋转输出矩阵
public int[][] generateMatrix(int n) {
if(n<1)
return null;
int[][] matrix = new int[n][n];
int startX = 0;
int startY = 0;
int loop = n/2;
int mid = n/2;
int i;
int j;
int offset = 1;
int count = 1;
while(loop!=0) {
i = startX;
j = startY;
for(j = startY; j < startY + n - offset; j++)
matrix[i][j] = count++;
for(i=startX; i < startX + n - offset; i++)
matrix[i][j] = count++;
for(; j > startY; j--)
matrix[i][j] = count++;
for(; i > startX; i--)
matrix[i][j] = count++;
startX++;
startY++;
offset += 2;
loop--;
}
if(n%2!=0)
matrix[mid][mid] = count;
return matrix;
}
2、给定一个矩阵 int matrix [m][n],每行每列都是增序的,实现一个算法去寻找矩阵中的某个元素
//从右上角开始搜索
public boolean searchMatrix(int[][] matrix, int target) {
int rows = matrix.length;
int columns = matrix[0].length;
boolean found = false;
if(matrix != null && rows > 0 && columns > 0) {
int row = 0;
int column = columns - 1;
while(row < rows && column >= 0) {
if(matrix[row][column] == target) {
found = true;
break;
}
else if(matrix[row][column] > target)
column--;
else row++;
}
}
return found;
}
3、top-k排序(求最小的k个元素)
思路1:最基本的思路,将N个数进行完全排序,从中选出排在前K的元素。目前来看快速排序、堆排序和归并排序都能达到O(NlogN)的时间复杂度。
思路2:可以采用数据池的思想,选择其中前K个数作为数据池,后面的N-K个数与这K个数进行比较,若小于其中的任何一个数,则进行替换。这种思路的算法复杂度是O(N*K)
从思路2可以想到,剩余的N-K个数与前面K个数比较的时候,是顺序比较的,算法复杂度是K。采用堆可以进一步降低时间复杂度。
思路3:大根堆维护一个大小为K的数组,目前该大根堆中的元素是排名前K的数,其中根是最大的数。此后,每次从原数组中取一个元素与根进行比较,如小于根的元素,则将根元素替换并进行堆调整(下沉),即保证大根堆中的元素仍然是排名前K的数,且根元素仍然最大;否则不予处理,取下一个数组元素继续该过程。该算法的时间复杂度是O(N*logK),该算法不需要一次将原数组中的内容全部加载到内存中,而这正是海量数据处理必然会面临的一个关卡。
要自己实现一个堆非常麻烦,可以询问一下面试官是否可以使用java中的API。
public int[] getLeastNumbers(int[] arr, int k) {
int[] result = new int[k];
if(k == 0)
return result;
PriorityQueue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
for (int i = 0; i < k; i++) {
queue.offer(arr[i]);
}
for (int i = k; i < arr.length; i++) {
if (queue.peek() > arr[i]) {
queue.poll();
queue.offer(arr[i]);
}
}
for(int i=0;i<k;i++){
result[i] = queue.poll();
}
return result;
}
思路4:借鉴快速排序的思想。快排的划分函数每次执行完后都能将数组分成两个部分,小于等于分界值 pivot 的元素的都会被放到数组的左边,大于的都会被放到数组的右边,然后返回分界值的下标。与快速排序不同的是,快速排序会根据分界值的下标递归处理划分的两侧,而这里我们只处理划分的一边,时间复杂度是O(N)。
public int[] getLeastNumbers(int[] arr, int k) {
randomSelected(arr, 0, arr.length - 1, k);
int[] result = new int[k];
for (int i = 0; i < k; i++) {
result[i] = arr[i];
}
return result;
}
private void randomSelected(int[] arr, int left, int right, int k) {
if (left >= right)
return;
int position = randomPartition(arr, left, right);
int num = position - left + 1;
if(k == num)
return;
else if(k < num) {
randomSelected(arr, left, position - 1, k);
}
else randomSelected(arr, position + 1, right, k - num);
}
private int randomPartition(int[] arr, int start, int end) {
//注意这个随机数产生的方法,不能忘了后面再加一个start
int index = new Random().nextInt(end - start + 1) + start;
swap(arr, index, end);
int pivot = arr[end];
int small = start - 1;
for(index = start; index < end; index++) {
if(arr[index] <= pivot) {
small++;
if(small != index) {
swap(arr, index, small);
}
}
}
swap(arr, ++small, end);
return small;
}
private void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
4、冒泡排序
public static void bubbleSort(int[] arr) {
if(arr == null || arr.length < 2)
return;
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - i - 1; j++) {
if(arr[j] > arr[j+1]) {
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
5、堆排序
public static void heapSort(int[] arr) {
for (int i = arr.length / 2 - 1; i >= 0; i--) {
adjustHeap(arr, i, arr.length);
}
for(int i = arr.length - 1; i > 0; i--) {
swap(arr, 0, i);
adjustHeap(arr, 0, i);
}
}
private static void adjustHeap(int[] arr, int i, int length) {
int temp = arr[i];
for (int k = 2 * i + 1; k < length; k = k * 2 + 1) {
if (k + 1 < length && arr[k] < arr[k + 1])
k++;
if (arr[k] > temp) {
arr[i] = arr[k];
i = k;
} else {
break;
}
}
arr[i] = temp;
}
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
6、椭圆形场地有两个赛道,可以同时提供两匹马比赛,两匹马比赛后,可以获知两匹马中跑的快的那匹马,但是没有计时工具。问题,如何最优的算法(比赛次数最少),获知10匹马中速度最快的三匹马
这道题其实和top-k的意思是一样的,最少的次数其实就是最优的时间复杂度,选择思路4,使用快速排序的思路。