给定一个排序和旋转数组的 C++ 程序,查找是否存在具有给定总和的对
给定一个经过排序然后围绕未知点旋转的数组。查找数组是否具有给定总和“x”的对。可以假设数组中的所有元素都是不同的。
例子 :
Input: arr[] = {11, 15, 6, 8, 9, 10}, x = 16
Output: true
There is a pair (6, 10) with sum 16
Input: arr[] = {11, 15, 26, 38, 9, 10}, x = 35
Output: true
There is a pair (26, 9) with sum 35
Input: arr[] = {11, 15, 26, 38, 9, 10}, x = 45
Output: false
There is no pair with sum 45.
我们已经讨论了排序数组的 O(n) 解决方案(参见方法 1 的步骤 2、3 和 4)。我们也可以将此解决方案扩展到旋转数组。这个想法是首先在数组中找到最大的元素,它也是枢轴点,最大之后的元素是最小的元素。一旦我们有索引最大和最小的元素,我们使用类似的中间算法(如方法 1 中讨论的这里)来查找是否存在一对。这里唯一新的是索引使用模运算以旋转方式递增和递减。
以下是上述思想的实现。
输出 :
Array has two elements with sum 16
上述解决方案的时间复杂度为 O(n)。使用此处讨论的二分搜索方法,可以将找到枢轴的步骤优化为 O(Logn)。
如何计算总和为x的所有对?
逐步算法是:
- 找到已排序和旋转数组的枢轴元素。枢轴元素是数组中最大的元素。最小的元素将与其相邻。
- 使用两个指针(比如左和右),左指针指向最小元素,右指针指向最大元素。
- 求两个指针所指向的元素之和。
- 如果总和等于 x,则增加计数。如果总和小于 x,则通过以旋转方式递增左指针来增加总和,将左指针移动到下一个位置。如果总和大于 x,则通过以旋转方式递减右指针来减少总和,将右指针移动到下一个位置。
- 重复步骤 3 和 4,直到左指针不等于右指针或直到左指针不等于右指针 - 1。
- 打印最终计数。
下面是上述算法的实现:
C++
// C++ program to find number of pairs with
// a given sum in a sorted and rotated array.
#include
using namespace std;
// This function returns count of number of pairs
// with sum equals to x.
int pairsInSortedRotated(int arr[], int n, int x)
{
// Find the pivot element. Pivot element
// is largest element of array.
int i;
for (i = 0; i < n-1; i++)
if (arr[i] > arr[i+1])
break;
// l is index of smallest element.
int l = (i + 1) % n;
// r is index of largest element.
int r = i;
// Variable to store count of number
// of pairs.
int cnt = 0;
// Find sum of pair formed by arr[l] and
// and arr[r] and update l, r and cnt
// accordingly.
while (l != r)
{
// If we find a pair with sum x, then
// increment cnt, move l and r to
// next element.
if (arr[l] + arr[r] == x){
cnt++;
// This condition is required to
// be checked, otherwise l and r
// will cross each other and loop
// will never terminate.
if(l == (r - 1 + n) % n){
return cnt;
}
l = (l + 1) % n;
r = (r - 1 + n) % n;
}
// If current pair sum is less, move to
// the higher sum side.
else if (arr[l] + arr[r] < x)
l = (l + 1) % n;
// If current pair sum is greater, move
// to the lower sum side.
else
r = (n + r - 1)%n;
}
return cnt;
}
/* Driver program to test above function */
int main()
{
int arr[] = {11, 15, 6, 7, 9, 10};
int sum = 16;
int n = sizeof(arr)/sizeof(arr[0]);
cout << pairsInSortedRotated(arr, n, sum);
return 0;
}
输出:
2
时间复杂度: O(n)
辅助空间: O(1)
Nikhil Jindal 提出了这种方法。
请参阅关于给定排序和旋转数组的完整文章,查找是否存在具有给定总和的对以获取更多详细信息!