寻找重复数

根据题意,数组中的数字都在1~n之间,所以数字的范围是小于数组的范围的,数组的元素可以和数组的索引相联系。

例如:nums[0] = 1 即可以将nums[0]作为索引 通过nums[0] 可以访问到nums[1],以此类推。

如左图所示,环的入口就是重复元素。

那么问题就转化为了如何找到入环的第一个节点的问题。时间复杂度为O(n)

慢指针可以定义为:nums[slow] 快指针可以定义为:nums[nums[fast]]

  1. class Solution {
  2. public int findDuplicate(int[] nums) {
  3. int slow = 0;
  4. int fast = 0;
  5. slow = nums[slow];
  6. fast = nums[nums[fast]];
  7. while(slow != fast){
  8. slow = nums[slow];
  9. fast = nums[nums[fast]];
  10. }
  11. fast = 0;
  12. while(slow != fast){
  13. fast = nums[fast];
  14. slow = nums[slow];
  15. }
  16. return slow;
  17. }
  18. }

【下面顺便复习一下关于链表的题】

环形链表

141. 环形链表

1. 判断是否有环的思路:使用快慢指针。快指针走两步,慢指针走一步,最终快慢指针在环上相遇,且绕圈小于两圈。
  1. public class Solution {
  2. public boolean hasCycle(ListNode head) {
  3. if(head == null || head.next == null || head.next.next == null){
  4. return false;
  5. }
  6. ListNode slow = head.next;
  7. ListNode fast = head.next.next;
  8. while(slow != fast){
  9. if(fast.next == null || fast.next.next == null){
  10. return false;
  11. }
  12. slow = slow.next;
  13. fast = fast.next.next;
  14. }
  15. return true;
  16. }
  17. }

142. 环形链表 II

2. 寻找入环第一个节点:使用快慢指针。快指针走两步,慢指针走一步,一起走到相遇节点后,慢指针不动,快指针回到原点,然后快慢指针再一起一步一步地走,相遇点即入环的第一个节点。

  1. public class Solution {
  2. public ListNode detectCycle(ListNode head) {
  3. if(head == null || head.next == null|| head.next.next == null){
  4. return null;
  5. }
  6. ListNode slow = head.next;
  7. ListNode fast = head.next.next;
  8. while(slow!=fast){
  9. if(fast.next == null || fast.next.next == null){
  10. return null;
  11. }
  12. slow = slow.next;
  13. fast = fast.next.next;
  14. }
  15. fast = head;
  16. while(slow != fast){
  17. slow = slow.next;
  18. fast = fast.next;
  19. }
  20. return slow;
  21. }
  22. }

相交链表

3. 找出两个链表相交的第一个节点
两个链表的三种可能情况:
  1. 一个有环,一个无环:不可能相交
  2. 两个都无环:需要判断是否相交。相交,则是第一个相交节点。不相交,返回null。
  3. 两个都有环
    1. 两个各自一个环:不相交,返回null
    2. 两个共用一个环
      1. 先找入环的第一个节点 loop1和loop2
      2. 入环节点一样:loop1==loop2 可以转化为无环的相交问题,终止节点变成了loop节点。
      3. 入环节点不一样:loop1继续向下走直到遇到loop2,如果没有遇到则是两个各自一个环。返回loop1或loop2。
 
两个都无环相交的情况:
思路:如果两个链表相交,那么末尾的节点一定是同一个,因为一个节点只有一个出度。假设长链表长len1,短链表长len2,长链表先走len1-len2步,短链表从回到起点跟着一起走,相遇点即交点。
  1. public class Solution {
  2. public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
  3. ListNode curA = headA;
  4. ListNode curB = headB;
  5. int lenA = 0, lenB = 0;
  6. while(curA != null){
  7. curA = curA.next;
  8. lenA ++;
  9. }
  10. while(curB != null){
  11. curB = curB.next;
  12. lenB ++;
  13. }
  14. //A始终是长链表
  15. curA = lenA > lenB ? headA:headB;
  16. curB = curA == headA? headB:headA;
  17. int del = Math.abs(lenA - lenB);
  18. while(del > 0){
  19. curA = curA.next;
  20. del--;
  21. }
  22. while(curA!=curB){
  23. if(curA.next == null || curB.next == null){
  24. return null;
  25. }
  26. curA = curA.next;
  27. curB = curB.next;
  28. }
  29. return curA;
  30. }
  31. }

两个都有环相交的情况:

【待续】

【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. GPTL—练习集—006树的遍历

    #include<bits/stdc++.h> using namespace std; typedef int daTp;//datatype typedef struct BTNode ...

  2. Linux下Wiki服务器的搭建

    一.准备工作 1.软件下载和安装 最主要的就是安装好Mysql+apache+PHP 测试apache能够解析index.php文件后就可以. mysql安装好后: adduser wiki   #给 ...

  3. #Week7 Neural Networks : Learning

    一.Cost Function and Backpropagation 神经网络的损失函数: \[J(\Theta) = - \frac{1}{m} \sum_{i=1}^m \sum_{k=1}^K ...

  4. Java——Java自动装箱和拆箱

    一.什么是自动装箱和拆箱: 我们知道java为8种基本类型分别提供了对应的包装类型,在Java SE5之前,如果要生成一个数值为10的Integer对象,必须这样进行: Integer i=new I ...

  5. Java——运算符那些事

    && 逻辑与 &&先运算&&左边的算式,如果为假,则直接停止,后面不管有多少运算式都不再运算,如果为真则继续判断后面的式子,只有所有的条件全部成立,才会 ...

  6. .net core HttpClient 使用之掉坑解析(一)

    一.前言 在我们开发当中经常需要向特定URL地址发送Http请求操作,在.net core 中对httpClient使用不当会造成灾难性的问题,这篇文章主要来分享.net core中通过IHttpCl ...

  7. Golang遍历删除数组

    Golang 做数字切片 package main import "fmt" /*遍历删除数组示例*/ func main() { //定义一个数组 a1 := []int{1, ...

  8. srping mvc RequestMapping实现

    spring mvc中定义请求的url只需要在方法上添加注解: @RequestMapping("aa.mvc")即可定义访问的url地址,但是你是否有考虑过为什么添加这个注解就可 ...

  9. Docker学习笔记(二):端口映射与容器互联

    端口映射 使用docker run时,可以指定-P(大写)与-p(小写)参数映射端口. docker run -P -P(大写)会随机映射一个端口到容器的内部端口 -> [feifei@ffma ...

  10. python实现登录密码重置简易操作

    需求: 1.用户输入密码正确登录 2.用户输入密码错误退出并调用函数继续输入 3.用户输入密码符合原先给定的一个值时,允许用户重置密码,并且可以用新密码登录 4.输入三次后禁止输入 虽然贴别的简单,但 ...