LeetCode448. Find All Numbers Disappeared in an Array 解答

来源:互联网 发布:windows insider 编辑:程序博客网 时间:2024/05/18 12:04

现在才发现每次提交的时候runtime是不同的,可能这一次提交的runtime是20ms,但是下一次提交的runtime就是18ms了,所以以后还是老老实实用时间复杂度来衡量吧23333

先来看一下题目

Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.

Find all the elements of [1, n] inclusive that do not appear in this array.

Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.
题目大意为:给定一个元素范围为1到n的int型数组,这里的n 是数组的长度,这个数组中的一些元素会出现两次,那就意味着,有些元素不会出现在数组中,你的任务就是找出这些没有出现的元素,并且,要求时间复杂度为O(n),并且不允许开辟其他空间。

Example:

Input:
[4,3,2,7,8,2,3,1]

Output:
[5,6]

解题思路

这道题我想了好久,乍一看好像很简单,一维的数组,1到n的排布,但是加上限制条件之后,一切好像又不是那么简单了。
一开始我想将arraylist遍历1到n来初始化,然后遍历一遍数组将数组里面有的数字从arraylist中剔除,但是我submit的时候竟然告诉我time limit exceeded。。。,我觉得可能是每次采用arraylist.contains()的方法的时候,其实还是遍历了一遍数组的。然后我看了一下contains()方法的源码,果然是这样,所以才会导致超时。
arraylist.contains()的源码:

public boolean contains(Object o) {       return indexOf(o) >= 0;       }    public int indexOf(Object o) {       if (o == null) {           for (int i = 0; i < size; i++)           if (elementData[i]==null)               return i;       } else {           for (int i = 0; i < size; i++)           if (o.equals(elementData[i]))               return i;       }       return -1;       }  

然后我再想了一个办法 ,遍历一次,将元素值-1所表示的位置的值转换为它的负数,然后再遍历一次,如果数组未曾出现过的数字,它的位置+1的值将会是正数,将这个正数加入结果的arraylist将其返回即可,这里要注意判断元素值-1所表示的位置的值是不是负数,是负数了就不用再取它的负数了,因为数组中有的数会出现两次,会导致负负得正。
代码如下:

class Solution {    public List<Integer> findDisappearedNumbers(int[] nums) {        List result=new ArrayList<Integer>();        for(int i=0;i<nums.length;i++){            if(nums[Math.abs(nums[i])-1]>0)                nums[Math.abs(nums[i])-1]*=-1;        }        for(int j=0;j<nums.length;j++){            if(nums[j]>0){                result.add(new Integer(j+1));            }        }        return result;    }}

更好的算法

这里有一个算法,如下:

class Solution {    public List<Integer> findDisappearedNumbers(int[] nums) {        List<Integer> output = new ArrayList<>();        int[] checkArray = new int[nums.length + 1];        for(int i = 0; i < nums.length; i++){            checkArray[i] = 0;         }        for(int i = 0; i < nums.length; i++){            checkArray[nums[i]]++;        }        for(int i = 1; i < checkArray.length; i++){            if(checkArray[i] == 0){                output.add(i);            }        }        return output;    }}

虽然它代码比较长,并且遍历了三遍,但是时间复杂度仍然是O(n) ,从题目要求上来说是没有问题的,但是它形式上更加简单,更加便于理解,所以就把它贴出来吧。

阅读全文
0 0
原创粉丝点击