双指针专题系列
问题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 ",__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 "); } else { printf("not find "); } 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 ", __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"有本质上的区别,前者初始化一个字符数组的元素,而后者是一个真正意义上的字符串常量,这个指针变量被初始化为指向这个字符串常量的存储未知;