C++程序 给定排序和旋转的数组,查找是否存在给定和的一对
给定一个排序后,然后围绕一个未知点旋转的数组。查找数组是否具有给定和“x”的一对。可以假定数组中的所有元素都是不同的。
示例:
输入:arr[] = {11, 15, 6, 8, 9, 10},x = 16
输出:true
有一对(6,10)和为16
输入:arr[] = {11, 15, 26, 38, 9, 10},x = 35
输出:true
有一对(26,9)和为35
输入:arr[] = {11, 15, 26, 38, 9, 10},x = 45
输出:false
没有和为45的一对。
我们已经讨论过一种针对排序数组的O(n)解决方法(请参见方法1的步骤2、3和4)。我们也可以将此解决方案扩展到旋转数组上。首先找到数组中最大的元素,这是枢轴点,最大元素后面的元素是最小元素。一旦我们有了最大和最小元素的索引,我们使用类似于中间相遇算法(如方法1中所述)来查找是否存在一对。这里唯一的新事物是使用模运算以旋转方式递增和递减索引。
下面是上述想法的实现。
输出 :
上述解的时间复杂度为O(n)。使用二进制搜索方法在O(logn)内优化可以找到枢轴。
如何计算所有和为x的对数?
以下是逐步算法:
- 找到排序和旋转数组的枢轴元素。枢轴元素是数组中最大的元素。最小元素将与它相邻。
- 使用两个指针(称为left和right),其中左指针指向最小元素,右指针指向最大元素。
- 查找指针指向的两个元素的和。
- 如果和等于x,则增加计数。如果和小于x,则将左指针按旋转方式递增到下一个位置以增加和。如果和大于x,则将右指针按旋转方式递减到下一个位置以减少和。
- 重复步骤3和4,直到左指针不等于右指针或左指针不等于right pointer-1为止。
- 打印最终计数。
下面是上述算法的实现。
输出:
时间复杂度: O(n)
辅助空间: O(1)
这种方法是由Nikhil Jindal推荐的。
方法:双指针方法
- 使用修改后的二分搜索算法查找旋转排序数组的旋转元素。
- 初始化两个指针,一个指向数组的最小元素,另一个指向数组的最大元素。
- 当左指针小于右指针时,重复步骤4到6。
- 计算由左右指针指向的元素的和。
- 如果总和等于给定的总和,则返回true。
- 如果总和大于给定的总和,则将右指针减少。如果总和少于给定的总和,则将左指针增加。
- 如果没有找到给定总和的一对,则返回false。
输出结果
时间复杂度:O(n)
辅助空间:O(1)