LeetCode 解答 #41. First Missing Positive プログラミング練習

問題:
f:id:stlisacity:20180613175728p:plain
難易度: hard
入力: int 型array[]
目的: 欠けた一番小さい正数を求めよ
出力: int

入力の中に含まれていない一番小さい正数を探す問題です。
例えば入力が[3,4,-1,1]であった場合、
欠けた一番小さい正数は2です。
マイナス部分と0は無視してかまいません。
一見簡単な問題に見えますが、
時間をO(n), メモリーをO(1)に抑えなければならないのでソートが出来ません。
この制限により難易度が一気に上がります。

注意すべき事: 

  • 入力はソートされていない
  • 時間をO(n), メモリーをO(1)に抑えなければならない


以下回答です。

class Solution {
    public int firstMissingPositive(int[] nums) {
        int n = nums.length;
        for (int i=0; i<n; i++) {
            while (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) {
                swap(nums, i, nums[i] - 1);
            }
        }

        for (int i=0; i<n; i++) {
            if (nums[i] != i + 1) return i+1;
        }
        return n+1;
    }
    
    public void swap (int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

ソートをするとO(n)を超えてしまいますので使えません。
全体のソートはできませんが、
部分的なソートなら出来ます。
つまりこの問題は、正数iをnums[i-1]にソートすればいいのです。
例えば5であればnums[4]に並び替え、2であればnums[1]に並べます。
すべて並べた後、最初に定位置になかった正数が答えになります。
重複する数字がないので、for文で最初から見て、入力の数字を並び替えた後に居るはずの位置にスワップします。
そうすることでO(n)内でのソートが可能となります。

今日は以上。
よいプログラミング生活を!