在这篇文章中,我们解释了数组中的双指针技术/算法,它被用来有效地解决大量的问题。问题包括反转数组和查找排序数组中是否存在给定和的一对:
目录:
- 双指针技术简介
- 例题1:反转一个数组
- 例题2:查找一个排序数组中是否存在给定和的一对
让我们开始学习双指针技术。
双指针技术简介
双指针技术是一种广泛使用的技术,用于解决基于数组的各种问题。这对排序数组特别有用,可以帮助解决各种各样的问题。顾名思义,我们使用2个 "指针",指向数组中的某些元素。指针根据一些条件(取决于问题)进行操作,直到它们相遇(可能会有所不同)。
双指针方法本质上使用了2个指针。这些指针可以根据使用情况以不同的方式使用。比如说。
-
一个指针可以是慢速运行的,而另一个指针可以是快速运行的。这种技术通常被广泛用于基于链接列表的问题。
-
一个指针指向第一个元素,另一个指针指向数组的最后一个元素。用于处理排序数组的问题。
让我们通过一个问题实例来更好地理解这种技术。请注意,双指针方法有多种应用,并不限于这个具体问题。
例题1:反转一个数组
给定一个数组,我们需要将其反转:
arr = [2,5,3,7,4]
反转的arr = [4,7,3,5,2 ]
解决这个问题的一个常用方法是使用2个指针的方法。一个指针指向第一个元素,第二个指针指向最后一个元素。指针所指向的元素被交换,指向第一个元素的指针被递增,而指向最后一个元素的指针被递减(Condition for manipulation)。这个过程一直持续到指针相遇(停止的条件)。
代码
以下是在Java中使用双指针技术的实现:
public static void reverseArray(int arr[], int n)
{
int i = 0, j = n-1;
while(i < j)
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
}
以下是在C++中使用双指针技术的实现:
void reverseArray(int arr[], int n)
{
int i = 0, j = n-1;
while(i < j)
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
}
时间和空间复杂度
时间复杂度是O(N),因为数组只被遍历了一次。
空间复杂度是O(1),没有使用辅助空间。
例题2:在一个已排序的数组中找出具有给定总和的一对数组是否存在
给定一个已排序的数组和一个数字K,我们需要找到是否存在一对元素,使它们的总和等于给定的数字K.解决这个问题有多种方法(有些方法比其他方法更有效)。
我们将讨论一种使用2个指针的方法作为关键算法的解决方案。
请注意,数组是经过排序的。
例子:
arr = [1,4,5,7,10], K = 12
对(5,7)产生的和等于12. 干运行 。
- i = 0, j = 4 => arr[i] + arr[j] = 11, 小于12,因此i++。
- i = 1, j = 4 => 4 + 10 = 14 and 14 > K, decrement j,j--.
- i = 1, j = 3 => 4 + 7 = 11 and 11 < K, 增加i,i++.
- i = 2, j = 3 => 5 + 7 = 12,等于给定的和K,返回true。
算法
-
我们使用两个指针,一个指向第一个元素(我们称之为i),另一个指向最后一个元素(我们称之为j)。
-
2.2.
1 如果sum == K,返回true。
2 如果sum < K, 递增 i。
-
返回false。
在这种情况下,这种采用2个指针方法的逻辑是有效的,因为,数组是排序的。
当sum < K时,我们增加i,它开始指向一个比当前元素大的数字。这增加了总和,并可能使其接近(甚至超过)K。然而,任何比当前元素小的数字都会导致总和变小,这肯定会小于K。
同样,当总和>K时,递减j也是有意义的,因为递减j会使总和比以前小,因为使用的新元素比当前元素小。
代码
以下是在Java中使用双指针技术的实现:
public static boolean pairExists(int arr[], int K)
{
int i = 0, j = arr.length - 1;
while(i < j)
{
if(arr[i] + arr[j] == K)
return true;
else if(arr[i] + arr[j] < K)
i++;
else
j--;
}
return false;
}
以下是在C++中使用双指针技术的实现。
bool pairExists(int arr[], int n, int K)
{
int i = 0, j = n-1;
while(i < j)
{
if(arr[i] + arr[j] == K)
return true;
else if(arr[i] + arr[j] < K)
i++;
else
j--;
}
return false;
}
时间和空间的复杂性
使用双指针方法有助于将时间复杂性降低到O(N)。我们只需对数组进行一次遍历,就能发现数组中是否存在具有给定和的配对。
这种方法不需要任何辅助空间,因此,空间复杂性为O(1)。
通过OpenGenus的这篇文章,你一定对阵列中的双指针技术有了一个完整的概念,以及如何使用它来解决问题。