分治算法——二分法寻找第n小元素(附完整代码)

问题分析

寻找第n小元素可以由多种方式实现,但是利用分治算法可以高效求解。

算法解析

每次递归锁定首元素到末尾元素之间的中位数,然后进行顺序调整,使得中位数左边元素都小于中位数;中位数右边的元素都大于中位数。然后根据n的值去判断后续应该搜索左半部分元素还是右半部分元素,不断递归调用,最终最后锁定的中位数即为第n小元素。
①初始化
h,t分别为用来遍历的头下标和尾下标,midIndex为中位数的下标,mid储存中位数的值。

		int h=head;
        int t=tail;
        int midIndex = (h+t)/2;//每次选择头到尾之间元素的中位数mid
        int mid = dataArray[midIndex];

②调整中位数左右两边元素
1)从左向右遍历左边的元素,直到找到比中位数大或者相等的元素。

			while (dataArray[h]<mid){
                h++;//找到mid左边比其大的数
            }

2)从右向左遍历右边的元素,直到找到比中位数小或者相等的元素。

			while (dataArray[t]>mid){
                t--;//找到mid右边比其小的数
            }

3)将两侧找到的元素交换顺序,同时如果出现中位数被换顺序,要将中位数的下标也进行调整。

	if(h<=t){
                //交换找到的数
                int tmp=0;
                tmp = dataArray[h];
                dataArray[h] =dataArray[t];
                dataArray[t] =tmp;

                //当左右下标移动到中间值mid上时,在交换数字同时,也要把下标换到正确位置。
                if(midIndex==h){
                    t = midIndex;
                }
                else if(midIndex == t){
                    h = midIndex;
                }
                
                //这里是为了能够跳出最外层循环,避免形成死循环,也影响到了后面的递归判断。
                h++;
                t--;
            }

③判断第n小元素方位,进行递归调用
如果第n小元素在左半部分就遍历左半部分元素;如果在右半部分就遍历右半部分元素

		//h与t将整个数组分为两块,左边为小于等于目标值的元素,右边为大于等于目标值的元素。
        //并且h与t分别对应了两部分相邻两元素的下标,t为左部分的末尾元素下标,h为右部分的首元素下标。
        if(n<=t){
            //如果n在左侧就递归左部分继续寻找
            return findNMin(head,t,n);
        }
        else if(n>=h){
            //如果n在右侧就递归右部分继续寻找
            return findNMin(h,tail,n);
        }
       else{
           //如果第一轮的中位数就是第n小元素直接结束
            return dataArray[n];
       }

④结果展示
在这里插入图片描述

完整代码

package com.algorithm.day1;
import java.util.Arrays;
import java.util.Scanner;
import java.util.Vector;

public class KeyWord{
    public int [] dataArray =new int[50];

    public int key = 0;
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        KeyWord keyWord =new KeyWord();
        System.out.println("输入数组元素个数");
        int numberCount = scanner.nextInt();
        System.out.println("请输入n");
        int n= scanner.nextInt();
        for(int i=1;i<=numberCount;i++){
            keyWord.dataArray[i] = scanner.nextInt();
        }
        System.out.println("第"+n+"小的数字是"+ keyWord.findNMin(1,numberCount,n));
    }

    public  findNMin(int head, int tail, int n) {
        int h=head;
        int t=tail;
        int midIndex = (h+t)/2;//每次选择头到尾之间元素的中位数mid
        int mid = dataArray[midIndex];
        while(h<=t){//h大于t时表示完成了,使mid左边为比它大的数,右边为比它小的数。
            while (dataArray[h]<mid){
                h++;//找到mid左边比其大的数
            }
            while (dataArray[t]>mid){
                t--;//找到mid右边比其小的数
            }

            if(h<=t){
                //交换找到的数
                int tmp=0;
                tmp = dataArray[h];
                dataArray[h] =dataArray[t];
                dataArray[t] =tmp;

                //当左右下标移动到中间值mid上时,在交换数字同时,也要把下标换到正确位置。
                if(midIndex==h){
                    t = midIndex;
                }
                else if(midIndex == t){
                    h = midIndex;
                }
                h++;
                t--;
            }
        }

        //h与t将整个数组分为两块,左边为小于等于目标值的元素,右边为大于等于目标值的元素。
        //并且h与t分别对应了两部分相邻两元素的下标,t为左部分的末尾元素下标,h为右部分的首元素下标。
        if(n<=t){
            //如果n在左侧就递归左部分继续寻找
            return findNMin(head,t,n);
        }
        else if(n>=h){
            //如果n在右侧就递归右部分继续寻找
            return findNMin(h,tail,n);
        }
       else{
           //如果锁定中位数直接返回值
            return dataArray[n];
       }
    }
}

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

freezing?

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值