首页 > 其他分享 >1.双指针

1.双指针

时间:2023-02-17 17:22:26浏览次数:47  
标签:head ListNode val nums next 指针

1.双指针

目录

1.1 什么是双指针

双指针,指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个相同方向(快慢指针)或者相反方向(对撞指针)的指针进行扫描,从而达到相应的目的。


1.2 对撞指针

对撞指针是指在数组中,将指向最左侧的索引定义为左指针(left),最右侧的定义为右指针(right),然后从两头向中间进行数组遍历。
对撞数组适用于连续数组和字符串,也就是说当你遇到题目给定连续数组和字符床时,应该第一时间想到用对撞指针解题

15. 三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

原题

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> result;
        sort(nums.begin(),nums.end());
        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] > 0){
                return result;
            }
            if (i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }
            int left = i + 1;
            int right = nums.size() - 1;
            while (left < right) {
                if (nums[i] + nums[left] + nums[right] > 0) {
                    right--;
                }
                else if (nums[i] + nums[left] + nums[right] < 0) {
                    left++;
                } else {
                    result.push_back(vector<int>{nums[i], nums[left], nums[right]});
                    while (right > left && nums[right] == nums[right - 1]) right--;
                    while (right > left && nums[left] == nums[left + 1]) left++;
                    right--;
                    left++;
                }
            }
        }
        return result;
        
    }
};

思路见代码回想录题解
视频
也算是对撞指针了

1.3 快慢指针

快慢指针也是双指针,但是两个指针从同一侧开始遍历数组,将这两个指针分别定义为快指针(fast)和慢指针(slow),两个指针以不同的策略移动,直到两个指针的值相等(或其他特殊条件)为止,如 fast 每次增长两个,slow 每次增长一个。

83. 删除排序链表中的重复元素

给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。
原题

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if (!head) {
            return head;
        }
        ListNode *dummy = new ListNode();
        ListNode *tail = dummy;
        while(head != NULL) {
            while(head->next != NULL && head->val == head->next->val) {
                head = head ->next;
            }
            if (head->next == NULL || head->val != head->next->val) {
                tail ->next = head;
                tail = head; 
            }
            head = head->next;
        }
        tail->next = NULL;
        return dummy->next;
    }
};

82. 删除排序链表中的重复元素 II

给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。

原题

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if (!head) {
            return head;
        }
        ListNode *dummy = new ListNode();
        ListNode *tail = dummy;
        while (head != NULL) {
            if (head->next == NULL || head->val != head->next->val) {
                tail->next = head;
                tail = head;
            }
            while (head->next != NULL && head->val == head->next->val) {
                head = head->next;
            }
            head = head->next;
        }
        tail->next = NULL;
        return dummy->next;
    }
};

这两道题都是用了一个算是快慢指针的思想吧

三叶老师的关于链表类题目的通解

基本思路:
几乎所有的链表题目,都具有相似的解题思路。

  1. 建一个「虚拟头节点」dummy 以减少边界判断,往后的答案链表会接在 dummy 后面

  2. 使用 tail 代表当前有效链表的结尾

  3. 通过原输入的 head 指针进行链表扫描


看题解可以看懂,但真的好难想到啊没搞明白...
还得再练练
sigma

标签:head,ListNode,val,nums,next,指针
From: https://www.cnblogs.com/romgk-blog/p/17130909.html

相关文章

  • 指针类型
    指针声明TypeTmingRi=^integer;vars1.s2:^string;s3:string;beginnew(s1);new(s2);s1^:='MingRiSoft';s2^:='kaihongliu';s1:=s2;......
  • D. Moving Dots(组合数学,贡献,二分/双指针)
    题目https://codeforces.com/contest/1788/problem/D思路从题目给的“2”这个信息入手,从贡献这个方面来考虑对于任意两不同的点,具有一定的范围,让这个范围内的点都被......
  • 字符指针与字符数组的复习
    遇到的刷题题目,给定sec秒,将其转换为时分秒输出,规定了函数形式为char*timeTrans(intsec)且需要返回修改的字符串首地址#include<stdio.h>char*timeTrans(intsec,c......
  • 关于指针Splay
    关于指针Splay目录关于指针Splay更好的阅读体验戳此进入写在前面操作核心节点UpdateGetDirRotateSplayInsertFindDeleteFindRankByValFindValByRankFindPreFindNxtCodeTOD......
  • c++学习7 指针与数组
    一二维数组与数组指针的关系二维数组名,代表的是第0行的行地址,“+1”是跳过一个行。而取“*”的话,则是在当前行地址基础上再取列地址,那么如果我们再取一个“*”呢?就会......
  • 指针
    指针也就是内存地址,指针变量是用来存放内存地址的变量(1)指针变量的声明​ 指针类型声明的一般格式为:Type指针类型名=^类型;​ New过程创建一个新的动态变量,并把指......
  • springboot在test的时候,new的类报空指针
    ok@ComponentpublicclassFifthGithubCrawler{@AutowiredprivateKBComponentVersionRepositoryversionRepository;/***导出所有数据到json......
  • c++函数指针
    函数的地址是存储其机器语言代码的内存的开始地址。通常,这些地址对用户而言,既不重要,也没有什么用处,但对程序而言,却很有用。例如,可以编写将另一个函数的地址作为参数的函数。......
  • linux内核之指针打印函数
    linux内核打印函数:define_netdev_printk_level(netdev_info,KERN_INFO);netdev_info:输入形参,指针函数;实际使用方法: ......
  • C经典 关于一维数组指针
    说明:1)一维数组指针表示方法int*p=a而非int*p=&a也可int*p=&a[0]表示2)p+1或a+1表示的是指向下一个地址#include<stdio.h>intmain(intargc,const......