首页 > 技术文章 > leetcode中快慢指针相关算法问题

dong-qing 2021-03-16 09:20 原文

leetcode中快慢指针相关算法问题

主要有三个

  • q202快乐数
    给定一个正整数,每次将该数替换为它每个位置上数的平方和,重复这个过程直到结果变为1,如果能变为1,这个数就是快乐数。
    最朴素的解法:对这个正整数每个位置的上的数字求平方并求和,直到结果变为1。但这种解法存在问题:如果这个数不是快乐数,就陷入死循环中,这并不是我们想看到的,结合本文主题,可使用快慢指针。
    快慢指针解法:首先我们需要写一个对每个位置上的数字求平方并求和的函数:
private int bitSquareSum(int n) {
   int sum = 0;
   while (n > 0) {
       int bit = n % 10;
       sum += bit * bit;
       n = n / 10;
   }
   return sum;
}

然后我们使用快慢指针:

public boolean isHappy(int n) {
        int slow = n;
        int fast = n;
        do {
            slow = bitSquareSum(slow);
            fast = bitSquareSum(fast);
            fast = bitSquareSum(fast);
        } while (slow != fast);

        return slow == 1;
    }

使用快慢指针思想,slow每次做一次bitSquareSum,fast做两次。
若可以变为1,则必fast先为1,返回true。
若为无限循环,fast每次多做一次bitSquareSum。
假设fast做2n次bitSquareSum后出现循环,则slow必刚好做了n次,并且此时fast与slow相等。
若fast与slow相等了,则说明出现了循环,返回false。

  • 141 环形链表
    判断一个链表是否存在环。
    若链表存在环,则必定有两个指针指向同一个节点
    在这里,我们假设slow=head,fast=head.next,slow每次向前走一步,fast每次向前走两步,即快指针每次都比满指针多走一步,只要这个链表有环,快指针必定会追上慢指针。
public boolean hasCycle(ListNode head) {
        if(head == null || head.next == null){
            return false;
        }
        ListNode slow = head;
        ListNode fast = head.next;
        while(slow!=fast){
            if(fast==null||fast.next==null){
                return false;
            }
                slow=slow.next;
                fast=fast.next.next;
        }
            return true;
    }

在这里思考一个问题,为什么每次快指针都是比慢指针多走一步,两步,三步可以吗?
这里追上可以包括两种意思,一是正好碰到,二是超过。
只要两者有速度差,并且链表有环,快指针追上慢指针是必然的事情。fast每次2步,slow每次两步,它们两的距离每次都会增加一步,如果有环,肯定会相遇。而不是超过。

  • 876 链表的中间结点
    返回一个链表的中间结点,如果有两个中间结点,则返回第二个中间结点。
public ListNode middleNode(ListNode head) {
        ListNode slow = head, fast = head;
        while(fast.next != null){
            fast = fast.next.next == null? fast.next: fast.next.next;
            slow = slow.next;
        }
        return slow;

    }

slow和fast指针刚开始都指向head节点,fast指针每次走两步,slow指针每次走一步。每次需要判断fast指针是否走到结尾。

  • 总结
    当然,以上三个题目肯定存在其他解法比快慢指针解法好。对比一下上面三个题目,发现快指针每次都是比慢指针多走一步。每个题目中具体还需要判断一下临界条件。

推荐阅读