1. 程式人生 > >編程之法section II: 2.2 和為定值的兩個數

編程之法section II: 2.2 和為定值的兩個數

cpp iterator 尋找 AI 存在 while ios last static

====數組篇====

2.2 求和為定值的兩個數:

題目描述:有n個整數,找出其中滿足兩數相加為target的兩個數(如果有多組滿足,只需要找出其中一組),要求時間復雜度盡可能低。


解法一:

思路:開散列映射,空間換時間, 查找耗時o(n)

Writer: zzq
Function: 求和為定值的兩個數。
方法一: 開散列映射(哈希表)。
1) 用哈希表Hashmap先把數組中的數字和對應的下標進行存儲,(鍵,值)=(具體數值,對應下標);
2) 遍歷數組,對loss=target-nums[i],在Hashmap中找是否存在loss,找到即返回loss所對應的value,也就是所對應的數組下標;
時間復雜度:O(n)



#include<iostream>
#include<map>
using namespace std;

//哈希表存儲查找  
void twoSum(int *nums, int *result, int length, int target) {    
        map<int, int> hashmap;
        for (int i = 0; i < length; i++)  
            hashmap[nums[i]]=i;  
        map<int, int>::iterator it;
        for
(int i = 0; i < length; i++) { int v = target - nums[i]; it = hashmap.find(v); if(it!=hashmap.end() && i != it->second){ result[0] = i; result[1] = hashmap[v]; break; } } } int
main(){ int nums[]={10,12,8,56,98,43,21,15,76,19}; int target = 20; int result[2] = {0,0}; twoSum(nums, result,10, target); cout<<result[0]<<‘ ‘<<result[1]<<endl; return 0; }

解法二:

思路:快排O(logn)+二分法O(nlogn).

Writer: zzq
Function: 求和為定值的兩個數。
方法二: 1)先對給定數組進行排序;
2)在排序好的數組基礎上,每次對於loss=target-nums[i],是用二分法查找loss是否存在,如果存在,則返回這兩個數;
時間復雜度:O(logn)+O(nlogn),
【 排序:O(logn);
二分查找: O(nlogn)。



#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
// 快速排序 
void QuickSort(int *a, int begin, int end){
    if(begin<end){
        int i = begin;
        int j = end;
        int temp = *(a+i);
        while(i<j){
            while(i<j&&*(a+j)>=temp)j--;
            if(i<j){
                *(a+i)=*(a+j);
                i++;
            }
            while(i<j&&*(a+i)<=temp)i++;
            if(i<j){
                *(a+j)=*(a+i);
                j--;
            }    
        }
        *(a+i)=temp;
    
        QuickSort(a,begin,i-1);
        QuickSort(a,i+1,end);
    }
}
 
//二分查找 
int BinaryQuery(int *a,int goal,int start, int end){
    int i=start,j=end;
    int flag = 0;
    while(i<=j){
        int middle = (j-i)/2;       
        if(goal==*(a+middle)){
            return 1;  // 找到目標值
        }
        else if(goal<*(a+middle)){ // 目標值在左半部分 
            j = middle-1;   //  尾下標指向左半部分最後一個元素         
        }
        else{   // 目標值在右半部分 
            i = middle +1;  // 首指針指向右半部分最後一個元素 
        }       
    }
    return 0;
}
int main(){
    int n,sum;
        cin>>n>>sum;
        int a[n];
        int i;
        for(i = 0;i<n;i++)cin>>a[i];
    
        QuickSort(a,0,n-1); // 快排 
    
        for(i = 0;i < n;i++){
            if((sum-a[i])>0){   
            int flag = BinaryQuery(a,sum-a[i],0, n-1);
            if(flag){
                cout<<a[i]<<‘ ‘<<sum-a[i]<<endl;    
                break;
            }   
        }       
    }   
    return 0;
}

解法三:

思路:快排O(logn)+ two pointers [首尾指針法]O(n).

