編程之美 - 滿足條件的兩個數字及擴展問題

問題描述: 對應函數 find_two
快速找出數組中的兩個數字,讓這兩個數字之和等於給定的數字。

想法:
如果把任意兩個數字組合進行嘗試的話,運算量是N*N不適合。
先將數組進行排序,然後從兩頭分別取數字進行組合,如果和大於目標數字則在大數字側找下一個稍小一點的數字。
如果和小於目標數字則在小數字側找下一個稍大一點的數字

擴展問題 1:  對應函數 find_three
快速找出數組中的三個數字,讓這兩個數字之和等於給定的數字。

擴展問題 2:  對應函數 find_three_near
快速找出數組中的三個數字,讓這兩個數字之和等於給定的數字或找到最接近的解。

想法:
想法與找兩個數字類似,先找到一大一小的兩個終點,然後用遊標在這兩個終點間進行遍歷,尋找第三個數,使他們的和接近或等於目標數字。


#include <iostream>
#include <vector>

using namespace std;

void swap(int &a, int &b)
{
    int tmp = 0;
    tmp = a;
    a = b;
    b = tmp;
}

void quick_sort(int* parr, int lpos, int rpos)
{
    int mid_pos = (lpos + rpos)/2;
    int mid_val = parr[mid_pos];
    int i = lpos, j = rpos;

    if (lpos >= rpos)
        return;

    while (i < j)
    {
        if ((parr[i] < mid_val) && (i < j))
        {
            i++;
        }

        if ((parr[j] > mid_val) && (i < j))
        {
            j--;
        }

        if (i < j)
        {
            swap(parr[i], parr[j]);
        }
    }
    mid_pos = j;
    quick_sort(parr, lpos, mid_pos);
    quick_sort(parr, mid_pos+1, rpos);
}

bool find_two(int arr[], int len, int num)
{
    int i = 0, j = len-1;
    bool result = false;

    quick_sort(arr, 0, len-1);

    while ((!result) && (i < j))
    {
        if ((arr[i] + arr[j]) == num)
            result = true;
        else if ((arr[i] + arr[j]) < num)
            i++;
        else
            j--;
    }
    if (result)
        cout << num << " = " << arr[i] << " + " << arr[j] << endl;
    else
        cout << "None" << endl;

    return result;
}

bool find_three(int arr[], int len, int num)
{
    int i = 0, j = len-1;
    bool bfound = false;
    int sum = 0, curr = 0;
    vector<int> list;

    if (len < 2)
        return false;

    quick_sort(arr, 0, len-1);

    // not found
    if ((arr[j-2] + arr[j-1] + arr[j] < num) || (arr[0] + arr[1] > num))
        return false;

    while ((j >= 0) && (arr[j] >= num))
        j--;

    if (j < 2)
        return false;

    while ((!bfound) && (i < j))
    {
        for (i = 0; i < j; i++)
        {
            sum = arr[i] + arr[j];
            curr = i + 1;
            while ((sum + arr[curr] < num) && (curr < j))
                curr++;

            if (sum + arr[curr] == num)
            {
                bfound = true;
                list.push_back(i);
                list.push_back(curr);
                list.push_back(j);
                break;
            }
        }
        j--;
    }

    if (bfound)
    {
        cout << num << " = " << arr[list[0]];
        for (i = 1; (size_t)i < list.size(); i++)
        {
            cout << " + " << arr[list[i]];
        }
        cout << endl;
    }
    else
        cout << "None" << endl;

    return bfound;
}


bool find_three_near(int arr[], int len, int num)
{
    int i = 0, j = len-1;
    bool bfound = false;
    int sum = 0, curr = 0, min = num;
    vector<int> list;

    if (len < 2)
        return false;

    quick_sort(arr, 0, len-1);

    // not found
    if ((arr[j-2] + arr[j-1] + arr[j] < num) || (arr[0] + arr[1] > num))
        return false;

    while ((j >= 0) && (arr[j] >= num))
        j--;

    if (j < 2)
        return false;

    while ((!bfound) && (j > 1))
    {
        for (i = 0; i < j; i++)
        {
            sum = arr[i] + arr[j];
            curr = i + 1;
            while ((sum + arr[curr] < num) && (curr < j))
                curr++;

            if (sum + arr[curr] == num)
            {
                bfound = true;
                list.clear();
                list.push_back(i);
                list.push_back(curr);
                list.push_back(j);
                break;
            }
            else if (min > abs((sum + arr[curr] - num)))
            {
                min = abs(sum + arr[curr] - num);
                list.clear();
                list.push_back(i);
                list.push_back(curr);
                list.push_back(j);
            }
        }
        j--;
    }

    if (!bfound)
        cout << "Not Found near value=" << min <<endl;

    cout << num << " = " << arr[list[0]];
    for (i = 1; (size_t)i < list.size(); i++)
    {
        cout << " + " << arr[list[i]];
    }
    cout << endl;

    return bfound;
}


void main()
{
    bool result = true;
    int test[] = {5, 12, 11, 6, 9, 21, 30};   int num = 50;  int limit = 3;
    int len = sizeof(test)/sizeof(test[0]);

    //int test[] = {5, 12, 11, 6, 9, 21, 30};   int num = 34;
    //int len = sizeof(test)/sizeof(test[0]);

    int test_near[] = {5, 12, 11, 6, 9, 21, 30};   int num_near = 52;
    int len_near = sizeof(test_near)/sizeof(test_near[0]);

    //find_two(test, len, num);

    //result = find_three(test, len, num);
    //if (!result)
    //    cout << "None" << endl;

    find_three_near(test_near, len_near, num_near);

    cin >> len;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章