LEETCODE刷題記錄【27 Remove Element】

給定一個數組 nums 和一個值 val,你須要原地移除全部數值等於 val 的元素,返回移除後數組的新長度。

不要使用額外的數組空間,你必須在原地修改輸入數組並在使用 O(1) 額外空間的條件下完成。數組

元素的順序能夠改變。你不須要考慮數組中超出新長度後面的元素。性能

1.先來寫一個最簡單的版本,即便用額外空間做爲輔助,把符合條件的元素寫到一個新的數組裏。優化

public static ArrayList removeElement(int[] nums, int val)
{

    ArrayList<Integer> newNums = new ArrayList<Integer>();
    for (int item:nums)
    {
        if(item != val)
        {
            newNums.add(item);
        }
    }
    System.out.print(newNums.size());
    return newNums;
}

基礎知識查漏補缺:
1.Java數組的聲明、初始化和使用
遇到了一個問題,新的數組須要聲明和初始化,可是新數組的長度還不知道,怎麼初始化。
考慮使用ArrayList
2.ArrayList的聲明和使用
3.靜態方法中調用非靜態方法的限制指針

上述方法:
1.須要遍歷數組一次,因此時間複雜度是o(n)
2.須要使用一個數組做爲額外空間,因此空間複雜度是o(n)code

2.還有沒有優化空間?
進階版本--下降空間複雜度
思路:
方法1須要開闢一個新的數組空間,然而題目中給定的說明,不須要考慮數組中超出長度後面的元素,能夠考慮把舊數組的空間再利用。
因爲必需要根據索引替換數組的值,因此不能用For-Each循環方法。索引

public static int removeElement(int[] nums, int val)
{
    int j = 0;
    for (int i = 0;i < nums.length;i++)
    {
        if(nums[i] != val)
        {
            nums[j] = nums[i];
            j++;
        }
    }
    System.out.print(j);
    return j;
}

複雜度分析:
時間複雜度:o(n) 遍歷2n次
空間複雜度:o(1)rem

3.還有沒有優化空間?
方法2在某些特定場景下會進行沒必要要的複製操做,影響性能。好比{1,2,3,5,4} val=4,或者{4,1,2,3,5},彷佛沒有必要把前4個元素複製一遍,在這一點上能夠進行優化,優化思路爲若是匹配到須要剔除的元素,就把數組末尾的元素替換到這個位置來。注意:尾部的元素有多是須要剔除的,因此,下一輪循環要從當前索引從新開始。it

public static int removeElement(int[] nums, int val)
{
    int n = nums.length;
    System.out.print(n);
    for (int i = 0;i < n;i++)
    {
        if(nums[i] == val)
        {
            nums[i] = nums[n-1];
            i--;
            n--;
            System.out.println("1:n--:"+n);
        }
    }
    System.out.print(n);
    return n;
}

遇到的問題:
1.在循環裏,把nums.length做爲了固定長度,會致使全部元素都被遍歷,實際上被替換到前面的元素不須要被遍歷,致使了bug
2.在使用i--時,考慮若是數組前幾個元素都是須要被剔除的元素,會不會致使index爲負,致使溢出。通過分析和實驗不會,由於每次循環結束i都要++基礎

複雜度分析:
時間複雜度:o(n) 遍歷n次
空間複雜度:o(1) List

總結:1.學會的新方法,雙指針法2.若是沒有廣泛的優化方法,那麼就考慮業務場景的特色,好比方法三,針對某些特殊場景提出優化空間。

相關文章
相關標籤/搜索