代码搬运工之面试常撕题篇一
代码搬运工之面试常撕题篇一
熟读力扣300题,不会写题也会敲。
排序
面试官:写个快排吧 你:我擦,幸亏准备了,快排我写的很快。 为什么让你写快排? 因为面试官想看你写得到底有多快,不快的男人不是一个好程序员。
public static void quickSort(int[] nums, int low, int high) { if (low < high) { int index = partition(nums, low, high); quickSort(nums, low, index - 1); quickSort(nums, index + 1, high); } } public static int partition(int[] nums, int left, int right) { //基准值 int pivot = nums[left]; while (left < right) { //从右往左扫描 while (left < right && nums[right] >= pivot) { right--; } //找到第一个比pivot小的元素 if (left < right) nums[left] = nums[right]; //从左往右扫描 while (left < right && nums[left] <= pivot) { left++; } //找到第一个比pivot大的元素 if (left < right) nums[right] = nums[left]; } //基准数放到合适的位置 nums[left] = pivot; return left; }
快排写法很多,这里写的就是以一个元素为基准,找到它应该在位置(排好序后的位置),这个位置上的元素是对的,它右边的元素都比他大,左边的元素都比他小,然后对它左边和右边的也按照这个规则。最终每个元素都找到了自己的位置。 partition这个函数,就是为了给left这个位置的元素找到排序后的位置。 举个用快排思想的题目 BM47 寻找第K大 有一个整数数组,请你根据快速排序的思路,找出数组中第 k 大的数。 给定一个整数数组 a ,同时给定它的大小n和要找的 k ,请返回第 k 大的数(包括重复的元素,不用去重),保证答案存在。 要求:时间复杂度 O(nlogn)O(nlogn),空间复杂度 O(1)O(1)
public static int findKth(int[] a, int n, int K) { // write code here int res = quicksort(a,0,a.length-1,K); return res; } public static int quicksort(int []a ,int left , int right,int k){ if(left<right){ int id = partion(a,left,right); if(id==a.length-k)//如果这个位置正好是第k大的数的位置,直接返回。 return a[id]; if(id<a.length-k)//如果这个位置正好小于第k大的数的位置,只需要对它右边进行快排,因为右边的都比它大。 return quicksort(a,id+1,right,k); if(id>a.length-k)//同上 return quicksort(a,left,id-1,k); } return a[left]; } private static int partion(int[] a, int left, int right) { Random random = new Random(); int rand = random.nextInt(right-left+1)+left;//随机一个基准,可以避免在有序的情况下,快排会失效 int pivot = a[rand]; int temp = a[left]; a[left]=pivot; a[rand]=temp; while (left<right){ while (left<right && a[right]>=pivot) right--; if(left<right) a[left]=a[right]; while (left<right && a[left]<=pivot) left++; if(left<right) a[right]=a[left]; } a[left]=pivot; return left; }
主要会存在快排失效的问题,会导致个别测试用例不通过,所以要改进一下,基准不是以第一个为准,而是随机生成一个基准,然后和第一个位置交换,其他的和之前的一样。
上一篇:
Java基础知识总结(2021版)