LeetCode刷题实况(三):双指针算法

双指针算法在做题时经常用到:对于线性的数据结构可使用双指针算法,主要形式为从左向右和两面向中间。
一、从两面向中间:适用于寻秩访问,确定开头秩与结尾秩,根据一定的条件,移动两个指针。多用于向量数据结构。双向链表知道头尾节点也可以。

这里拿《剑指offer》中的“调整数组顺序使奇数排在偶数前”为例
题目链接:调整数组顺序使奇数排在偶数前
代码如下:

class Solution {
    public int[] exchange(int[] nums) {
        if(nums.length <= 1) return nums;
        int first = 0;
        int last = nums.length - 1;
        while(first < last){
            while((nums[first] % 2 == 1) && (first < last)){
                first++;
            }
            while((nums[last] % 2 == 0) && (first < last)){
                last--;
            }
            swap(nums, first, last);
        }
        return nums;
    }
    public void swap(int[] nums, int first, int last){
        int temp = nums[first];
        nums[first] = nums[last];
        nums[last] = temp;
    }
}

在这里插入图片描述
本题的意思是,将所有的奇数都放在前面,偶数都放在后面。看到这个你想到了什么?快排对不对?这就是快排中排序思想的一个变种。

begin指针开始向后移动,满足一定条件时停止,这样begin指针走过的数据都满足这个条件。然后end指针开始向前移动,满足另一个需求时停止,进行一些操作(当然这两个需求也可以相同,详情可见该题:两数之和)。当begin等于或大于end指针时,退出循环。这样begin走过的路都是满足条件1,end走过的路都满足条件2,不满足的都被交换了。

这个条件,并不一定是,比大小,也可能像本题比奇偶。需要根据题目灵活运用。
总结:核心要义在于,找到数据的要求,根据一些大小或者奇偶关系,挪动两个指针。这里驱动指针可以是由循环++驱动,也可以是由结果数据进行驱动。

简单一句话就是通过数据来驱动指针。
二、同向双指针:也叫做快慢指针,通过一个快指针向前遍历,来满足条件,驱动慢指针向前移动。

这里用《剑指offer》中的面试题22来解释
题目链接:链表中倒数的第K个节点
在这里插入图片描述
代码如下:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode getKthFromEnd(ListNode head, int k) {
        if(head == null) return head;
        ListNode low = null;
        ListNode temp = head;
        while(k-- > 0){
            head = head.next;
        }
        low = temp;
        while(head != null){
            head = head.next;
            low = low.next;
        }
        return low;
    }
}

这个题惭愧的说,我第一反应是用栈,虽然也能用,但是会慢,时间复杂度是N(链表长度)但是入栈出栈操作,确实相对这个耗费时间。

该题中使用算法的技巧:快慢指针之间满足长度为k的条件,那我们只需要满足当快指针走了k步后,才开始驱动慢指针向前走,当快指针到null时,慢指针刚好到达我们想要的节点。
总结:同向双指针是由快指针触发条件,使慢指针向前移动,只需要快指针遍历一次,即可得到我们想要的结果。
三、总结:无论是单向还是双向双指针,都是有快/左指针去触发一个条件(如上面的偶数或到达第k步)然后来驱动慢指针移动,进而得到我们想要的结果。这里双向可以用单向的方式写。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值