leetcode_16题——3Sum Closest(两个指针)

3Sum Closest

  Total Accepted: 38536 Total Submissions: 143223My Submissions

 

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

    For example, given array S = {-1 2 1 -4}, and target = 1.



    The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

 

Hide Tags
  Array Two Pointers
 
    开始的时候想半天,没想到啥好办法,开始想的先计算两个的与target的距离的最小,确定了之后,再计算三个的,发现这样做算法上就是错误的。
int threeSumClosest(vector<int>& nums, int target) {

	int len_nums=nums.size();

	int x=0;

	int y=1;

	int best_two_sum=abs(nums[0]+nums[1]-target);

	for(int i=0;i<len_nums-1;i++)

		for(int j=i+1;j<len_nums;j++)

		{

			if(abs(nums[i]+nums[j]-target)<best_two_sum)

			{

				x=i;

				y=j;

				best_two_sum=abs(nums[i]+nums[j]-target);

			}

		}



	int z=0;

	int flag=0;

	int last_result;

	for(int i=0;i<len_nums;i++)

	{

		if(i!=x&&i!=y&&flag==0)

		{z=i;last_result=abs(nums[i]+nums[x]+nums[y]-target);flag=1;}

		if(i!=x&&i!=y&&flag==1)

		{

			if(abs(nums[i]+nums[x]+nums[y]-target)<last_result)

			{

				z=i;

				last_result=abs(nums[i]+nums[x]+nums[y]-target);

			}

		}

	}

	return nums[x]+nums[y]+nums[z];

}

*/

//O(n^3)时间复杂度太高了

/*

int threeSumClosest(vector<int>& nums, int target)

{

	int len_nums=nums.size();

	int result=abs(nums[0]+nums[1]+nums[2]-target);

	int l_x=0,l_y=1,l_z=2;

	for(int y=1;y<len_nums-1;y++)

	{

		for(int x=0;x<y;x++)

			for(int z=y+1;z<len_nums;z++)

			{

				if(abs(nums[x]+nums[y]+nums[z]-target)<result)

				{

					l_x=x;l_y=y;l_z=z;

					result=abs(nums[x]+nums[y]+nums[z]-target);

				}

			}

	}

	return nums[l_x]+nums[l_y]+nums[l_z];

}

  接下来想到干脆直接采用穷举法,试下,也就是时间复杂度为O(n^3)发现不能AC

int threeSumClosest(vector<int>& nums, int target)

{

	int len_nums=nums.size();

	int result=abs(nums[0]+nums[1]+nums[2]-target);

	int l_x=0,l_y=1,l_z=2;

	for(int y=1;y<len_nums-1;y++)

	{

		for(int x=0;x<y;x++)

			for(int z=y+1;z<len_nums;z++)

			{

				if(abs(nums[x]+nums[y]+nums[z]-target)<result)

				{

					l_x=x;l_y=y;l_z=z;

					result=abs(nums[x]+nums[y]+nums[z]-target);

				}

			}

	}

	return nums[l_x]+nums[l_y]+nums[l_z];

}

     再后来在网上看了下别人的算法,发现有一种还可以,就是在开始的时候就进行排序,这个是O(nlog n),接着枚举一个数,再设立两个指针,一个左指针从0到这个数的位置,一个右指针从最后到这个数的位置,然后当sum<target时将左指针右移,当sum>target时,将右指针向左移,

     值得注意的是,在这个移的过程中,当sum<target时,若右移后发现又变成了sum>target,则要将之前的值记录下来,进行比较,另外一个指针也是

同样的道理。这个时间复杂度是O(n^2),

     总的为O(nlog n)+O(n^2)=O(n^2)

int threeSumClosest(vector<int>& nums, int target)

{

	sort(nums.begin(),nums.end());

	int len_nums=nums.size();

	int sum;

	int sum_reault;



	int last_sum=abs(nums[0]+nums[1]+nums[2]-target);

	sum_reault=nums[0]+nums[1]+nums[2];



	for(int y=1;y<len_nums-1;y++)

	{

		int x=0;

		int z=len_nums-1;

		while(x<y&&z>y)

		{

			if(nums[x]+nums[y]+nums[z]>target)

			{

				z--;

				if(z>y&&nums[x]+nums[y]+nums[z]<target)

				{

					sum=nums[x]+nums[y]+nums[z+1];

					if(abs(sum-target)<last_sum)

					{

						last_sum=abs(sum-target);

						sum_reault=sum;

					}

				}

			}

			else if(nums[x]+nums[y]+nums[z]<target)

			{

				x++;

				if(x<y&&nums[x]+nums[y]+nums[z]>target)

				{

					sum=nums[x-1]+nums[y]+nums[z];

					if(abs(sum-target)<last_sum)

					{

						last_sum=abs(sum-target);

						sum_reault=sum;

					}

				}

			}

			else

				return target;

		}



		if(x==y)

		{

			x-=1;

			sum=nums[x]+nums[y]+nums[z];

			if(abs(sum-target)<last_sum)

			{

				last_sum=abs(sum-target);

				sum_reault=sum;



			}

		}

		if(z==y)

		{

			z+=1;

			sum=nums[x]+nums[y]+nums[z];

			if(abs(sum-target)<last_sum)

			{

				last_sum=abs(sum-target);

				sum_reault=sum;

			}

		}

	}

	return sum_reault;

}





int main()

{

	vector<int> vec;

	vec.push_back(0);

	vec.push_back(2);

	vec.push_back(1);

	vec.push_back(-3);



	cout<<threeSumClosest(vec,1)<<endl;



}

  

你可能感兴趣的:(LeetCode)