寻找重复数

根据题意,数组中的数字都在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. 环形链表

1. 判断是否有环的思路:使用快慢指针。快指针走两步,慢指针走一步,最终快慢指针在环上相遇,且绕圈小于两圈。
 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;
}
}

相交链表

3. 找出两个链表相交的第一个节点
两个链表的三种可能情况:
  1. 一个有环,一个无环:不可能相交
  2. 两个都无环:需要判断是否相交。相交,则是第一个相交节点。不相交,返回null。
  3. 两个都有环
    1. 两个各自一个环:不相交,返回null
    2. 两个共用一个环
      1. 先找入环的第一个节点 loop1和loop2
      2. 入环节点一样:loop1==loop2 可以转化为无环的相交问题,终止节点变成了loop节点。
      3. 入环节点不一样:loop1继续向下走直到遇到loop2,如果没有遇到则是两个各自一个环。返回loop1或loop2。
 
两个都无环相交的情况:
思路:如果两个链表相交,那么末尾的节点一定是同一个,因为一个节点只有一个出度。假设长链表长len1,短链表长len2,长链表先走len1-len2步,短链表从回到起点跟着一起走,相遇点即交点。
 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. 寻找重复数(数组模拟链表的快慢指针法)的更多相关文章

  1. Java实现 LeetCode 287 寻找重复数

    287. 寻找重复数 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找出这个重复的数. 示例 ...

  2. LeetCode | 287. 寻找重复数

    特别感谢LeetCode大佬陈牧远的科普知识 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找 ...

  3. [LeetCode]287. 寻找重复数(二分)

    题目 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找出这个重复的数. 示例 1: 输入: [ ...

  4. leetcode 287寻找重复数

    这道题用STL容器就很好写了,可以用set也可以用map, 用unordered_map的C++代码如下: class Solution { public: int findDuplicate(vec ...

  5. LeetCode:寻找重复数【287】

    LeetCode:寻找重复数[287] 题目描述 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数 ...

  6. Leetcode之二分法专题-287. 寻找重复数(Find the Duplicate Number)

    Leetcode之二分法专题-287. 寻找重复数(Find the Duplicate Number) 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和  ...

  7. 287. 寻找重复数 Java解法

    287. 寻找重复数 这题的难点就在于下面的说明了,我们先不管下面的那些说明的要求,用常规的解法来解答下上的题目. 排序思想解法 先把原来的数组进行排序,然后逐个遍历,一旦发现后一个元素和当前的元素相 ...

  8. UVA11988-Broken Keyboard(数组模拟链表)

    Problem UVA11988-Broken Keyboard Accept: 5642  Submit: 34937 Time Limit: 1000 mSec Problem Descripti ...

  9. 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 ...

随机推荐

  1. 腾讯技术工程 | 基于Prophet的时间序列预测

    预测未来永远是一件让人兴奋而又神奇的事.为此,人们研究了许多时间序列预测模型.然而,大部分的时间序列模型都因为预测的问题过于复杂而效果不理想.这是因为时间序列预测不光需要大量的统计知识,更重要的是它需 ...

  2. How to get binary string from ArrayBuffer?

    https://stackoverflow.com/questions/16363419/how-to-get-binary-string-from-arraybuffer https://stack ...

  3. libevent(十三)evhttp事件处理流程

    在libevent(六)http server中,作为一个单线程http server,不仅要监听每个连接的到来,还要监听每个连接上的I/O事件. 查看源码可知,在evhttp_bind_socket ...

  4. 高精度封装Bignum

    还没有写完,目前只实现了加,乘,且不能作用于负数 \(update\ in 20.4.8 添加了高精除低精ddiv函数,比较大小comp函数\) #include <bits/stdc++.h& ...

  5. HDU1300Pearls

    传送门 描述: 有几种不同的珍珠.每种珍珠都有它的单价.当然质量高的珍珠价格一定也是高的. 为了避免买家只买1个珍珠.就要求不论是买了多少个珍珠都是需要在购买数量上加10.之后乘上单价. 例如:买5个 ...

  6. C. Journey bfs 拓扑排序+dp

    C. Journey 补今天早训 这个是一个dp,开始我以为是一个图论,然后就写了一个dij和网络流,然后mle了,不过我觉得如果空间开的足够的,应该也是可以过的. 然后看了题解说是一个dp,这个dp ...

  7. MATLAB矩阵处理—特殊矩阵

    需要掌握 MATLAB语言中特殊矩阵 MATLAB语言中矩阵的变幻 MATLAB语言矩阵如何求值 MATLAB语言中特征值与特征向量 MATLAB语言中稀疏矩阵 2.1  特殊矩阵 如何建立矩阵? 逐 ...

  8. 王颖奇 201771010129《面向对象程序设计(java)》第八周学习总结

    实验六 接口的定义与使用 实验时间 2018-10-18 1.实验目的与要求 (1) 掌握接口定义方法: (2) 掌握实现接口类的定义要求: (3) 掌握实现了接口类的使用要求: (4) 掌握程序回调 ...

  9. 字节码编程,Javassist篇一《基于javassist的第一个案例helloworld》

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 目录 @ 目录 目录 一.前言 二.开发环境 三.案例目标 四.技术实现 五.测试结果 1. ...

  10. 如何使用apt-get在ubuntu系统上安装OpenJDK 8

    文章目录 添加ppa仓库 设置openjdk版本 查看java 版本 Android 8.1 系统编译的时候需要安装OpenJDK 8,这里如果可以自己下载源码编译安装,当然本想编译Android系统 ...