zoukankan      html  css  js  c++  java
  • 编程之法section II: 2.2 和为定值的两个数

    数组篇

    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;    
    }
    
    CV小蜡肉
  • 相关阅读:
    JQuery源码解析-Dom加载过程
    多个script标签的作用域
    JQuery源码解析-JQuery的工具方法(1)
    JQuery源码解析-JQuery的工具方法
    JQuery源码解析-JQuery.extend()方法
    JQuery源码解析-添加JQuery的一些方法和属性
    中兴捧月算法精英挑战赛-迪杰斯特拉派
    C语言中的内存相关问题
    动态内存管理
    虚函数与虚继承小结
  • 原文地址:https://www.cnblogs.com/zzq-123456/p/9221823.html
Copyright © 2011-2022 走看看