南大算法設計與分析課程OJ答案代碼(1)中位數附近2k+1個數、任意兩數之和是否等於給定數


問題1

用來測試的,就不說了

問題2:中位數附近2k+1個數

給出一串整型數 a1,a2,...,a以及一個較小的常數 k,找出這串數的中位數 和最接近 的小於等於 的 k 個數,以及最接近 的大於等於 的 k 個數。將這 2k+1 個數按升序排序后輸出。

中位數定義:如果數串的大小是偶數 2j,中位數是從小到大排列的第 j 個數;如果數串的大小是奇數 2j+1,中位數是從小到大排列的第 j+1 個數。

輸入

第一行是 k 的值和數串的長度 n。

第二行是以空格隔開的 n 個整型數,最后一個數后面有空格。

輸出

按升序排列的 2k+1 個數,以空格分開,最后一個數后面沒有空格。結果可能出現重復的數。

思路

  這題如果直接排序再輸出是會超時的,排序算法的復雜度為nlgn,后來按照快排的思想做通過了。

  先以快排的思想找出中位數,復雜度為n(遞歸方程為T(n)=T(n/2)+n,用代入法就可以證明),(由於快排是隨機選取一個數做標准,所以我們在排完一次后需要判斷所選標准和中位數的差距,接着在子區間內繼續尋找中位數,選取到中位數后返回,具體看searchmid函數,應該寫得很簡潔了)

  按照快排的思想,我們已經將數組分為小於中位數的區間,中位數,大於中位數的區間。根據題目,所給的k很小,再根據選擇排序的思想在左右兩區間各選取k個數即可。

#include <iostream>
#include <vector>
#include <algorithm>
#include <limits.h>
using namespace std;

//使用快速排序的思路,找出中間數,first和last為區間,pos為要尋找有序狀態下的第幾個數
int searchmid(vector<int>& v,int first, int last, int pos) {
    int left = first;
    int key = last;
    for (int i = first; i <= last; ++i) {
        if (v[i] < v[key]) {
            swap(v[i], v[left]);
            left++;
        }
    }
    swap(v[left], v[key]);
    if (left < pos)
        return searchmid(v, left+1, last, pos);
    else if (left > pos)
        return searchmid(v,first,left-1,pos);
    return left;
}

int main()
{
    int k,length;
    cin >> k;
    cin >> length;
    vector<int> v(length,0);
    int pos = 0, num;
    while (cin >> num) {
        v[pos] = num;
        pos++;
    }

    /*int k = 0;
    vector<int> v = {34, 10,9,8,7,6,5,4,3,2,1,0};
    int length = v.size();*/

    vector<int> result;
    int index = searchmid(v, 0, length-1, length/2 - 1 + length%2);
    //在數組前一部分尋找k個小於等於v[index]的數
    for (int j = 0; j < k; ++j) {
        int max = INT_MIN;
        int max_pos;
        for (int i = 0; i < index-j; ++i) {
            if (v[i] > max) {
                max = v[i];
                max_pos = i;
            }
        }
        swap(v[max_pos],v[index-j-1]);
    }
    //在數組后一部分尋找k個大於等於v[index]的數
    for (int j = 0; j < k; ++j) {
        int min = INT_MAX;
        int min_pos;
        for (int i = index + j + 1; i < length; ++i) {
            if (v[i] < min) {
                min = v[i];
                min_pos = i;
            }
        }
        swap(v[min_pos],v[index+j+1]);
    }
    for (int i = index - k; i <= index + k; i++) {
        cout << v[i] ;
        if (i != index + k)
            cout << " ";
    }
    /*cout << endl;

    sort(v.begin(), v.end());
    for (auto h : v)
        cout << h << " ";
    cout << endl;

    system("pause");*/
    return 0;
}
View Code

 問題3:任意兩數之和是否等於給定數

題目描述

給定一個 int 數組 arr,元素按照升序排列且各不相同。另外有一個目標數 c,請你找出 arr 中所有的數對 a, b,使得 a + b = c。

輸入

輸入為三行,第一行為 arr 的元素個數,第二行為 arr,元素以空格分隔,第三行為目標數 c。

輸出

所有符合條件的數對 a, b。a 和 b 以空格分開,每個數對占據一行。每行中 a < b,所有數對以它的第一個數(也就是 a 的值)升序排列。

思路

直接遍歷判斷,符合條件的直接輸出就可以了。

int main()
{
    int length;
    int target;
    cin >> length;
    vector<int> v(length, 0);
    for (int i = 0; i < length; ++i)
        cin >> v[i];
    cin >> target;

    for (int i = 0; i < length;++i) {
        for (int j = i + 1; j < length; j++) {
            if (v[i] + v[j] == target) {
                cout << v[i];
                cout << " ";
                cout << v[j];
                cout << endl;
            }
        }
    }

    //system("pause");
    return 0;
}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM