首页 > 编程语言 >[算法]双指针的种种应用

[算法]双指针的种种应用

时间:2023-10-02 13:11:23浏览次数:27  
标签:遍历 ListNode struct 种种 next int 算法 指针

本文使用C语言

Q:为什么要用双指针?

A:因为
通过使用双指针可以使算法的时间复杂度降低(或者降低遍历次数),有时也能降低空间复杂度

分类

根据双指针的用法,可分为前后双指针,头尾双指针,快慢双指针.....


前后双指针

应用一 删除排序数组中的重复项

要求:原地删除,并返回新数组的长度,不需要考虑数组中超出新长度后面的元素。

思路:通过创建一前一后两个指针,前指针指向上一个元素后指针向后历遍,一旦找到不同的元素,前指针指向下一个位置,并视为空位,通过后指针找到目标元素,并存入前指针目前所指向的空位。然后后指针接着遍历,直至遍历整个数组.

//代码实现
int removeDuplicates(int* nums, int numsSize){
    int* left = nums;
    int*right = nums+1;
    int ret = 1;
    //遍历数组
    for (int i=0;i<numsSize-1;i++)
    {
        if(*left != *right)
        {
            left++;
            *left = *right;
            right++;
            ret++;
        }
        else
        {
            right++;
        }
    }
    return ret;
}

分析:这个函数只遍历的一遍数组,没有复制数组,所以时间复杂度O(n),空间复杂度O(1);


头尾双指针

应用一 翻转数组/字符串

关于翻转,首先想到的应该是创建一个等长的空数组,再同时顺序遍历原数组和逆序遍历空数组,逐位储存到空数组,然后再同时顺序遍历两个数组,将已逆序的数组拷贝至原数组

缺点:需要多次遍历,且空间复杂度为O(n)

使用双指针优化:整个数组的翻转可逐步拆解为:第一个和最后一个互换、第二个和倒数第二个互换、、、第N个数和倒数第N个数互换,直至中间。此处便可使用双指针,头尾指针各自一边交换所指向的内容,一边向中间靠近

//代码实现-这里是翻转字符串
void reverseString(char* s, int sSize){
    int *left = s;//头指针
    int *right = s + sSize-1;//尾指针
    while(left<right)//尚未到达中间时
    {
        char tmp = *left;
        *left = *right;
        *right = tmp;
        left++;
        right--;
    }
}

快慢双指针

应用一 删除链表倒数第K个节点

一般解法:先遍历一遍链表获得链表总数N,再二次遍历到N-K处的节点,并执行删除

如何优化:使用快慢双指针,仅需遍历一次,就能用慢指针定位目标节点

//代码实现
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
    //创建哨兵位解决头删问题
    struct ListNode* dummy = (struct ListNode*)malloc(sizeof(struct ListNode));
    dummy->val = 0;
    dummy->next = head;

    struct ListNode* slow = dummy;
    struct ListNode* fast = dummy;
    while (int i = 0;i<n+1;n++)//移动fast
    {
        fast = fast->next;
    }
    
    while(fast != NULL)//同时遍历
    {
        fast= fast->next;
        slow= slow->next;
    }
    //此时slow指向目标节点的前一个节点
    struct ListNode* tmp = slow->next;
    slow->next = slow->next->next;
    free(tmp);
    return dummy->next;
}

应用二 找出并返回链表中间的节点

:偶数个节点时删除前一个中间节点

一般解法:依然是先遍历一遍链表,然后定位中间的节点,二次遍历

如何优化:使用慢指针(一步走一个节点)和快指针(一步走两个节点),二者同时遍历,直至快指针指向NULL或快指针指向尾节点

当遍历结束时,慢指针指向目标中间节点

//代码实现
struct ListNode* middleNode(struct ListNode* head){
    struct ListNode *slow = head;
    struct ListNode *fast = head;
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next; 
    }

    return slow;
}

标签:遍历,ListNode,struct,种种,next,int,算法,指针
From: https://www.cnblogs.com/SDF0521/p/17739864.html

