美文网首页数据结构和算法分析
选择第k小元素(分治法)

选择第k小元素(分治法)

作者: 张的笔记本 | 来源:发表于2019-11-27 13:58 被阅读0次

1、伪码

image.png
原理视频:https://www.bilibili.com/video/av7134874?p=29
2、实现
typedef pair<int, int> pairs;
/*
 * 选择第k小元素
 */ 
int Select(vector<int> a, int k)//需要保证k的范围合理
{   
    int temp1 = a.size();
    vector<int>::iterator iter = a.begin();
    
    if(temp1 < 5){
        sort(iter, iter + temp1);
        return *(iter + k - 1);
    }
    
    int temp2, temp3, i, m, n, last, sdn, sxn/*大于或小于m的个数*/;
    vector<pairs> b;
    vector<pairs>::iterator iter1;
    vector<int> c, sd, sx;
    
    n = temp1 / 5;
    last = temp1 % 5;//不是5的倍数
    
    for(i = 0; i < n; ++i){
        temp2 = i * 5;
        sort(iter + temp2, iter + temp2 + 5);
        b.push_back(make_pair(*(iter + temp2 + 2), i + 1));
    }
    
    /*
    for_each(a.begin(), a.end(), Show);
    cout<<endl;
    for(vector<pairs>::iterator m = b.begin(); m != b.end(); ++m){
        cout<<"("<<m -> first<<","<<m -> second<<")";
    }
    cout<<endl;
    */
    
    for(iter1 = b.begin();iter1 != b.end(); ++iter1)
        c.push_back(iter1 -> first);
    m = Select(c, b.size() / 2 + 1);
    
    //cout<<m<<endl;
    
    (n % 2) ? (sdn = sxn = (n / 2 + 1) * 3 - 1) : (sxn = (n / 2 + 1) * 3 - 1, sdn = n / 2 * 3 - 1);

    //处理不能整除5而剩余的元素
    for(i = 0, iter = a.end() - 1; i < last; ++i){
        if(*(iter - i) >= m){
            ++sdn;
            sd.push_back(*(iter - i));
        }
        else{
            ++sxn;
            sx.push_back(*(iter - i));
        }
    }
    
    
    for(iter1 = b.begin(); iter1 != b.end(); ++iter1){
        temp3 = ((iter1 -> second) - 1) * 5 + 2;
        iter = a.begin() + temp3;
        if(iter1 -> first < m){
            sx.push_back(*iter);sx.push_back(*(iter - 1));sx.push_back(*(iter - 2));
            for(i = 1; i <= 2; ++i){
                if(*(iter + i) >= m){
                    ++sdn;
                    sd.push_back(*(iter + i));
                }
                else{
                    ++sxn;
                    sx.push_back(*(iter + i));
                }
            }
        }
        else if(iter1 -> first == m){
            sx.push_back(*(iter - 1));sx.push_back(*(iter - 2));
            sd.push_back(*(iter + 1));sd.push_back(*(iter + 2));
        }
        else{
            sd.push_back(*iter);sd.push_back(*(iter + 1));sd.push_back(*(iter + 2));
            for(i = -2; i <= -1; ++i){
                if(*(iter + i) >= m){
                    ++sdn;
                    sd.push_back(*(iter + i));
                }
                else{
                    ++sxn;
                    sx.push_back(*(iter + i));
                }
            }
        }
    }
    
    /*
    cout<<sdn<<endl;
    for_each(sd.begin(), sd.end(), Show);
    cout<<endl;
    cout<<sxn<<endl;
    for_each(sx.begin(), sx.end(), Show);
    cout<<endl;
    */
    if(k <= sxn)
        return Select(sx, k);
    else if(k == sxn + 1)
        return m;
    else
        return Select(sd, k - sxn - 1);
}

原理参见 屈婉玲老师 算法设计与分析 ORZ

相关文章

  • 选择第k小元素(分治法)

    1、伪码 原理参见 屈婉玲老师 算法设计与分析 ORZ

  • 寻找第 k 小元素-分治法

    问题 对一个已经序列A[1,...,n],如何寻找其第k小的元素? 算法 使它在O(n)的时间复杂度内解决 code

  • 算法习题

    4 递归与分治 选择问题 例4.9 查找第k个小/大元素 n个元素,元素划分n/5(不带余数),每组五个元素,不足...

  • Leetcode简略题解

    LC23 合并k个有序链表 分治法 暴力k个指向k个链表头的指针找最小值O(KN) -> 维护k个元素的最小堆 O...

  • 2018-07-03

    线性时间选择 给定线性序集中n个元素和一个整数k,1<=k<=n,要求找出这n个元素中第k小的元素,即如果将这n个...

  • 分治法求第k大元

    核心是类似于快速排序的划分过程代码如下: 我在该段过程浪费了很多时间: 之前我写成了 理解成是右边数组的第k-i-...

  • leetcode-合并K个排序链表

    思路: 首先解决两个链表的合并: 利用分治法解决K个链表的排序: 如果使用非递归版本的分治法,可以这样做:

  • C语言实现用分治法找出第k小元素的算法

  • 快速排序和寻找第k小元素

    搞了一晚上寻找第k小元素,终于弄出来了,下面的代码,我测试的是没有问题的。这思想完美体现了快速排序的思想,分治,又...

  • [LeetCode](week2) 23. Merge k So

    这周课是讲分治法,那就来做一题分治类型的Hard题目 题目描述 Merge k sorted linked lis...

网友评论

    本文标题:选择第k小元素(分治法)

    本文链接:https://www.haomeiwen.com/subject/shspwctx.html