C++之经典算法-双指针的魅力
来源:互联网 发布:中信银行安全控件mac 编辑:程序博客网 时间:2024/05/01 02:00
原文:http://blog.csdn.net/zzran/article/details/8456721 拿来主义~
在解决问题过程中,经常碰到使用双指针解决的情况,使用双指针,可以很高效很快速的解决问题,罗列一下应用双指针的情况:
1,将给定的英文字符串进行反转,例如: I love programming。得到的结果是:.gnimmargorp evol I。下面给出核心代码:
- #include<stdio.h>
- #include<string.h>
- void swap_string(char *p_start, char *p_end) {
- char temp;
- while(p_start <= p_end) {
- temp = *p_start;
- *p_start = *p_end;
- *p_end = temp;
- p_start++;
- p_end--;
- }
- }
- void main() {
- char str[] = "I love programming.";
- swap_string(str, str + strlen(str) - 1);
- printf("%s\n", str);
- }
2,给定一个字符串,例如:" test ** ",要求出去字母之外其他多余的字符,这也需要设定两个指针,一个慢指针和一个快指针,核心代码如下:
- #include<stdio.h>
- #include<string.h>
- void trim_word(char *word) {
- char *p_slow = word;
- char *p_fast = word;
- while(*p_fast) {
- if(!(*p_fast >= 'a' && *p_fast <= 'z') && !(*p_fast >= 'A' && *p_fast <= 'Z')) {
- p_fast++;
- } else {
- *p_slow++ = *p_fast++;
- }
- }
- *p_slow = '\0';
- }
- void main() {
- char word[] = " test ** ";
- trim_word(word);
- printf("%s\n", word);
- }
3,给定一个字符串,例如:"abccba",判断它是否是回文。可以应用数组解决,但是数组的索引速度没有指针的移动速度快,所以设定两个指针,一个指向字符串开始,一个指向字符串结尾,同步移动。核心代码如下:
- #include<stdio.h>
- #include<string.h>
- int is_palindrome(char *str) {
- char *p_start = str;
- char *p_end = str;
- while(p_start < p_end) {
- if(*p_start != *p_end) {
- return 0;
- }
- p_start++;
- p_end--;
- }
- return 1;
- }
- void main() {
- char string[] = "abccba";
- if(is_palindrome(string)) {
- printf("string is palindrome.\n");
- } else {
- printf("string is not palindrome.\n");
- }
- }
4,判断一个单链表是否有环,可以设置两个指针,一个指针每次移动一步,另一个指针每次移动两步,如果存在环的话,移动快的指针一定可以追上移动慢的指针。如下代码没有在真实的环境中跑过,只是一个基本的思路:
- int is_cycling(LinkList L) {
- LinkNode *p_slow = L;
- LinkNode *p_fast = L;
- while(p_fast && p_fast->next) {
- p_fast = p_fast->next;
- p_fast = p_fast->next;
- p_slow = p_slow->next;
- if(p_slow == p_fast) {
- return 1;
- }
- }
- return 0;
- }
5,给定一个链表,首先假设链表正向数或者反向数的第一个的标号都为1,不要受数组的影响。要求是找到链表中倒数第k个节点。链表的缺点之一就是不能像数组一样进行随机的存储和读取。比较笨拙的办法就是先遍历一遍链表,求出它的长度n,因为是找倒数第k个,所以我们只要找到整数第n-k个就可以了。另外一种比较巧妙的方法就是设定两个指针,一个指针先移动k-1步,那么它指向的就是链表中的第k个节点,然后再设置一个指针,指向链表头,假设头部中存储数据。那么两个指针同时移动,直至第一个指针指向空为止。核心代码如下,需要注意k的值超过链表长度的情况,同时,代码也只是基本思路,为经过验证:
- LinkNode get_node(LinkList L, int k) {
- LinkNode *p_first = L;
- LinkNode *p_second = L;
- int i = 0;
- while(i < k) {
- p_first = p_first->next;
- i++;
- }
- if(p_first == NULL)
- return NULL;
- while(p_first != NULL) {
- p_first = p_first->next;
- p_second = p_second->next;
- }
- return p_second;
- }
6,给定一个有序数组,然后给定一个数字m,在数组中找出两个数,使得这两个数的和与m相等。这个题目在双指针面前显得轻而易举:
- #include<stdio.h>
- #include<stdlib.h>
- void FindTwoNumbers(int a[], int n, int dest) {
- int *e, *f;
- e = a;
- f = a + n - 1;
- int sum;
- sum = *e + *f;
- while(sum != dest && e < f)
- {
- if(sum < dest) {
- sum = sum - *e + *(++e);
- } else {
- sum = sum - *f + *(--f);
- }
- }
- if(sum == dest) {
- printf("%d=%d+%d\n",dest,*e,*f);
- } else {
- printf("not find\n");
- }
- }
- void main()
- {
- int num[] = {1, 2, 4, 7, 11, 15};
- int temp = 9;
- FindTwoNumbers(num, sizeof(num)/sizeof(int), temp);
- }
7,就是字符串移位问题,这个也用到的双指针,假设给定字符串“abcdefg”,让字符串向做移动三位,得到的结果是:“defgabc”,这个怎么做呢,首先找到分界点,将字符串分为两部分,很自然的分界点应该和移动位数有关,故将字符串分为:abc,defg两部分,先分别将两部分翻转成:cbagfed,然后再将整个字符串翻转:defgabc。
- C++之经典算法-双指针的魅力
- 双指针的魅力
- 双指针的魅力
- 双指针的魅力
- 双指针的魅力
- 指针的魅力
- 指针的魅力
- 指针的魅力
- 指针的魅力
- 指针的魅力
- 指针的魅力
- 指针的魅力
- 指针的魅力
- 指针的魅力
- 指针的魅力
- 指针的魅力
- 指针的魅力
- 经典算法之冒泡指针
- 2012,虎头蛇尾
- 自定义UINavigationBar背景
- hbase的filter集合
- [leetcode] merge k sort list
- POJ 2115 C Looooops
- C++之经典算法-双指针的魅力
- Protocol Buffers学习2
- jQuery常见开发技巧总结
- CABasicAnimation 如何解决保持移动后的位置状态不变
- 传世单机 设置GM账号
- double输出
- sip rport 机制
- web工程各类URL地址的写法
- windows下Qt5安装使用