编程之美 - 满足条件的两个数字及扩展问题

问题描述: 对应函数 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;
}




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