双指针专题

双指针专题系列

问题1:LEETCODE  两数之和target问题    有序数组

题目描述:在有序数组中找出两个数,使它们的和为 target。

使用双指针,一个指针指向值较小的元素,一个指针指向值较大的元素。指向较小元素的指针从头向尾遍历,指向较大元素的指针从尾向头遍历。

  • 如果两个指针指向元素的和 sum == target,那么得到要求的结果;
  • 如果 sum > target,移动较大的元素,使 sum 变小一些;
  • 如果 sum < target,移动较小的元素,使 sum 变大一些。

数组中的元素最多遍历一次,时间复杂度为 O(N)。只使用了两个额外变量,空间复杂度为 O(1)。

#include<stdio.h>
void twoSum(int* numbers, int target,int *tag) 
{
    
    if (numbers == NULL) return;
    int i = 0, j = 3;
    int sum = 0;
    while (i < j) 
    {
        sum = numbers[i] + numbers[j];
        if (sum == target) 
        {
            tag[0]=  i;
            tag[1] = j;
            return;
        } 
        else if (sum < target)
        {
            i++;
        } 
        else 
        {
            j--;
        }
    }
    return ;
}
int main(void)
{
    int  a[4] = {1,3,7,9};
    int tag[2] = {0};
    int target = 8;
    twoSum(a,target,tag);
    printf("[%s][%d][anita]num1 = %d  num2 = %d\n",__FUNCTION__,__LINE__,tag[0],tag[1]);
    
    return 0;
}

 

 问题2:LEETCODE     两数平方和

题目描述:判断一个非负整数是否为两个整数的平方和。

可以看成是在元素为 0~target 的有序数组中查找两个数,使得这两个数的平方和为 target,如果能找到,则返回 true,表示 target 是两个整数的平方和。

本题和 167. Two Sum II - Input array is sorted 类似,只有一个明显区别:一个是和为 target,一个是平方和为 target。本题同样可以使用双指针得到两个数,使其平方和为 target。

本题的关键是右指针的初始化,实现剪枝,从而降低时间复杂度。设右指针为 x,左指针固定为 0,为了使 02 + x2 的值尽可能接近 target,我们可以将 x 取为 sqrt(target)。

因为最多只需要遍历一次 0~sqrt(target),所以时间复杂度为 O(sqrt(target))。又因为只使用了两个额外的变量,因此空间复杂度为 O(1)。

注意:在gcc下用到数学函数,如sqrt。在gcc时要加上 -lm 参数,这样告诉编译器我要用到数学函数了 。

#include<stdio.h>
#include<math.h>
#include<stdbool.h>
bool func2(int target)
{
    int a = 0;
    a = sqrt(target);
    int i = 0;
    int j = a;
    while(i < j)
    {
        int k = i * i + j * j;
        if(k == target)
        {
            return true;
        }
        else if(k < target)
        {
            i++;
        }
        else
        {
            --j;
        }
    }
    return false;

}

int main(void)
{
    int a = 9;
    if(true == func2(a))
    {
        printf("find\n");
    }
    else
    {
        printf("not find \n");
    }
    return 0;
}

 问题三:反转字符串中的元音字符

#include<stdio.h>
#include<string.h>
static void my_switch(char *a,char *b)
{
    char temp = '0';
    temp = *a;
    *a = *b;
    *b = temp;
}
static int is_vowel(const char c)
{
    if(c == 'a' || c == 'e' || c == 'i' || c == 'o' || c =='u')
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
int main(void)
{
    char string[6] = "hello";    /*非常重要,如果写为char *string = "hello"  则一直段错误*/
    int head = 0,tail = 0;
    tail = strlen(string);
    while(head < tail)
    {
        printf("[%s][%d][anita]  is_vowel(string[head] = %c  is_vowel(string[tail-1]) = %c\n",\
                    __FUNCTION__,__LINE__,string[head],string[tail-1]);
        if(is_vowel(string[head]) && is_vowel(string[tail-1]))
        {
            my_switch(&string[head], &string[tail-1]);
            head ++;
            tail --;
        }
        else if(!is_vowel(string[head]))
        {
            head++;
        }
        else if(!is_vowel(string[tail - 1]))
        {
            tail--;
        }
    }
}

注意:char message[]  = "hello"   与char *message = "hello"有本质上的区别,前者初始化一个字符数组的元素,而后者是一个真正意义上的字符串常量,这个指针变量被初始化为指向这个字符串常量的存储未知;

posted @ 2020-10-21 22:25  Anita光子  阅读(65)  评论(0编辑  收藏  举报