1. 程式人生 > >和為s的兩個數字 【微軟面試100題 第十四題】

和為s的兩個數字 【微軟面試100題 第十四題】

題目要求:

  輸入一個遞增排序的陣列和一個數字s,在陣列中查詢兩個數,使得它們的和正好是s。如果有多對數字的和等於s,輸出任意一對即可。

  例如輸入陣列{1,2,4,7,11,15}和數字15.由於4+11=15,因此輸出4和11.

  參考資料:劍指offer第41題

題目分析:

  方法1 窮舉法:兩個for,時間複雜度O(n^2).

  方法2 二分查詢法:逐個遍歷選一個數,二分查詢選另一個數,時間複雜度O(nlogn).

  方法3 雙向掃描+臨時陣列法:先用輸入數字s依次減去原陣列a,組成一個新陣列b:14、13、11、8、4、0.然後從陣列a左邊開始,b右邊開始掃描,小的移動,直到兩個數相等,則找到。a中位置的數為第一個數,b中數的位置對應的a中位置的數為第二個數.

  方法4 hash法:先用陣列建立一個hash表。這樣,對於一個輸入數字,只用遍歷一遍陣列就可以找到是否有這樣的兩個數。時間複雜度O(N).空間複雜度O(N).

  方法5 雙向掃描:從兩端掃描,如果a[i]+a[j]>s,則j--,否則i++,如果最終找到a[i]+a[j] = s,則找到。

程式碼實現:

#include <iostream>

using namespace std;

typedef struct Pair
{
    int i,j;
}Pair;

Pair findSum(int *a, int n,int s);

int main(void)
{
    int a[] = {1,2,4,7,11,15};
    int n = sizeof(a)/sizeof(int);
    int s = 15;
    Pair res = findSum(a,n,s);
    if(res.i == -1)
        cout << "not find" << endl;
    else
        cout << "find it,and the first number is " << res.i << ",the second number is " << res.j <<endl;
    return 0;
}
//方法5實現
Pair findSum(int *a, int n,int s)
{
    //sort(s,s+n); 如果陣列非有序的,那就事先排好序 O(N*logN )
    int *begin=a;
    int *end=a+n-1;
    Pair TwoNums;
    while(begin<end) // 倆頭夾逼,或稱兩個指標兩端掃描法,很經典的方法, O(N )
    {
        if(*begin+*end>s)
        {
            --end;
        }
        else if (*begin+*end<s)
        {
            ++begin;
        }
        else
        {
            TwoNums.i = *begin;
            TwoNums.j = *end;
            return TwoNums;
        }
    }
    TwoNums.i = -1;
    TwoNums.j = -1;
    return TwoNums;
}