文章目录
- 二分查找
- 顺序查找
- 二分查找迭代写法
- 二分查找递归写法
- 元素中有重复元素的二分查找
- 在排序数组中查找元素的第一个和最后一个位置
- 山脉数组的峰顶索引
- 旋转数字的最小数字
- 找缺失数字
- 优化求平方根
- 二叉搜索树中搜索指定值
- 验证二叉搜索树
- 有序数组转化为二叉搜索树
- 快速排序
- 以第一个元素为基准实现快速排序
- 以最后一个元素为基准实现快速排序
- 以中间元素为基准实现快速排序
- 归并排序
- 归并排序
二分查找
顺序查找
逐个遍历,判断是否是待查找的元素
public int search(int[] array,int key){for(int i=0;i<array.length;i++){if(array[i]==key){return i;}}return -1;
}
二分查找迭代写法
有序数组可用,可作为模板记忆,注意边界
public int binarySearch(int[] array,int key,int low,int high){while (low<= high){int mid = low+((high-low)>>1);if(array[mid]==key){return mid;}else if(array[mid]>key){high = mid - 1;}else if(array[mid]<key){low = mid + 1;}}return -1;
}
二分查找递归写法
有序数组可用,可作为模板记忆,注意边界
public int binarySearch(int[] array,int key,int low,int high){if(low<=high){int mid = low+((high-low)>>1);if(array[mid]==key){return mid;}else if(array[mid]>key){return binarySearch(array,key,low,mid-1);}else if(array[mid]<key){return binarySearch(array,key,mid+1,high);}}return -1;
}
元素中有重复元素的二分查找
基于模板找到元素后,继续向前遍历,找到等于待查找元素在数组中首次出现的位置,如果元素过多,也可使用二分查找方式继续查找
public int binarySearchRe(int[] array, int key, int low, int high) {while (low <= high) {int mid = low + ((high - low) >> 1);if (array[mid] == key) {while (mid >= 0 && array[mid] == key) {mid--;}return mid + 1;} else if (array[mid] > key) {high = mid - 1;} else if (array[mid] < key) {low = mid + 1;}}return -1;
}
在排序数组中查找元素的第一个和最后一个位置
基于模板找到元素后,继续向前、后遍历,找到等于待查找元素在数组中首次出现的位置和最后出现的位置,如果元素过多,也可使用二分查找方式继续查找
public int[] searchRange(int[] nums, int target) {return binarySearch(nums,target,0,nums.length-1);
}public int[] binarySearch(int[] nums,int target,int low,int high){int[] res = new int[]{-1,-1};while(low<=high){int mid = low + ((high-low)>>1);if(nums[mid]==target){int left = mid;while(left>=0&&nums[left]==target){left--;}int right = mid;while(right<nums.length&&nums[right]==target){right++;}res[0] = left+1;res[1] = right-1;return res;}else if(nums[mid]>target){high = mid-1;}else if(nums[mid]<target){low = mid+1;}}return res;
}
山脉数组的峰顶索引
注意山脉的判断条件,高于两侧数据,递增顺序在左侧,递减顺序在右侧
public int peakIndexInMountainArray(int[] arr) {int high = arr.length-2;int low = 1;while(low <= high){int mid = low+((high-low)>>1);if(arr[mid]>arr[mid-1] && arr[mid]>arr[mid+1]){return mid;}else if(arr[mid]>arr[mid-1] && arr[mid]<arr[mid+1]){low = mid+1;}else if(arr[mid]<arr[mid-1] && arr[mid]>arr[mid+1]){high = mid - 1;}}return -1;
}
旋转数字的最小数字
使用二分查找模板,边界值通过测试样例确定
public int findMin(int[] nums) {int low = 0;int high = nums.length - 1;while(low<high){int mid = low+((high-low)>>1);if(nums[mid]>nums[high]){low = mid+1;}else if(nums[mid]<nums[high]){high = mid;}}return nums[low];
}
找缺失数字
使用二分查找模板,边界值通过测试样例确定
public int missingNumber(int[] array){int high = array.length;int low = 0;while (low<=high){int mid = low + ((high - low)>>1);if(array[mid] == mid){low = mid+1;}else{high = mid - 1;}}return low;
}
优化求平方根
使用二分查找模板,边界值通过测试样例确定
public int mySqrt(int x) {int low = 1;int high = x;while(low <= high){int num = low + ((high-low)>>1);if(x/num == num){return num;}else if(x/num>num){low = num + 1;}else{high = num - 1;}}return high;
}
二叉搜索树中搜索指定值
二分查找与二叉树的结合,先判断根节点,根据根节点与待查找值的情况判断在左子树或者右子树查找
public TreeNode searchBST(TreeNode root, int val) {if(root==null){return null;}else if(root.val == val){return root;}else if(root.val<val){return searchBST(root.right,val);}else if(root.val>val){return searchBST(root.left,val);}return null;
}
验证二叉搜索树
限定low和high两个范围进行验证,验证左右子树时,根据根节点的值更新low和high
public boolean isValidBST(TreeNode root) {long low = Long.MIN_VALUE;long high = Long.MAX_VALUE;return isValidBST(root,low,high);
}public boolean isValidBST(TreeNode root,long low,long high){if(root==null){return true;}if(root.val<=low || root.val >=high){return false;}return isValidBST(root.left,low,root.val)&&isValidBST(root.right,root.val,high);
}
有序数组转化为二叉搜索树
每次选择中间值作为根节点,再通过左右两个序列创建左右子树
public TreeNode sortedArrayToBST(int[] nums) {return sortedArrayToBST(nums,0,nums.length-1);
}public TreeNode sortedArrayToBST(int[] nums,int left,int right){if(left>right){return null;}int mid = left+((right-left)>>1);TreeNode root = new TreeNode(nums[mid]);root.left = sortedArrayToBST(nums,left,mid-1);root.right = sortedArrayToBST(nums,mid+1,right);return root;
}
快速排序
以第一个元素为基准实现快速排序
快速排序模板1
public void quickSort(int[] array, int left, int right) {if(left<right){int pivot = array[left];int i = right + 1;for (int j = right; j > left; j++) {if (array[j] > pivot) {i--;int temp = array[j];array[j] = array[i];array[i] = temp;}}int pivotIndex = i - 1;int temp = array[left];array[left] = array[pivotIndex];array[pivotIndex] = temp;quickSort(array,left,pivotIndex-1);quickSort(array,pivotIndex+1,right);}
}
以最后一个元素为基准实现快速排序
快速排序模板2
public void quickSort(int[] array, int left, int right) {if (left < right) {int pivot = array[right];int i = left - 1;for (int j = left; j < right; j++) {if (array[j] < pivot) {i++;int temp = array[i];array[i] = array[j];array[j] = temp;}}int pivotIndex = i + 1;int temp = array[pivotIndex];array[pivotIndex] = array[right];array[right] = temp;quickSort(array, left, pivotIndex - 1);quickSort(array, pivotIndex + 1, right);}
}
以中间元素为基准实现快速排序
快速排序模板3
public static void quickSort(int[] array, int start, int end) {if (start >= end) {return;}int left = start;int right = end;int mid = (left + right) / 2;int pivot = array[mid];while (left <= right) {while (left <= right && array[left] < pivot) {left++;}while (left <= right && array[right] > pivot) {right--;}if (left <= right) {int temp = array[left];array[left] = array[right];array[right] = temp;left++;right--;}}quickSort(array, start, right);quickSort(array, left, end);
}
归并排序
归并排序
归并排序模板
public void mergeSort(int[] array, int start, int end, int[] temp) {//2.直至每个序列只包含一个元素,停止划分if (start >= end) {return;}//1.从中间开始,每次划分为两个序列mergeSort(array, start, (start + end) / 2, temp);mergeSort(array, (start + end) / 2 + 1, end, temp);//3。进行有序数组的合并merge(array, start, end, temp);
}public void merge(int[] array, int start, int end, int[] temp) {//找到序列中点int mid = (start + end) / 2;//left遍历左边的序列int left = start;//right遍历右边的序列int right = mid + 1;//index遍历临时数组,存储合并结果int index = 0;//两个序列均从起点到终点进行遍历while (left <= mid && right <= end) {//将两个序列中较小的元素放入临时数组中if (array[left] < array[right]) {temp[index++] =array[left++];}else {temp[index++] =array[right++];}}//此时仅剩一个序列未遍历结束,直接赋值while (left <= mid){temp[index++] =array[left++];}while (right<=end){temp[index++] =array[right++];}//将归并的结果拷贝到原数组for (int i=start;i<=end;i++){array[i] = temp[i];}
}
数组中第K大的数的问题可以通过数组排序解决,根据题目中给定的时间、空间复杂福选择合适的排序算法