题目: 在一个增序的整数数组里找到两个数,使它们的和为给定值。已知有且只有一对解。
输入: 输入是一个数组(numbers)和一个给定值(target)。输出是两个数的位置,从 1 开始计数。
Input: numbers = [2,7,11,15], target = 9
输出: Output: [1,2]
方法一: 双指针
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
int low = 0, high = numbers.size()-1;
while(low < high){
int sum = numbers[low] + numbers[high];
if(sum == target){
return {low+1, high+1};
} else if(sum > target){
--high;
} else{
++low;
}
}
return {-1, -1};
}
};
复杂度分析
时间复杂度: O(n),其中 n 是数组的长度。两个指针移动的总次数最多为 n 次
空间复杂度: O(1)
方法二: 二分查找
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
for(int i=0; i<numbers.size(); ++i){
int low = i+1, high = numbers.size()-1;
while(low <= high){
int mid = (high - low) / 2 + low;
if(numbers[mid] == target - numbers[i]){
return {i+1, mid+1};
} else if(numbers[mid] > target - numbers[i]){
high = mid - 1;
} else {
low = mid + 1;
}
}
}
return {-1, -1};
}
};
复杂度分析
时间复杂度: O(nlogn),其中 n 是数组的长度。需要遍历数组一次确定第一个数,时间复杂度为O(n),寻找第二个数使用二分查找,时间复杂度为O(logn),因此总时间复杂度为O(nlogn).
空间复杂度: O(1)
双指针主要用于遍历数组,两个指针指向不同的元素,协同完成任务,也可以延伸至多个数组的多个指针。
1.若两个指针指向同一数组,遍历方向相同且不会相交,则成为滑动窗口(两个指针包围的区域即为当前的窗口),经常用于区间搜索。
2.若两个指针指向同一数组,但是遍历方向相反,则可以用来搜索,待搜索的数组往往是排好序的。
指针与常量
int x;
int *p1 = &x; // 指针可以被修改,值也可以被修改
const int *p2 = &x; // 指针可以被修改,值不可以被修改(const int)
int *const p3 = &x; // 指针不可以被修改(*const),值可以被修改
const int *const p4 = &x; // 指针不可以被修改,值也不可以被修改
指针函数与函数指针
// addition是指针函数,一个返回类型是指针的函数
int *addition(int a, int b){
int *sum = new int(a+b);
return sum;
}
int subtraction(int a, int b){
return a - b;
}
int operation(int x, int y, int (*func)(int, int)){
return (*func)(x, y);
}
// minus是函数指针,指向函数的指针
int (*minus)(int, int) = subtraction;
int *m = addition(1, 2);
int n = operation(3, *m, minus);