Linear time selection of algorithm design and analysis (C++)

Linear time selection algorithm

  • Imitating quick sort algorithm
  • Use divide and conquer strategy on arrays

Example one

Problem Description

For a given n-element array a[0:n-1], it is required to find the k-th smallest element from it

Input: Input multiple sets of test cases.
 There are 2 rows for each test case. The
 first row is integers n and k (1≤k<n≤1000), and the
 second row is n integers.

Output: the k-th smallest element

problem analysis

We know that the idea of ​​a sort of the quick sort algorithm is:
 find a number as the standard, put the smaller number on the left, and the larger number on the right

To find the k-th smallest element, the most rude way is to sort all of them, but this has done a lot of extra work. Drawing on the one-time sorting idea of ​​the quick sort algorithm, we can use the first element of the array as a standard, and put the ones smaller than it on the left. Place larger than it on the right:

  • When the element on the left side of this standard and it add up to k, the k-th smallest number is found
  • When the element on the left side of this standard and it add up to less than k, then continue to the right to find the smallest number (k-1-subscript of the number)
  • When the element on the left of this standard and it add up to greater than k, continue to the left to find the k-th smallest number

Algorithm implementation

#include <iostream>
#include <algorithm>
#define N 100
using namespace std;
//一维数组容器
int a[N];

//线性选择算法寻找第k小的元素
int linearTimeSelection(int,int,int);

int main()
{
    
    
    int n,k;
    cout<<"输入数组大小:";
    cin>>n;
    if(n>N || n<1) {
    
    
        cout<<"预留空间不足或数组大小非法!";
        exit(0);
    }

    cout<<"输入数组元素:";
    for(int i=0;i<n;i++) cin>>a[i];

    cout<<"查找第几小的元素:";
    cin>>k;
    if(k > n || k < 1){
    
    
        cout<<"查找位置非法!";
        exit(0);
    }
    cout<<linearTimeSelection(0,n-1,k);
    return 0;
}
/*
    left 进行线性选择的首位下标
    right 进行线性选择的末尾下标
    k 寻找第k位小的元素
*/
int linearTimeSelection(int left,int right,int k){
    
    
    if(left >= right) return a[left];
    int point = a[left];
    int i = left,
        j = right+1;

    while(1){
    
    
        do{
    
    i++;}while(a[i] < point);
        do{
    
    j--;}while(a[j] > point);
        if(i>=j) break;
        swap(a[i],a[j]);
    }

    if(j-left+1 == k) return point;
    a[left] = a[j];
    a[j] = point;

    if(j-left+1 < k) return linearTimeSelection(j+1,right,k-(j+1-left));	//向右找
    return linearTimeSelection(left,j-1,k);	//向左找
}

Example 2

Problem Description

  An oil company plans to build a main oil pipeline from east to west. The pipeline passes through an oil field with n oil wells. From each oil well, there must be an oil pipeline connected to the main pipeline along the shortest path (or south or north).
  Given the location of n oil wells, that is, their x-coordinates (east-west) and y-coordinates (south-north), the program calculates the sum of the minimum length of the oil pipeline from each oil well to the main pipeline.

Input the
  first line is an integer n, indicating the number of oil wells (1≤n≤10 000) The
  next n lines are the positions of the oil wells, each line contains two integers x and y (-10 000≤x, y≤10 000)
Output
  the sum of the minimum length of the oil pipeline from each oil well to the main pipeline

Input example
5
1 2
2 2
1 3
3 -2
3 3
Output example
6

Sample diagram
Insert picture description here

problem analysis

  • How to determine the location of the main oil pipeline?
    From the analysis diagram I drew on the input sample above, it can be clearly seen that the main pipe is only determined by the y coordinate, and the main pipe exists in the range of the y value (that is, the maximum and minimum values ​​of the input y coordinate Between), because the distance between the oil well and the main pipeline is to be found to be the smallest, so find the median of the y value of the oil well location .
  • How to calculate the minimum distance sum?
    After finding the location of the main pipeline, we calculate the distance to the main pipeline for each oil well and add them up.
  • Regarding the median calculation
    1. Direct sorting, find the element with the n/2 subscript;
    2. Use the linear time selection algorithm to select the n/2-th smallest element; (we use this method)

Algorithm implementation

#include <iostream>
#include <algorithm>
#define N 10000
using namespace std;

//存储油井的y值
int a[N];
//线性时间选择算法
int linearTimeSelection(int,int,int);
int main()
{
    
    
    int n,temp;
    cout<<"请输入油井的数量:";
    cin>>n;
    cout<<"请输入油井坐标:";
    for(int i=0;i<n;i++)
        cin>>temp>>a[i];
    //主管道位置
    int mid = linearTimeSelection(0,n-1,n/2);

    int sum = 0;
    for(int i=0;i<n;i++){
    
    
        sum += abs(a[i]-mid);
    }

    cout<<sum<<endl;
    return 0;
}

int linearTimeSelection(int left,int right,int k){
    
    
    if(left >= right) return a[left];
    int i = left,
        j = right+1;
    int point = a[left];

    while(1){
    
    
        do{
    
    i++;}while(a[i]<point);
        do{
    
    j--;}while(a[j]>point);
        if(i>=j) break;
        swap(a[i],a[j]);
    }

    if(j-left+1 == k) return point;
    a[left] = a[j];
    a[j] = point;

    if(j-left+1 < k) return linearTimeSelection(j+1,right,k-(j-left+1));
    return linearTimeSelection(left,j-1,k);
}

Recommended by other articles in this blog

Divide and conquer strategy exercises for algorithm design and analysis (part 2)

Divide and conquer strategy exercises for algorithm design and analysis (on)

Divide and conquer strategy for algorithm design and analysis

Algorithm design and analysis of recursive algorithm exercises (part 2)

Algorithm design and analysis of recursive algorithm exercises (on)

Guess you like

Origin blog.csdn.net/L333333333/article/details/102646289