leetcode面试经典150题——01合并2个有序数组

题目:合并2个有序数组

描述:给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
leetcode链接

方法一:借用第三个数组nums3,设置指针i,j指向nums1和nums2,比较两个指针指向的元素,小的存储到nums3中,最后把nums3复制到nums1中

时间复杂度:o(m+n) 空间复杂度:o(m+n)

void merge(vector<int> &nums1,int m,vector<int> &nums2,int n){
	if(n==0){//第二个数组长度为0时直接返回 
		return;
	}
	vector<int> num3(m+n,0);//初始化每个元素为0 
	int k=0;
	int i,j;
	for(i=0,j=0;i<m&&j<n;){
		if(nums1[i]<nums2[j]){
			num3[k++] = nums1[i++];
		}else{
			num3[k++] = nums2[j++];
		}	
	}
	if(i==m){//把剩下数组的元素复制到nums3中 
		while(j<n){
			num3[k++] = nums2[j++];
		}
	}else{
		while(i<m){
			num3[k++] = nums1[i++];
		}
	}
	for(k=0;k<m+n;k++){
		nums1[k] = num3[k];
	} 
}

方法二:由于nums1的长度为m+n,那么直接把nums2复制到nums1后面,再对nums1进行排序
时间复杂度:o(nlogn) 空间复杂度:o(1)

void merge(vector<int> &nums1,int m,vector<int> &nums2,int n){
	for(int i=m,j=0;i<m+n&&j<n;i++,j++){
		nums1[i] = nums2[j];
	}
	sort(nums1.begin(),nums1.end());//左闭右开 
}

方法三:逆向双指针,我们设置三个指针p1,p2,p3分别指向nums1最后一个输入的元素,num2最后一个元素,nums1中最后一个元素,比较p1,p2指向的元素大小,大的元素放在p3指向的位置,然后指针前移,经过证明有如下结论:将元素放置nums1的过程中不会产生覆盖现象,**
证明如下**:
对于任意一个时刻,nums1中有m-1-p1个元素放在nums1后面,nums2中有n-1-p2个元素放在nums1后面,指针p1后面有m+n-p1-1个元素,那么要使得m+n-p1-1>=m-1-p1+n-1-p2,即p1后面的元素个数要大于nums1放置的个数加上nums2放置的个数,此时nums1中的元素才不会被覆盖,化简得p2>=-1显然成立,得证。

> 时间复杂度:o(m+n) 空间复杂度:o(1)*

void merge(vector<int> &nums1,int m,vector<int> &nums2,int n){
	int p1 = m-1,p2 = n-1;
	int p3 = m+n-1;
	int tag;
	while(p1>=0||p2>=0){
		if(p1==-1){
			tag = nums2[p2--];
		}else if(p2==-1){
			tag = nums1[p1--];
		}else if(nums1[p1]>nums2[p2]){
			tag = nums1[p1--];
		}else{
			tag = nums2[p2--];
		}
		nums1[p3--] = tag;
	}
}

你可能感兴趣的:(leetcode,面试,算法)