巧用“快指针”、“慢指针”

  有时候处理链表相关问题的时候,定义“快指针”和“慢指针“的方法有时候会极大地提高时间效率。下面是常见的几种使用这个方法的情况。假设不考虑异常输入的情况。

判断一个链表是否有环

  定义两个指针,快指针步长为2,慢指针步长为1.同时从链表头开始出发。如果链表中有环那么他们必然相遇。

 1 bool hasCycle(ListNode *head) {
 2     if(!head)
 3         return false;
 4     ListNode* fast = head->next;
 5     ListNode* slow = head;
 6     while(fast) {
 7         if(fast == slow)
 8             return true;
 9         if(fast->next&&fast->next->next){
10             fast = fast->next->next;
11             slow = slow->next;
12         }
13         else
14             return false;
15     }
16     return false;
17 }

  

求链表中倒数第k个结点

  假设链表长度为n,那么我们轻松得出这些结论:链表中的倒数第k个结点也就是正数第n-(k-1)个结点。所以我们只需要正向的让指针走n-k次,那么指针停留的结点便是倒数第k个结点。走完这个链表需要走的步长是n-1。

  我们定义两个指针,快指针先出发,走k-1步。此时它停在正数第k个结点上。慢指针也开始从链表头出发。两个指针步长都为1,走到快指针为NULL为止。快指针停止时他走的第二段路的长度就是慢指针的长度:(n-1)-(k-1)= n-k.根据第一段的推导可知此致慢指针的指向便是倒数第k个结点。

 1 ListNode* find(ListNode* head,int k)
 2 {
 3     if(!head)
 4         return NULL;
 5     ListNode* fast = head;
 6     ListNode* slow = head;
 7     for(int i=0;i<k-1;++)
 8         fast = fast->next;
 9     while(fast)
10     {
11         fast = fast->next;
12         slow = slow->next;
13     }
14     return slow;
15 }

求链表的中间结点

  这个比较简单。也是定义两个指针,快指针步长为2,慢指针步长为1。同时从head出发,当快指针为NULL时,慢指针就停在中间结点了。

 1 ListNode* findMid(ListNode* head)
 2 {
 3     if(!head)
 4         return NULL;
 5     ListNode* fast = head;
 6     ListNode* slow = head;
 7     while(fast = fast->next)
 8     {
 9         fast = fast->next;
10         slow = slow->next;
11     }
12     return slow;
13 }
时间: 2024-10-14 01:45:17

巧用“快指针”、“慢指针”的相关文章

链表操作时巧用指针的指针

比如在插入有序链表的过程中,一般情况下要使用俩指针来遍历,而后还要判断是否在第一个位置插入:利用指针的指针后不需要另外考虑这种特殊情况. 代码: #include <stdio.h> #include <stdlib.h> struct node{ int data; struct node *next; } *head; //sorted link-list void insert(struct node *new_node){ struct node *cur = head,

详解 常量指针和指针常量

说一下 常量指针和指针常量 的区别. 常量指针 指向常量的指针,也就是说指针指向的对象是常量,指向的常量不能修改.指针不是一个常量, 可以把指针指向别一个常量. 常量指针是我们最常用的,一般声明形式如下: const int *p; int const *p; 例: int a(1), b(3); const int *p; // 或者是 int const *p; p = &a; std::cout << "address : " << p <&

数组指针和指针数组的区别

数组指针(也称行指针) 定义 int (*p)[n]; ()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长.也就是说执行p+1时,p要跨过n个整型数据的长度. 如要将二维数组赋给一指针,应这样赋值: int a[3][4]; int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组. p=a;        //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0] p++;       //该语句执行过后,也就是

【转】让你不再害怕指针——C指针详解(经典,非常详细)

前言:复杂类型说明 要了解指针,多多少少会出现一些比较复杂的类型,所以我先介绍一下如何完全理解一个复杂类型,要理解复杂类型其实很简单,一个类型里会出现很多运算符,他们也像普通的表达式一样,有优先级,其优先级和运算优先级一样,所以我总结了一下其原则:从变量名处起,根据运算符优先级结合,一步一步分析.下面让我们先从简单的类型开始慢慢分析吧: [cpp] view plain copy int p; //这是一个普通的整型变量 int *p; //首先从P 处开始,先与*结合,所以说明P 是一个指针,

数组指针、指针数组、函数指针、指针函数 -----笔记

1.数组的四种访问方式 定义数组 a[]; 指针 *p 指向数组a; (1) 利用数组的下表进行访问 a[i]; (2) 数组名+地址的偏移量i *(a+i) (3) 利用指针 p 进行下表访问 p[i] (4) 指针p + 地址的偏移量i *(p+i) 一维数组数组名:相当于一个单指针 2. 数组指针(指针)     指针数组(数组) 函数指针(指针)     指针函数(函数)    -------->只看后边两个字就能够区分是指针还是数组或函数 _______________________

(C/C++)区别:数组与指针,指针与引用

1.数组跟指针的区别 数组要么在静态存储区被创建(如全局数组),要么在栈上被创建.数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变. 指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动态内存.指针远比数组灵活,但也更危险. 数组和指针特点的简单比较: 数组 指针 保存数据 保存地址 直接访问数据 间接访问数据,先取得指针的内容,然后以它为地址取得数据 用于存储数目固定且类型相同的数据 通常用于动态数据结构 编译器自动分配和删除

函数指针和指针函数

(1)函数指针 函数指针就是指向函数的指针变量,即本质是一个指针变量. int (*f) (int x); /* 声明一个函数指针 */ f=func; /* 将func函数的首地址赋给指针f */ 指向函数的指针包含了函数的地址,可以通过它来调用函数.声明格式如下:        类型说明符 (*函数名)(参数) (2)指针函数 指针函数是指带指针的函数,即本质是一个函数.函数返回类型是某一类型的指针 类型标识符 *函数名(参数表) int *f(x,y);

指针与指针变量

一.指针与指针地址 1. 地址 计算机的内存被划分成一个个存储单元,这些存储单元按一定的规则编号,这个编号就是存储单元的地址.每个存储单元大小为一个字节,每个单元的地址是唯一的. 2. 变量的地址 在程序中所有的变量都要分配相应的存储单元,不同数据类型所需要的存储空间的大小不同.系统分配给变量的内存空间的起始单元单元地址称为该变量的地址. 例如: int a; 假设分配给a的4个存储单元编号为0x300.0x301.0x302.0x303,如图,则0x303称为变量a的地址. 3. 指针 变量在

第32课 数组指针和指针数组分析

1. 数组的类型 (1)C语言中的数组有自己特定的类型 (2)数组的类型由元素类型和数组大小共同决定.(如int array[5]类型为int[5]) 2. 定义数组类型 (1)C语言中通过typedef为数组类型重命名:typedef type(name)[size]; ①数组类型:如typedef int (AINT5)[5]; typedef float (AFLOAT10)[10]; ②数组定义:AINT5 iArray; AFLOAT10 fArray; 3. 数组指针 (1)数组指针

指针的含义——指针变量、指针的指针、指针使用的注意

指针其实很容易理解的,其他并不是大家想象的那么神奇,那么难. 一.指针的含义:指针其实就是一个变量,它所存放的不是数据,而是数据在内存中地址.当然指针也可以存放函数(方法)的地址,后面会讲到的.声明指针的关键符是*号,指向地址的关键符是&. 二.指针变量: 例如1:#include <stdio.h> int main {  int a =10;   //第一一个变量a,赋值为10 int *p = &a;   //p就是一个指针变量,所指向的就是变量a的地址 printf(&