Writer: zzq
Function: 求和為定值的兩個數。
方法二: 1)先對給定數組進行排序;
2)在排序好的數組基礎上,每次對於loss=target-nums[i],是用首尾指針法查找loss是否存在,如果存在,則返回這兩個數;
時間復雜度:O(logn)+O(nlogn),
【 排序:O(logn);
two pointers: O(n)。




#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
// 快速排序 
void QuickSort(int *a, int begin, int end){
    if(begin<end){
        int i = begin;
        int j = end;
        int temp = *(a+i);
        while(i<j){
            while(i<j&&*(a+j)>=temp)j--;
            if(i<j){
                *(a+i)=*(a+j);
                i++;
            }
            while(i<j&&*(a+i)<=temp)i++;
            if(i<j){
                *(a+j)=*(a+i);
                j--;
            }    
        }
        *(a+i)=temp;
    
        QuickSort(a,begin,i-1);
        QuickSort(a,i+1,end);
    }
}
// 首尾指針法
void GetGoalIndex(int *a, int goal,int start,int end){
    int begin = start;
    int last = end;
    
    while(begin<=last){
        int currentSum = *(a+begin)+*(a+last);
        if(currentSum==goal){
            cout<<*(a+begin)<<‘ ‘<<*(a+last);
            // 如果需要找到所有滿足條件的對數,則需要加上這兩行 
            //begin++;
            //last--;
            break;
            
        }
        else{
            if (currentSum>goal){
                last--;
            }
            else{
                begin++;
            }   
        } 
    }   
} 
int main(){
    int n,sum;
    cin>>n>>sum;
    int a[n];
    int i;
    for(i = 0;i<n;i++)cin>>a[i];
    
    QuickSort(a,0,n-1); // 快排 
    GetGoalIndex(a,sum,0, n-1); 
    return 0;
}

舉一反三:

找和為定值的兩個數的下標,並且兩個數不能是同一個。

1:散列表法
2:快排+two pointers(新建數組b跟蹤存儲下標變化情況)。

void QuickSort(int *a, int *b, int begin, int end){
    //cout<<begin<<‘ ‘<<end<<endl;
    if(begin<end){
        int i = begin;
        int j = end;
        int temp = *(a+i);
        int temp_index=*(b+i);  
        while(i<j){
            while(i<j&&*(a+j)>=temp)j--;
            if(i<j){
                *(a+i)=*(a+j);
                *(b+i)=*(b+j);
                i++;
            }
            while(i<j&&*(a+i)<=temp)i++;
            if(i<j){
                *(a+j)=*(a+i);
                *(b+j)=*(b+i);
                j--;
            }    
        }
        *(a+i)=temp;
        *(b+i)=temp_index;
        //for(int i=0;i<10;i++)cout<<b[i]<<‘ ‘;
        //cout<<endl;
        QuickSort(a, b, begin, i-1);
        QuickSort(a, b, i+1, end);
    }
}
// 尋找下標 ,用數組c接收下標 
void GetGoalIndex(int *a, int *b, int *c, int goal,int start,int end){
    int begin = start;
    int last = end;
    while(begin<=last){
        int currentSum = *(a+begin)+*(a+last);
        if(currentSum==goal){
            if(*(b+begin)>*(b+last)){
                *c=*(b+last);
                *(c+1)=*(b+begin);
            }
            else{
                *c=*(b+begin);
                *(c+1)=*(b+last);
            }   
            break;
        }
        else{
            if (currentSum>goal){
                last--;
            }
            else{
                begin++;
            }   
        } 
    }
} 
int* twoSum(int* nums, int numsSize, int target) {
    int i;
    int b[numsSize];
    static int c[2];
    for(i = 0;i<numsSize;i++){
        b[i]=i;
    }

    QuickSort(nums, b, 0, numsSize-1);
    //for(int i=0;i<10;i++)cout<<b[i]<<‘ ‘;
    //cout<<endl;    
    GetGoalIndex(nums, b, c,target, 0, numsSize-1); 
    return c;    
}

編程之法section II: 2.2 和為定值的兩個數