• 算法导论9.37习题解答


    CLRS 9.3-7 :

    给出一个O(n)时间的算法,在给定一个有n个不同数字的集合S以及一个正整数k<=n后,它能确定出S中最接近其中位数的k个数。

    算法思想:
    1.找到数组a中第n/2小的数median;
    2.对a中非median数进行|a[i] - median|,得到一个大小为n - 1的数组distance;
    3.寻找distance中第k小的数值;
    4.对distance进行一次遍历,找到小于等于k的数,从而对应得到数组a中的k个数。

    上述每一步的时间复杂度都为O(n),因而最后总的时间复杂度为O(n).

    #include <iostream>
    #include
    <time.h>
    using namespace std;
    //随机化分割
    int randomized_partition(int* a, int p, int r);
    int randomized_select(int* a, int p, int r, int i);
    int main()
    {
      const int LEN =12;
      int arr[LEN] = { 5, 7, 10, 3, 6, 2, 8, 9, 4, 1, 11 , 12};
      int median = randomized_select(arr, 0, LEN -1, (LEN -1)/2);
      int distance[LEN -1];
      int distance_cpy[LEN -1];

      int temp =0;
      int middle;
      for(int i =0; i < LEN; i++)
      {
        if(arr[i] != median)
          distance[temp
    ++] = abs(arr[i] - median);
        else
          middle
    = i;
      }
      for(int i =0; i < LEN -1; i++)
        distance_cpy[i]
    = distance[i];
      int k;
      while(true)
      {
        cout
    <<"输入k:"<<endl;
        cin
    >>k;
        cout
    <<"k邻近值为:"<<endl;
        int kth_value = randomized_select(distance_cpy, 0, LEN -2, k -1);
        int* k_arr =newint[k];
        int j =0;
        //这里要注意,比如中间值为6,那么k = 3,有5,7明显符合要求,他们最近,4,8也符合要求,那么在这选择谁
        if(k%2)
        {
          bool flag =true;
          for(int i =0; i < LEN -1; i++)
          {
            if(distance[i] < kth_value)
            {
              if(i < middle)
                k_arr[j
    ++] = median - distance[i];
              else
                k_arr[j
    ++] = median + distance[i];
            }
            else if(distance[i] == kth_value && flag)
            {
              if(i < middle)
                k_arr[j
    ++] = median - distance[i];
              else
                k_arr[j
    ++] = median + distance[i];
              flag
    =false;
            }
          }
        }
        else
        {
          for(int i =0; i < LEN -1; i++)
          {
            if(distance[i] <= kth_value)
            {
              if(i < middle)
                k_arr[j
    ++] = median - distance[i];
              else
                k_arr[j
    ++] = median + distance[i];
            }
          }
        }
        for(int i =0; i < k; i++)
        cout
    <<k_arr[i]<<"\t";
        cout
    <<endl;
        delete[] k_arr;
      }
    }
    //下标为[p, r]之间的元素
    int randomized_partition(int* a, int p, int r)
    {
      srand(time(NULL));
      int q = rand()%(r - p +1) + p;
      int temp = a[q];
      a[q]
    = a[r];
      a[r]
    = temp;
      int j = p;
      for(int i = p; i < r; i++)
      {
        if(a[i] < a[r])
        {
          if(i != j)
          {
            int temp2 = a[i];
            a[i]
    = a[j];
            a[j]
    = temp2;
          }
          j
    ++;
        }
      }

      temp
    = a[j];
      a[j]
    = a[r];
      a[r]
    = temp;
      return j;
    }
    //迭代版本
    int randomized_select(int* a, int p, int r, int i)
    {
      int q = randomized_partition(a, p, r);
      while(p != r)
      {
        if(i == q)
          return a[q];
        else if(i < q)
        {
          r
    = q -1;
          q
    = randomized_partition(a, p, r);
        }
        else
        {
          p
    = q +1;
          q
    = randomized_partition(a, p, r);
        }
      }
      return a[p];
    }
  • 相关阅读:
    CCF NOI1006 捡石头
    POJ NOI MATH-7648 蓄水池水管问题
    CCF NOI1005 存款收益
    CCF NOI1004 填充矩形
    CCF NOI1003 猜数游戏
    CCF NOI1002 三角形
    Project Euler Problem 26 Reciprocal cycles
    HDU1799 循环多少次?
    CCF NOI1001 温度转换
    POJ NOI MATH-7647 余数相同问题
  • 原文地址:https://www.cnblogs.com/null00/p/2065064.html
Copyright © 2020-2023  润新知