数组------寻找和为定值的两个数

题目描述:
给定一个数组和一个整数,要求在数组中找到两个数,使得它们的和为这个整数.
方法:排序夹逼
首先使用快速排序算法把数组按升序排列,然后使用夹逼的方法找到答案.即使用两个指针分别指向数组的头和尾(begin, end).
1. 若arr[begin] + arr[end] == sum 就输出;
2. 若arr[begin] + arr[end] < sum 代表两数的和偏小需要增大,则begin++;
3. 若arr[begin] + arr[end] > sum 代表两数之和偏大需要减小,则end–;

#include <iostream>
using namespace std;

#define MIN 5

void quickSort(int *arr, int first, int last);
int  partition(int *arr, int first, int last);
void insertSort(int *arr, int first, int last);
void sortFirstMidLast(int *arr, int first, int mid, int last);
void twoSum(int *arr, int length, int sum);

int main()
{
    int array[] = {
        -38, 38, -963, 658, 963, 56. 86, -86, -456, 82, 456, 89, -36, 489, -489, 56, 25, 0. -52, 258, 63, -63, 9, 1
    };

    quickSort(array, 0, sizeof(array)/sizeof(int) - 1);
    twoSum(array, sizeof(array)/sizeof(int), 0);

    return 0;
}

void quickSort(int *arr, int first, int last)
{
    if(last - first + 1 <= MIN)     //当剩余部分长度小于MIN时,直接使用插入排序
    {
        insertSort(arr, first, last);
    }
    else
    {
        int index = partition(arr, first, last);
        quickSort(arr, first, index - 1);
        quickSort(arr, index + 1, last);
    }
}

void insertSort(int *arr, int first, int last)
{
    for(int un = first + 1; un <= last; un++)
    {
        int tmp = arr[un];
        int local = un;
        while(local > 0 && arr[local - 1] > tmp)
        {
            arr[local] = arr[local - 1];
            local--;
        }
        arr[local] = tmp;
    }
}

int partition(int *arr, int first, int last)
{
    int mid = first + (last - first) / 2;
    sortFirtstMidLast(arr, first, mid, last);
    swap(arr[mid], arr[last - 1]);

    int index = last - 1;
    int value = arr[index];
    int leftIndex = first + 1;
    int rightIndex = last - 2;
    bool done = true;

    while(done)
    {
        while(arr[leftIndex] < value)
            leftIndex += 1;
        while(arr[rightIndex] > value)
            rightIndex -= 1;
        if(leftIndex < rightIndex)
        {
            swap(arr[leftIndex], arr[rightIndex]);
            leftIndex += 1;
            rightIndex -= 1;
        }
        else
        {
            done = false;
        }
    }
    swap(arr[index], arr[leftIndex]);
    index = leftIndex;
    return index;
}

void sortFirstMidLast(int *arr, int first, int mid, int last)
{
    if(arr[first] > arr[mid]) 
        swap(arr[first], arr[mid]);
    if(arr[mid] > arr[last]) 
        swap(arr[mid], arr[last]);
    if(arr[first] > arr[mid]) 
        swap(arr[first], arr[mid]);
}

void twoSum(int *arr, int length, int sum)
{
    int begin = 0;
    int end = length - 1;

    while(begin < end)
    {
        if(arr[begin] + arr[end] == sum)
        {
            cout << arr[begin] << "\t" << arr[end] << endl;
            begin += 1;
            end -= 1;
        }
        else if(arr[begin] + arr[end] < sum)
        {
            begin += 1;
        }
        else 
        {
            end -= 1;
        }
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
解题思路: 首先,中位数的定义是将一组数据按照从小到大(或从大到小)排序后,处于中间位置的那个数。因此,对于这道题,我们需要将个已排好序的数组合并为一个有序数组,然后找出这个有序数组的中位数。 最简单的方法是将个数组合并为一个有序数组,然后直接找出中位数。但是,这种方法的时间复杂度是 O(n),不符合题目要求。因此,我们需要采用分治策略来解决这个问题。 具体地,我们可以采用类似于归并排序的方法。将 X 和 Y 分别分成段,分别为 X1, X2 和 Y1, Y2。然后比较 X1 和 Y1 的中位数,设为 m1,比较 X2 和 Y2 的中位数,设为 m2。如果 m1 = m2,则 m1 和 m2 就是整个数组的中位数。如果 m1 < m2,则中位数一定在 X2 和 Y1 中,我们可以继续在 X2 和 Y1 中递归地寻找中位数。如果 m1 > m2,则中位数一定在 X1 和 Y2 中,我们可以继续在 X1 和 Y2 中递归地寻找中位数。递归的终止条件是数组长度为 1 或 2。 代码实现: ```c #include <stdio.h> int findMedian(int X[], int Y[], int n) { if (n == 1) { return X[0] < Y[0] ? X[0] : Y[0]; } else if (n == 2) { int a = X[0] < Y[0] ? X[0] : Y[0]; int b = X[1] > Y[1] ? X[1] : Y[1]; return (a + b) / 2; } int m1 = X[n/2]; int m2 = Y[n/2]; if (m1 == m2) { return m1; } else if (m1 < m2) { return findMedian(X + n/2, Y, n - n/2); } else { return findMedian(X, Y + n/2, n - n/2); } } int main() { int X[] = {1, 3, 5, 7, 9}; int Y[] = {2, 4, 6, 8, 10}; int n = sizeof(X) / sizeof(X[0]); int median = findMedian(X, Y, n); printf("The median is %d\n", median); return 0; } ``` 代码解释: 函数 `findMedian` 接受三个参数:个已排好序的数组 X 和 Y,以及数组长度 n。函数的返回值是这个数组的中位数。 如果数组长度为 1,直接返回 X 和 Y 中较小的那个数作为中位数。 如果数组长度为 2,找出 X 和 Y 中各自的最大值和最小值,然后计算它们的平均值作为中位数。 如果数组长度大于 2,找出 X 和 Y 中间的个数 m1 和 m2,如果 m1 = m2,则它们就是整个数组的中位数。否则,如果 m1 < m2,则中位数一定在 X2 和 Y1 中,我们可以继续在 X2 和 Y1 中递归地寻找中位数。如果 m1 > m2,则中位数一定在 X1 和 Y2 中,我们可以继续在 X1 和 Y2 中递归地寻找中位数。递归的终止条件是数组长度为 1 或 2。 在 `main` 函数中,我们定义了个已排好序的数组 X 和 Y,以及数组长度 n。然后调用 `findMedian` 函数来寻找个数组的中位数,并打印出结果。 测试结果: ``` The median is 5 ``` 时间复杂度分析: 由于每次递归都将数组长度减半,因此递归深度为 O(log n)。在每一层递归中,我们需要比较个数组中间的个数,因此时间复杂度为 O(1)。因此,总的时间复杂度为 O(log n)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值