[LeetCode] 448. Find All Numbers Disappeared in an Array 找到數組中消失的數字

題目描述

給定n個數字的數組,裏面的值都是1-n,可是有的出現了兩遍,所以有的沒有出現,求沒有出現值這個數組中的值有哪些。java

要求不能用額外的空間(除了返回列表以外),時間複雜度n數組

思路

由於不能用額外空間而且時間是O(n),因此不能用排序或者hashapp

經過在對應位置的值去肯定下一個位置,一直到遍歷完。其實本身也沒有很成熟的思想。code

好比對於[4,3,2,7,8,2,3,1]:
A[0],4===>找到a[3],7===>a[6],3===>a[2]======注意有可能出現循環,行不通。排序

原本覺得行不通,後來通過思考,能夠行得通,只不過複雜度是O(k*n),k是重複的數字的個數,也是缺乏的數字的個數。思路是這樣的A[0],4,而且把A[0]標記爲-1===>a[3],7並把4放到a[3]===>a[6],3,把7放到a[6],===>a[2],2,把3放到a[2]===>a[1],3,把2放到a[3],===>想把3放到a[2],只是a[2]已經=3,因此3是數組中重複的。一個循環結束,從A[0]又開始,找到!=-1,而且!=i+1的a[i],把裏面的值放到對應的位置上。一直到全部位置不是-1就是i+1結束。位置是-1的,對應空缺數值i+1。hash

代碼

public static List<Integer> findDisappearedNumbers(int[] nums) {
        List<Integer> result=new ArrayList<>();
        boolean isEnding=false;//用isEnding檢查是否全部位置不是-1就是i+1
        boolean isExist=false;//是否從上一個位置取出了數字
        int i=0;//表明找到的位置
        while(!isEnding){
            isEnding=true;
            i=0;
            while(i<nums.length){
                if((nums[i]!=i+1)&&(nums[i]!=-1)){//沒有重複,能夠放進去
                    isEnding=false;
                    int tmp=nums[i];
                    if(isExist){//若是有能夠放進去的值,就先取出來再放進去
                        nums[i]=i+1;
                    }else{//不然,只能取出來,並把-1放進去
                        nums[i]=-1;
                    }
                    i=tmp-1;
                    isExist=true;
                }else{//若是相等,那麼就重複了不須要放進去,直接往前面去;碰到了-1,若是須要放進去,就先放進去,再日後面去
                    if(isExist&&nums[i]==-1){
                        nums[i]=i+1;
                    }
                    i++;
                    isExist=false;
                }
            }
        }
        for(i=0;i<nums.length;i++){
            if(nums[i]==-1){
                result.add(i+1);
            }
        }
        return result;
}

分析

看了看solution,是把全部的對應值的對應位置上的值都置爲相反數:nums[|nums[i]| -1] = -|nums[|nums[i]|-1]|,若是第二次遍歷發現它>0,那麼它是沒見過的。好比[4,3,2,7,8,2,3,1],遍歷一遍以後,獲得[-4,-3,-2,-7,8,2,-3,-1],因此是八、2對應位置的數值沒有在數組出現過,也就是5,6io

相關文章
相關標籤/搜索