【Leetcode】287. 寻找重复数(数组模拟链表的快慢指针法)
寻找重复数

根据题意,数组中的数字都在1~n之间,所以数字的范围是小于数组的范围的,数组的元素可以和数组的索引相联系。
例如:nums[0] = 1 即可以将nums[0]作为索引 通过nums[0] 可以访问到nums[1],以此类推。

如左图所示,环的入口就是重复元素。
那么问题就转化为了如何找到入环的第一个节点的问题。时间复杂度为O(n)
慢指针可以定义为:nums[slow] 快指针可以定义为:nums[nums[fast]]
class Solution {
public int findDuplicate(int[] nums) {
int slow = 0;
int fast = 0;
slow = nums[slow];
fast = nums[nums[fast]];
while(slow != fast){
slow = nums[slow];
fast = nums[nums[fast]];
}
fast = 0;
while(slow != fast){
fast = nums[fast];
slow = nums[slow];
}
return slow;
}
}
【下面顺便复习一下关于链表的题】
环形链表
141. 环形链表
public class Solution {
public boolean hasCycle(ListNode head) {
if(head == null || head.next == null || head.next.next == null){
return false;
}
ListNode slow = head.next;
ListNode fast = head.next.next;
while(slow != fast){
if(fast.next == null || fast.next.next == null){
return false;
}
slow = slow.next;
fast = fast.next.next;
}
return true;
}
}
142. 环形链表 II
2. 寻找入环第一个节点:使用快慢指针。快指针走两步,慢指针走一步,一起走到相遇节点后,慢指针不动,快指针回到原点,然后快慢指针再一起一步一步地走,相遇点即入环的第一个节点。
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head == null || head.next == null|| head.next.next == null){
return null;
}
ListNode slow = head.next;
ListNode fast = head.next.next;
while(slow!=fast){
if(fast.next == null || fast.next.next == null){
return null;
}
slow = slow.next;
fast = fast.next.next;
}
fast = head;
while(slow != fast){
slow = slow.next;
fast = fast.next;
}
return slow;
}
}
相交链表
- 一个有环,一个无环:不可能相交
- 两个都无环:需要判断是否相交。相交,则是第一个相交节点。不相交,返回null。
- 两个都有环
- 两个各自一个环:不相交,返回null
- 两个共用一个环
- 先找入环的第一个节点 loop1和loop2
- 入环节点一样:loop1==loop2 可以转化为无环的相交问题,终止节点变成了loop节点。
- 入环节点不一样:loop1继续向下走直到遇到loop2,如果没有遇到则是两个各自一个环。返回loop1或loop2。
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode curA = headA;
ListNode curB = headB;
int lenA = 0, lenB = 0;
while(curA != null){
curA = curA.next;
lenA ++;
}
while(curB != null){
curB = curB.next;
lenB ++;
}
//A始终是长链表
curA = lenA > lenB ? headA:headB;
curB = curA == headA? headB:headA;
int del = Math.abs(lenA - lenB);
while(del > 0){
curA = curA.next;
del--;
}
while(curA!=curB){
if(curA.next == null || curB.next == null){
return null;
}
curA = curA.next;
curB = curB.next;
}
return curA;
}
}
两个都有环相交的情况:
【待续】
【Leetcode】287. 寻找重复数(数组模拟链表的快慢指针法)的更多相关文章
- Java实现 LeetCode 287 寻找重复数
287. 寻找重复数 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找出这个重复的数. 示例 ...
- LeetCode | 287. 寻找重复数
特别感谢LeetCode大佬陈牧远的科普知识 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找 ...
- [LeetCode]287. 寻找重复数(二分)
题目 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找出这个重复的数. 示例 1: 输入: [ ...
- leetcode 287寻找重复数
这道题用STL容器就很好写了,可以用set也可以用map, 用unordered_map的C++代码如下: class Solution { public: int findDuplicate(vec ...
- LeetCode:寻找重复数【287】
LeetCode:寻找重复数[287] 题目描述 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数 ...
- Leetcode之二分法专题-287. 寻找重复数(Find the Duplicate Number)
Leetcode之二分法专题-287. 寻找重复数(Find the Duplicate Number) 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 ...
- 287. 寻找重复数 Java解法
287. 寻找重复数 这题的难点就在于下面的说明了,我们先不管下面的那些说明的要求,用常规的解法来解答下上的题目. 排序思想解法 先把原来的数组进行排序,然后逐个遍历,一旦发现后一个元素和当前的元素相 ...
- UVA11988-Broken Keyboard(数组模拟链表)
Problem UVA11988-Broken Keyboard Accept: 5642 Submit: 34937 Time Limit: 1000 mSec Problem Descripti ...
- C - Boxes in a Line 数组模拟链表
You have n boxes in a line on the table numbered 1 . . . n from left to right. Your task is to simul ...
随机推荐
- codeforce 1311 D. Three Integers
In one move, you can add +1 or −1 to any of these integers (i.e. increase or decrease any number by ...
- POJ - 2387 Til the Cows Come Home (最短路入门)
Bessie is out in the field and wants to get back to the barn to get as much sleep as possible before ...
- 如何将PHP7达到最高性能
PHP7 VS PHP5.6 1. Opcache 记得启用Zend Opcache, 因为PHP7即使不启用Opcache速度也比PHP-5.6启用了Opcache快, 所以之前测试时期就发生了有人 ...
- EOS基础全家桶(十)交易Action操作
简介 区块链上的所有操作都是通过交易(Transaction)上链的,无论你是转账交易还是发起的智能合约的调用,而EOS和传统区块链不同的是EOS在一个交易里可以发起多个行为(Action),这使得E ...
- java运行时跟编译时的区别,欢迎大家指正
个人博客地址:https://blog.csdn.net/qq_41907991 关于java运行时及编译时期的区别: 首先我们要了解编译以及运行的概念: 编译就是指,编译器帮你把源码翻译成机器能识别 ...
- JAVA基础篇 之 finalize()方法的作用
我们知道java有垃圾回收器负责回收无用对象占据的内存资源,但也有特殊情况:假设你的对象(并非使用new)获得了一块特殊的内存区域,由于垃圾回收器只知道回收那些经由new分配的内存,所以它不知道如 ...
- 【大数据 Spark】利用电影观看记录数据,进行电影推荐
利用电影观看记录数据,进行电影推荐. 目录 利用电影观看记录数据,进行电影推荐. 准备 1.任务描述: 2.数据下载 3.部分数据展示 实操 1.设置输入输出路径 2.配置spark 3.读取Rati ...
- 【Kafka】数据分区策略
数据分区策略 四种策略 一.指定分区号,数据会直接发送到所指定的分区 二.没有指定分区号,指定了数据的key,可以通过key获取hashCode决定数据发送到哪个分区 三.都没有指定的话,会采取rou ...
- android实现计时器
新建布局文件activity_main.xml <?xml version="1.0" encoding="utf-8"?> <LinearL ...
- 浅析Spring中AOP的实现原理——动态代理
一.前言 最近在复习Spring的相关内容,刚刚大致研究了一下Spring中,AOP的实现原理.这篇博客就来简单地聊一聊Spring的AOP是如何实现的,并通过一个简单的测试用例来验证一下.废话不 ...