• 七日算法先导(二)——双指针


    作业解答

    昨天作业都比较简单,我挑几个小伙伴反应的疑惑说一下:
    增量元素之间的最大差值

    int max(int a,int b){    
        return a>b?a:b;
    }
    int min(int a,int b){
        return a<b?a:b;
    }
    
    int maximumDifference(int* nums, int numsSize){
        int maxS = -1;//最大差为-1
        int minS = nums[0];//最小元素为nums[0]
    
        //遍历数组,时间复杂度为O(n)
        for(int i = 1; i<numsSize;i++){
            int sub = nums[i] -minS;
            if(sub > 0){
                //更新
                maxS = max(sub,maxS);
            }
    
            //更新最小
            minS = min(nums[i],minS);
        }
        return maxS;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    其中这个最小元素为啥要初始化为nums[0],简单的来说我们是从左到右遍历数组的,nums[i]每次减minS,假设minS初始化为其他值,那么可能出现跳过第一个值或者初始值不在数组中的情况

    674. 最长连续递增序列 - 力扣(LeetCode)

    class Solution {
        public int findLengthOfLCIS(int[] nums) {
            //双指针(假的滑动窗口)
            if(nums == null || nums.length == 0)    return 0;
            
            int i = 0, j = 1, ans = 1;
            while(j < nums.length){
                if(nums[j] > nums[j-1]){
                    j++;
                }else{
                    i = j;
                    j++;
                }
                ans = Math.max(ans, j-i);
            }
            return ans;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    昨天这个题,就可以考虑用双指针来写,当然昨天的暴力解法也是正确的。

    思路:
    当nums[j] > nums[j-1] 的时候就是左边大于本身满足条件,j++
    否则的话,就不连续了,i变为j
    最后比较最长序列,ans,和,j-i中选取最大的

    概念

    参考我之前写过的这篇文章:
    从0到1入门双指针

    入门是不够的,下面我们来看双指针的三种情况:

    1. 数组相向追赶
    2. 数组相向逼近
    3. 链表快慢指针(有点难)

    数组相向追赶

    俩个指针,i可以一直往前走,但是j只有当满足条件的时候才往前走

    数组相向逼近

    一般来说,俩个指针从数组的俩端开始,不断的去check是否满足条件,根据不同的条件,来选择是左指针自增,还是右指针自减

    链表快慢指针

    快慢指针,顾名思义,定义俩个指针,一个指针可以走的很快,另一个相对走的较慢,当快指针走到链表结尾,慢指针对应的节点,获取一些信息,从而解决一些问题。

    slow = slow.next;
    fast = fast.next.next;
    
    
    • 1
    • 2
    • 3

    假设快慢指针原来都指向头结点,这样的话,fast指针移动速度就是slow指针的两倍,这是很有用的设计

    例如:
    找到链表中点

    int length = 0;
    ListNode node = head;
    // 遍历一遍链表得到链表长度
    while(node!=null){
        node = node.next;
        length ++;
    }
    // 根据得到的链表长度,可以遍历长度/2次来找到终点
    ListNode centerNode = head;
    for(int i=0;i<length/2-1;i++){
        centerNode = centerNode.next;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    上面的方法遍历了N+N/2次,且代码略显复杂,最后遍历长度/2次时,要注意centerNode节点实际上是中点的下一个节点,所以可以让遍历次数-1来得到中点.

    下面是使用了快慢节点的做法:

    // 快慢指针起点相同
    ListNode slow = head;
    ListNode fast = head;
    while(fast.next!=null && fast.next.next!=null){
        slow = slow.next;
        // 快指针移动速度为慢指针两倍
        fast = fast.next.next;
    }
    // 当快指针到达链表表尾时,此时慢指针指向链表中点
    ListNode centerNode = slow;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    刷题巩固

    双调序列
    判断子序列
    排列排序
    俩数之和||

  • 相关阅读:
    HTML5+CSS3小实例:纯CSS实现奥运五环
    基于stm32单片机自动灭火火灾报警装置Proteus仿真
    一台服务器成了哆啦A梦的神奇口袋
    外汇天眼:如何识别外汇欺诈?你也可以拥有“火眼金睛”一步识别黑平台!
    python学习--特殊方法和属性
    如何防止html转义函数
    一个注解实现SpringBoot接口定制属性加解密
    系统架构师第一部分——架构设计基础
    java计算机毕业设计动漫论坛系统MyBatis+系统+LW文档+源码+调试部署
    面试题整理:如何判断一个对象是否属于某个类?
  • 原文地址:https://blog.csdn.net/weixin_45920495/article/details/126114028