• 算法必刷系列之查找、排序


    二分查找

    顺序查找

    逐个遍历,判断是否是待查找的元素

    public int search(int[] array,int key){
        for(int i=0;i<array.length;i++){
            if(array[i]==key){
                return i;
            }
        }
        return -1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    二分查找迭代写法

    有序数组可用,可作为模板记忆,注意边界

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    二分查找递归写法

    有序数组可用,可作为模板记忆,注意边界

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    元素中有重复元素的二分查找

    基于模板找到元素后,继续向前遍历,找到等于待查找元素在数组中首次出现的位置,如果元素过多,也可使用二分查找方式继续查找

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在排序数组中查找元素的第一个和最后一个位置

    基于模板找到元素后,继续向前、后遍历,找到等于待查找元素在数组中首次出现的位置和最后出现的位置,如果元素过多,也可使用二分查找方式继续查找

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    山脉数组的峰顶索引

    注意山脉的判断条件,高于两侧数据,递增顺序在左侧,递减顺序在右侧

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    旋转数字的最小数字

    使用二分查找模板,边界值通过测试样例确定

    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];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    找缺失数字

    使用二分查找模板,边界值通过测试样例确定

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    优化求平方根

    使用二分查找模板,边界值通过测试样例确定

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    二叉搜索树中搜索指定值

    二分查找与二叉树的结合,先判断根节点,根据根节点与待查找值的情况判断在左子树或者右子树查找

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    验证二叉搜索树

    限定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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    有序数组转化为二叉搜索树

    每次选择中间值作为根节点,再通过左右两个序列创建左右子树

    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    快速排序

    以第一个元素为基准实现快速排序

    快速排序模板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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    以最后一个元素为基准实现快速排序

    快速排序模板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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    以中间元素为基准实现快速排序

    快速排序模板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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    归并排序

    归并排序

    归并排序模板

    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];
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    数组中第K大的数的问题可以通过数组排序解决,根据题目中给定的时间、空间复杂福选择合适的排序算法

  • 相关阅读:
    idea Springboot在线商城系统VS开发mysql数据库web结构java编程计算机网页源码maven项目
    赶紧收藏!2024 年最常见 20道 Kafka面试题(三)
    商城小程序系统,商城源码
    Java泛型
    Redis Twemproxy 集群规范部署手册
    【学习笔记】各类基于决策单调性的dp优化
    UML类图简单认识
    【Robotframework+python】实现http接口自动化测试
    Supervisor进程管理
    猿创征文|前端进阶必备——WebSockt实现聊天室(附源码)
  • 原文地址:https://blog.csdn.net/m0_45362454/article/details/133931536