排序练习
1已知一个几乎有序的数组,几乎有序是指,如果把数组排好顺序的话,每个元素移动的距离可以不超过k,并且k相对于数组来说比较小。请选择一个合适的排序算法针对这个数据进行排序。
给定一个int数组A,同时给定A的大小n和题意中的k,请返回排序后的数组。
[2,1,4,3,6,5,8,7,10,9],10,2
返回:[1,2,3,4,5,6,7,8,9,10]
改进后的堆排序,取k个元素排序
import java.util.*; public class ScaleSort { public int[] sortElement(int[] A, int n, int k) { if (A == null || A.length == 0 || n < k) { return A; } int[] heap = getKHeap(A, k); for(int i = k; i < n; i++){ A[i - k] = heap[0]; heap[0] = A[i]; heapify(heap, 0, k); } for(int i = n - k; i < n; i++){ A[i] = heap[0]; swap(heap, 0, k - 1); heapify(heap, 0, --k); } return A; } public int[] getKHeap(int[] A, int k){ int[] heap = new int[k]; for(int i = 0; i < k; i++){ heapInsert(heap, A[i], i); } return heap; } public void heapInsert(int[]A, int value, int index){ A[index] = value; while(index != 0){ int parent = (index - 1) / 2; if(A[parent] > A[index]){ swap(A, parent, index); index = parent; } else{ break; } } } public void heapify(int[] arr, int index, int heapSize) { int left = index * 2 + 1; int right = index * 2 + 2; int smallest = index; while (left < heapSize) { if (arr[left] < arr[index]) { smallest = left; } if (right < heapSize && arr[right] < arr[smallest]) { smallest = right; } if (smallest != index) { swap(arr, smallest, index); } else { break; } index = smallest; left = index * 2 + 1; right = index * 2 + 2; } } public void swap(int[] arr, int index1, int index2) { int tmp = arr[index1]; arr[index1] = arr[index2]; arr[index2] = tmp; } }
2请设计一个高效算法,判断数组中是否有重复值。必须保证额外空间复杂度为O(1)。
给定一个int数组A及它的大小n,请返回它是否有重复值。
[1,2,3,4,5,5,6],7
返回:true
堆排序,需要改写为非递归实现
import java.util.*; public class Checker { public boolean checkDuplicate(int[] a, int n) { if (a == null || n == 0) { return false; } heapSort(a); for (int i = 1; i < n; i++) { if (a[i] == a[i - 1]) { return true; } } return false; } public void heapSort(int[] arr) { for (int i = 0; i != arr.length; i++) { heapInsert(arr, i); } for (int i = arr.length - 1; i != 0; i--) { swap(arr, 0, i); heapify(arr, 0, i); } } public void heapInsert(int[] arr, int index) { while (index != 0) { int parent = (index - 1) / 2; if (arr[parent] < arr[index]) { swap(arr, parent, index); index = parent; } else { break; } } } public void heapify(int[] arr, int index, int heapSize) { int left = index * 2 + 1; int right = index * 2 + 2; int largest = index; while (left < heapSize) { if (arr[left] > arr[index]) { largest = left; } if (right < heapSize && arr[right] > arr[largest]) { largest = right; } if (largest != index) { swap(arr, largest, index); } else { break; } index = largest; left = index * 2 + 1; right = index * 2 + 2; } } public void swap(int[] arr, int index1, int index2) { int tmp = arr[index1]; arr[index1] = arr[index2]; arr[index2] = tmp; } }
3有两个从小到大排序以后的数组A和B,其中A的末端有足够的缓冲空容纳B。请编写一个方法,将B合并入A并排序。
给定两个有序int数组A和B,A中的缓冲空用0填充,同时给定A和B的真实大小int n和int m,请返回合并后的数组。
import java.util.*; public class Merge { public static int[] mergeAB(int[] A, int[] B, int n, int m) { int index=n+m-1; int i=n-1; int j=m-1; while(i>=0&&j>=0){ if(A[i]>B[j]){ A[index]=A[i]; i--; }else{ A[index]=B[j]; j--; } index--; } while(j>=0){ A[index]=B[j]; j--; index--; } return A; } }
加上
while(j>=0){
A[index]=B[j];
j--;
index--;
}
考虑到A中已合并完,而B中还有元素(若B合并完,A中还有元素,不用处理)
4有一个只由0,1,2三种元素构成的整数数组,请使用交换、原地排序而不是使用计数进行排序。
给定一个只含0,1,2的整数数组A及它的大小,请返回排序后的数组。保证数组大小小于等于500。
[0,1,1,0,2,2],6
返回:[0,0,1,1,2,2]
import java.util.*; public class ThreeColor { public int[] sortThreeColor(int[] A, int n) { int p0 = 0; int p2 = n-1; int temp = 0; for (int i = 0 ;i < n ; i++){ if ( p2 < i) break; if ( A[i] < 1){ temp = A[i]; A[i] = A[p0]; A[p0] = temp; p0++; } if ( A[i] > 1){ temp = A[i]; A[i] = A[p2]; A[p2] = temp; i--; p2--; } } return A; } }
5现在有一个行和列都排好序的矩阵,请设计一个高效算法,快速查找矩阵中是否含有值x。
给定一个int矩阵mat,同时给定矩阵大小nxm及待查找的数x,请返回一个bool值,代表矩阵中是否存在x。所有矩阵中数字及x均为int范围内整数。保证n和m均小于等于1000。
[[1,2,3],[4,5,6],[7,8,9]],3,3,10
返回:false
import java.util.*; public class Finder { public boolean findX(int[][] mat,int n,int m,int x){ int i=0; int j=m-1; while(i<n&&j>=0){ if(mat[i][j]<x){ i++; }else if(mat[i][j]==x){ return true; }else if(mat[i][j]>x){ j--; } } return false; } }
牛客网上的答案
import java.util.*; public class Finder { public boolean findX(int[][] mat, int n, int m, int x) { int a = n - 1 ; int b = 0 ; while ( a >= 0 && b < m ){ if ( mat[a][b] == x ) return true ; if ( mat[a][b] > x ){ a-- ; if( a < 0 ){ break; } } if ( mat[a][b] < x ) b++ ; } return false; } }
6
对于一个数组,请设计一个高效算法计算需要排序的最短子数组的长度。
给定一个int数组A和数组的大小n,请返回一个二元组,代表所求序列的长度。(原序列位置从0开始标号,若原序列有序,返回0)。保证A中元素均为正整数。
[1,4,6,5,9,10],6
返回:2
import java.util.*; public class Subsequence { public int shortestSubsequence(int[] A, int n) { // write code here int max=A[0]; int min=A[n-1]; int right=0; int left=0; for(int i=0;i<n;i++){ if(A[i]>=max){ max=A[i]; // right=i; }else{ right=i; } } for(int i=n-1;i>=0;i--){ if(A[i]<=min){ min=A[i]; // left=i; }else{ left=i; } } if(right==left){ return 0; }else{ return (right-left+1); } } }
牛客网上的答案
import java.util.*; public class Subsequence { public int shortestSubsequence(int[] A, int n) { // write code here int max = A[0],min = A[n-1],r = 0,l = 0; for (int i = 0;i < n;i++) { if (A[i] > max) max = A[i]; else if (A[i] < max) r = i; } for (int j = n-1;j >= 0;j--) { if (A[j] < min) min = A[j]; else if (A[j] > min) l = j; } if (r-l == 0) return 0; else return r-l+1; } }
7有一个整形数组A,请设计一个复杂度为O(n)的算法,算出排序后相邻两数的最大差值。
给定一个int数组A和A的大小n,请返回最大的差值。保证数组元素多于1个。
[1,2,5,4,6],5
返回:2
import java.util.*; public class Gap { public int maxGap(int[] A, int n) { // write code here Arrays.sort(A); int max=A[1]-A[0]; for(int i=2;i<n;i++){ if(A[i]-A[i-1]>max) max=A[i]-A[i-1]; } return max; } }
牛客网上的答案:
利用桶排序的思想
import java.util.*; public class Gap { public int maxGap(int[] A, int n) { // write code here if(null == A ||n<2) return 0; int min=Integer.MAX_VALUE; int max=Integer.MIN_VALUE; for(int i=0;i<n;i++){ if(A[i]>max) max=A[i]; if(A[i]<min) min=A[i]; } if(min==max) return 0; boolean[] hasNum =new boolean[n+1]; int[] maxs=new int[n+1]; int[] mins=new int[n+1]; for(int i=0;i<n;i++){ int bid=bucket(A[i],n,min,max); maxs[bid]=hasNum[bid]?Math.max(maxs[bid],A[i]):A[i]; mins[bid]=hasNum[bid]?Math.min(mins[bid],A[i]):A[i]; hasNum[bid]=true; } int res=0; int lastMax=0; int i=0; while(i<=n){ if(hasNum[i++]){ lastMax = maxs[i-1]; break; } } for(;i<=n;i++){ if(hasNum[i]){ res=Math.max(res,mins[i]-lastMax); lastMax=maxs[i]; } } return res; } public int bucket(long num,long length,long min,long max){ return (int)((num-min)*length/(max-min)); } }

浙公网安备 33010602011771号