相关文章

  • 深入理解算法与数据结构
    ......
  • 点云配准算法-旋转矩阵估计-Kabsch-Umeyama algorithm
    Kabsch-Umeyamaalgorithm参考文献:https://www.wikiwand.com/en/Kabsch_algorithm面向点云配准,最小化两点集均方根误差(RMSD,rootmeansquareddeviation)来计算最佳旋转矩阵。注:该算法只能计算旋转矩阵,做点云配准还需要计算平移向量。当平移和旋转都正确计算出,该算法有......
  • 【C++】函数重载 ③ ( 为函数指针赋值重载函数 )
    文章目录一、函数指针回顾1、函数指针概念2、函数指针语法3、代码示例-函数指针示例二、为函数指针赋值重载函数1、为函数指针赋值重载函数2、代码示例-为函数指针赋值重载函数博客总结:重载函数:使用相同的函数名,定义不同的函数参数列表;判定标准:只有函数......
  • 算法训练day23 LeetCode669.108.538.
    算法训练day23LeetCode669.108.538.669.修剪二叉搜索树题目669.修剪二叉搜索树-力扣(LeetCode)题解代码随想录(programmercarl.com)递归不能单纯地由根节点的值直接删除单值,需要继续判断子节点是否符合条件classSolution{public:TreeNode*trimBST(T......
  • 文心一言 VS 讯飞星火 VS chatgpt (103)-- 算法导论10.1 1题
    一、用go语言,仿照图10-1,画图表示依次执行操作PUSH(S,4)、PUSH(S,1)、PUSH(S,3)、POP(S)、PUSH(S,8)和POP(S)每一步的结果,栈S初始为空,存储于数组S[1..6]中。文心一言:图10-1展示了在执行一系列栈操作后栈的状态。我会用文字描述来模仿这个图,因为目前我无法直接绘制图片。栈S......
  • 文心一言 VS 讯飞星火 VS chatgpt (103)-- 算法导论10.1 1题
    一、用go语言,仿照图10-1,画图表示依次执行操作PUSH(S,4)、PUSH(S,1)、PUSH(S,3)、POP(S)、PUSH(S,8)和POP(S)每一步的结果,栈S初始为空,存储于数组S[1..6]中。文心一言:图10-1展示了在执行一系列栈操作后栈的状态。我会用文字描述来模仿这个图,因为目前我无法直接绘制图片。栈S初始......
  • KMP字符串匹配算法
    挑战最通俗的KMP算法讲解什么是\(KMP\)KMP是一种用于模式串匹配问题的算法。给出一个文本串和模式串,查询模式串在文本串中的(出现次数、出现位置等等)的问题称为“模式串匹配问题”。KMP算法的本质是:针对模式串构建一个特定的数组,用于在匹配失败时减少后续匹配过程中的无用比......
  • C++常见算法&数据结构模版
    各种常见算法&数据结构模板1.最长不下降子序列(LIS)1.1\(O(n^2)\)做法点击查看代码for(inti=1;i<=n;i++){ cin>>a[i]; dp[i]=1; } for(inti=1;i<=n;i++){ for(intj=1;j<i;j++){ if(a[i]>a[j]){ dp[i]=max(dp[i],dp[j]+......
  • 视频融合/监控汇聚平台EasyCVR助力AI算法智能防溺水,实现水域监管
    防溺水已经成为青少年安全教育的重要内容,同时也是社会各界共同承担的安全管理责任。特别是在夏季,随着天气逐渐转热,溺水事故也进入了危险期、易发期和高发期。传统的预防和管理方法主要通过日常宣传演讲和人工巡逻来提醒人们溺水的危害,但存在一些问题:1)缺乏有效的安全预警设施:当人......
  • AssetDatabase.LoadAssetAtPath 获取FBX资源空指针问题
    问题一 LoadAssetAtPath返回空publicclassProcessModel:AssetPostprocessor{privatevoidOnPostprocessModel(GameObjectinput){if(input.name!="Enemy2b")return;//取得导入模型相关信息ModelImporterimporter=ass......