算法-秒殺數組元素位置調整類問題

這類題目有點特別,不要求我們對數組元素進行像正常排序那樣從大到小或者從小到大,而是要求我們使用O(N)的方法將符合條件的元素排在前面或者後面。其實這是排序的一種變形,不需要我們消滅逆序數。

解決思路有兩類:
1、利用快排思想,將符合條件數據放在前面或後面,一遍遍歷即可完成
2、指針的思想
2、利用冒泡排序思想,我們將符合條件的數據冒在前面,而且我們不需要消滅逆序數,因此每個元素訪問2次,所以時間複雜度仍然是O(N)

1、給定一個數組,將奇數(正數…etc)排在左邊,偶數排在右邊

以奇數爲例,使用快排思想,快排中我們選擇的樞紐元其實是作爲一個條件出現的,而在這裏,只不過這個“樞紐元”換成了奇數偶數而已。

    /**
     * 利用快排思想,複雜度O(n)
     * @param nums
     */
    public static void reOrder(int[] nums){
        int left=0,right=nums.length-1;
        while(left<right){
            while (left<right&&(nums[left]&1)==1){left++;}//找到第一個偶數
            while(left<right&&(nums[right]&1)==0){right--;}//找到第一個奇數
            if(left<right){
                swap(nums,left,right);//交換數據
            }
        }
    }

我們還可以有另一種操作: 指針法

使用一個指針指向當前第一個不符合條件的位置,然後遍歷數組,每次遇到符合條件的,我們就可以將其交換,這樣就可以實現題目要求。而且這個方法寫起來非常簡潔

public static void reOrder(int[] nums){
	int ptr=0;
	for(int i=0;i<nums.length;i++){
		if((nums[i]&1)==1){//判斷奇數偶數
			swap(nums,ptr++,i);
		}
	}
}

2、給定一個數組,將奇數(正數…etc)排在左邊,偶數排在右邊(保證相對位置不變)

這類題目和上面相比,稍微複雜了點,這裏要求我們維持相對順序不變。冒泡法給我們帶來了希望。已經冒過的位置不在冒泡,說明每個元素被訪問了兩次,所以時間複雜度爲O(N)

我們也用一個指針指向第一個不符合條件的位置,然後遍歷數組,冒泡冒到那個位置

public static void reOrder(int[] nums){
	int ptr=0;
	for(int i=0;i<nums.length;i++){
		if((nums[i]&1)==1){//判斷奇偶數
			int curr=i;
			while(curr>ptr){//冒到第一個不符合條件的那個位置
				swap(nums,curr,--curr);//前後交換
			}
			ptr++;
		}
	}
}

2中的代碼可以直接放在1中使用

	//交換元素
    public static void swap(int[] nums,int i,int j){
        int temp=nums[i];
        nums[i]=nums[j];
        nums[j]=temp;
    }

3、將數組中0移動到數組尾部

題目很簡單,直接套殼就好了。。。

    public void moveZeroes(int[] nums) {
        int ptr=nums.length-1;
        for(int i=nums.length-1;i>=0;i--){
           if(nums[i]==0){
               int curr=i;
               while(curr<ptr){
                int temp=nums[curr];
                nums[curr]=nums[curr+1];
                nums[curr+1]=temp;
                curr++;
               }
               ptr--;
           }
        }
    }

不過,我們其實可以針對本題進行優化。因爲我們知道特定的數據爲0,那麼我們就可以統計非零個數,然後將後面置零。

    public void moveZeroes(int[] nums) {
        int noZeroIndex=0;
        for(int i=0;i<nums.length;i++){
            if(nums[i]!=0){
                nums[noZeroIndex++]=nums[i];
            }
        }
        for(int i=noZeroIndex;i<nums.length;i++){
            nums[i]=0;
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章