zl程序教程

您现在的位置是:首页 >  其他

当前栏目

1. 两数之和---双指针篇七

2023-03-14 22:54:13 时间

两数之和题解集合


引言

本题的双指针解法解释的可能不够清楚,建议大家先看这篇文章: leetcode 167. 两数之和 II - 输入有序数组----双指针篇六,二分篇二


暴力法

思路:

枚举所有nums[i]+nums[j]的可能结果,从中找出等于目标值的结果,然后返回对应下标

注意:这里不能对nums数组进行降序排列,到达减枝效果,因为这样会导致元素下标发生改变,如果非要做,可以考虑用哈希表保存元素在原数组的下标

代码:

class Solution {
public:
	vector<int> twoSum(vector<int>& nums, int target) 
	{
		for (int i = 0; i < nums.size(); i++)
		{
			for (int j = i+1; j < nums.size(); j++)
			{
				if (nums[j] + nums[i] == target) return vector<int>({ i ,j });
			}
		}
		return vector<int>();
	}
};

哈希法

思路:

我们遍历到数字 a 时,用 target 减去 a,就会得到 b,若 b 存在于哈希表中,我们就可以直接返回结果了。若 b 不存在,那么我们需要将 a 存入哈希表,好让后续遍历的数字使用。

图解:

代码:

class Solution {
	unordered_map<int, int> map;
public:
	vector<int> twoSum(vector<int>& nums, int target) 
	{
		for (int i = 0; i < nums.size(); i++)
		{
			if (map.find(target - nums[i]) != map.end()) return { map[{target - nums[i]}],i };
			map[nums[i]] = i;
		 }
		return {};
	}
};

排序加二分查找

思路:

先对指定数组进行排序,排序前用一个数组保存原数组元素对应的下标。

通过两个指针i和j,固定一个指针i,那么另外一个指针j指向的元素的值也是确定的,为target-nums[i]

我们只需要再剩余指定区间[i+1,size)中利用二分查找,查找对于元素的值等于target-nums[i]

这里我们利用一个索引数组记录对应元素的下标

代码:

class Solution {
	vector<int> index;
public:
	vector<int> twoSum(vector<int>& nums, int target) 
	{
		index.resize(nums.size());
		for (int i = 0; i < nums.size(); i++)
			index[i] = i;
         //选择排序
		for (int i = 0; i < nums.size() - 1; i++)
		{
			int MIN = i;
			for (int j = i + 1; j < nums.size(); j++)
			{
				if (nums[MIN] > nums[j])
					MIN = j;
			}
			if (MIN != i)
			{
				swap(nums[MIN], nums[i]);
				swap(index[MIN], index[i]);
			}
		}
		for (int i = 0; i < nums.size(); i++)
		{
			int targetNum = target - nums[i];
			int left = i + 1;
			int right = nums.size() - 1;
			while (left < right)
			{
				int mid = (left + right) / 2;
				if (nums[mid] < targetNum)
					left = mid + 1;
				else if (nums[mid] > targetNum)
					right = mid - 1;
				else
					return { index[i],index[mid] };
			}
			if (left<nums.size()&&nums[left] == targetNum)
			{
				return { index[i],index[left] };
			}
		}
		return {};
	}
};

双指针

先将数组复制一份(防止之后打乱下标),然后对复制的数组排序。 接着,在其两端放两个指针,相向而行,往中间靠,同时检查两数和,查出来就停止。

代码:

class Solution {
	vector<int> index;
public:
	vector<int> twoSum(vector<int>& nums, int target) 
	{
		index.resize(nums.size());
		for (int i = 0; i < nums.size(); i++)
			index[i] = i;
         //选择排序
		for (int i = 0; i < nums.size() - 1; i++)
		{
			int MIN = i;
			for (int j = i + 1; j < nums.size(); j++)
			{
				if (nums[MIN] > nums[j])
					MIN = j;
			}
			if (MIN != i)
			{
				swap(nums[MIN], nums[i]);
				swap(index[MIN], index[i]);
			}
		}
        //双指针
		int i = 0, j = nums.size() - 1;
		while (i < j)
		{
			if (nums[i] + nums[j] < target)
				i++;
			else if (nums[i] + nums[j] > target)
				j--;
			else
				return { index[i],index[j] };
		}
		return {};
	}
};