在算法中,双指针的问题较为常见,应用也比较广泛,双指针问题能够降低时间复杂度和空间复杂度,有必要掌握这一内容。
下面通过LeetCode的题目来说明双指针。
示例 1:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
解析:这道题可以通过双指针来求解,即给定i和j,分别指向0位置和numsize -1的位置, 比较两个指针所指向的元素的平方的大小,大的逆序放在要返回的数组中。为什么要逆序呢?
由于已知数组是非递减顺序排序的:
假如输入的数组全是非负数,那么平方后也是一个递增顺序。
假如输入的数组全是负数,那么平方后是一个递减的顺序。
假如输入的数组有负数,有非负数,那么平方后的情况就尾部是递减或递增的。
所以逆序存放平方后大的元素,就不再需要讨论上面的情况。
图解如上:
这样就可以解决问题了。
代码如下:
int* sortedSquares(int* nums, int numsSize, int* returnSize)
{
assert(nums);
*returnSize = numsSize;
int *ret = (int*)malloc(sizeof(int)*numsSize);
int i =0;
int j =numsSize -1;
while(numsSize--)
{
if(nums[i]*nums[i]
输入: nums = [1,2,3,4,5,6,7], k = 3
输出:[5,6,7,1,2,3,4]解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]
对于旋转的题目,只需要记住最优解法即可。
最优解是:逆序
该方法远比双指针来得更加简单粗暴。
后k个逆序
前numsSize个逆序
整体逆序
想想是不是这样。
所谓的逆序,也是第一个下标的元素和最后一个下标的元素交换位置即可
交换完第一个和最后一个元素后,再交换第二个元素和倒数第二个元素,以此类推
代码实现:
void reverse(int*left,int *right)
{
while(left
k%=numsSize的原因是,假如旋转8次,有6个元素,其效果和旋转两次是一样的。
输入: nums = [0,1,0,3,12]
输出:[1,3,12,0,0]
解析:
本题使用双指针也是非常好的方法。
给一个指针指向下标0位置,该指针用来记录非0元素的个数,给另一个指针,该指针一次次往后遍历,如果往后遍历的指针!= 0 ,那么就把这个元素赋值给第一个位置的元素,然后各自往后移。
如果往后遍历的指针 == 0,那么继续往后遍历,第一个指针不用走。
这样遍历下去,最后第一个指针指向的位置就是最后一个非0元素的下标,然后把 后面的元素全都赋值成0即可。
代码如下:
int cmp(const void*e1,const void*e2)
{
return *(int*)e1 - *(int*)e2;
}
void moveZeroes(int* nums, int numsSize)
{
assert(nums);
int i =0;
int j =0;//记录0个数
for(i=0;i
示例 1:
输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
示例 2:
输入:numbers = [2,3,4], target = 6
输出:[1,3]
解释:2 与 4 之和等于目标数 6 。因此 index1 = 1, index2 = 3 。返回 [1, 3] 。
示例 3:
输入:numbers = [-1,0], target = -1
输出:[1,2]
解释:-1 与 0 之和等于目标数 -1 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
解析:
在这道题中,我们要寻找的是符合条件的一对下标 (i,j)它们需要满足的约束条件是:
i、j都是合法的下标,即 0≤i
i<j(题目要求)
而我们希望从中找到满足 arr[i] + arr[j] == target 的下标 (i,j)。以 n=5 为例,这时候全部的搜索空间是:
我们从右上角开始比较:
当arr[0] +arr[4] >target时,此时arr[0]是所在行中最小的,既然最小的+arr[4] 都> target,那么后面的arr[1]+ arr[4] ,arr[2] + arr[4] ...都大于target,所以应该找arr[0] +arr[3]的元素 ,此时就可以排除一列元素了,即j--。如下图:
当arr[0] +arr[4] arr[0]+arr[2]...也仍然小于target。所以应该排除掉一行元素,即i++。如下图: 代码如下:
int* twoSum(int* numbers, int numbersSize, int target, int* returnSize){
*returnSize = 2;
assert (numbers);
int i =0;
int j =numbersSize -1;
int *ret = (int*)malloc(sizeof(int)*(*returnSize));
while(i