1. 程式人生 > >LeetCode581-最短無序子陣列(滑動視窗)

LeetCode581-最短無序子陣列(滑動視窗)

JS做題爽就爽在不用開編輯器

 

 

 

這個題目比較難,畢竟最後是用了On級別的演算法

做了下去看來大體上是對的,但是很多地方的小細節出了很多差錯,因為是在很困的情況下做的題目

 

主要就是找到一個視窗,裡面最小的數字往左挪動,右邊最大的數字往右挪。

不需要真實的交換,只是簡單的比較即可。

1、窗口裡面的重複數字怎麼辦? 不用管,因為窗口裡面有他們的位置,只需要找一個代表出去即可。

2、數組裡的重複數字怎麼辦?如果是降序的,就把它放到窗口裡面。 比如3,2,2,2,2,2 這些2要全部進去。

3、往左往右挪,會不會導致把更小或更大的陣列弄進視窗?

不會。

往左移動可能會有比窗口裡面更大的數字,因為是降序找到這個最小數字的。

往右移動不會有小於最小值的數字,假如右邊有小於最小值的數字,那麼窗口裡面的數字全都比它大,它也是降序,也會被拉到窗口裡面的。

 

反證法很重要。

 

/**
 * @param {number[]} nums
 * @return {number}
 */
var findUnsortedSubarray = function(nums) {
    
    if(nums.length == 1){
        return 0;
    }
    
    if(nums.length == 2){
        
if(nums[0]>nums[1]){ return 2; }else{ return 0; } } // 滑動視窗,找到不合理的數字的範圍吧,順便記錄裡面的最大最小值,以及下標,因為最大最小值關係著子陣列的大小 // 最小的一直往左交換位置,最大的一直往右交換位置,最後這個位置之差就是了 // 最大的數往右邊交換,不會把小於最小的數換進來,因為如果右邊存在小於最小的數,那麼這個數當初肯定也會被納入到滑動窗口裡面去的 // 倒是最左邊可能換入比最大還大的數,所以先弄好最小的數字開始
// 還可能有重複元素,比如題目的9<10,不過10會一直換到最後,應該還好 // 但是最小和最大的數字可能會有多個,不過好像這些重複數字會在滑動窗口裡有他們的位置,所以不用管 let low = -1,high = -1; // 如果當前值是降序,就是ture,用來記錄重複的數字[1,3,2,2,2] 4 let flag = false; let last = nums[0]; for(let i=1;i<nums.length;i++){ if(nums[i]<last){ if(low===-1){ // 應該把前一個也算進來 low=i-1; // 第一次就要給high賦值 high = i; }else{ //high很有可能不會被賦值 如果中途只有一個降序[1,3,2,4,5] high=i; } flag = true; }else if(nums[i]===last){ if(flag){ high=i; } }else{ flag=false; } last = nums[i]; } // console.log(low,high); // 找到最小和最大的數字 // 陣列的內容可以使正負數 let min = nums[low]; let max = nums[low]; for(let i=low;i<=high;i++){ if(nums[i]<min){ min=nums[i]; } if(nums[i]>max){ max=nums[i]; } } // console.log(min,max); // 一直挪左邊的 // 直接和視窗外面的比即可 //視窗外面要麼是重複數字,要麼是升序排好的,如果遇到比自己還小或相等的,就是應該退出了 for(let i =low-1;i>=0;i--){ if(min<nums[i]){ low--; if(nums[i]>max){ max=nums[i]; } }else{ break; } } // 挪右邊的 for(let i=high+1;i<nums.length;i++){ if(max>nums[i]){ high++; }else{ break; } } // console.log(low,high); if(high===low){ return 0; }else{ return high-low+1; } //[2,1] 2 0 // 如果整個陣列是逆序的,這個方法不行啊 // [3,2,1]應該可以,2是low,1是high // [-1,-1,-1,-1] };

 

時間還行

 

 

 

百度了一下,有一種簡單的做法。

 

先用一個輔助陣列儲存,然後將輔助陣列排序,輔助數組裡面,肯定會有一部分數字和原來的不一樣。

1,2,3【】,8,9

那麼這個【】其實就是子陣列的大小....因為,確實,按照我的方式,往左往右挪了之後的陣列,也是這樣

然後從左找到第一個不同的數字

從右找到第一個。

【】就是源數組裡面,亂序的數字再正確排序下,應該在的範圍。

 

好難啊,轉不過彎