算法的意義:不在於你考慮大神們是怎麼考慮到的方法,你爲什麼想不到。而是你在遇到相似的問題時候,能想起這種問題的解決方法。自己不是笨,他們當初遇到同樣的問題時,也曾絞盡腦汁,只不過,他們更早的實踐過了。
------------2019.11.28日 於濟南
荷蘭國旗是由紅白藍3種顏色的條紋拼接而成,如下圖所示:
假設這樣的條紋有多條,且各種顏色的數量不一,並且隨機組成了一個新的圖形,新的圖形可能如下圖所示,但是絕非只有這一種情況:
需求是:把這些條紋按照顏色排好,紅色的在上半部分,白色的在中間部分,藍色的在下半部分,我們把這類問題稱作荷蘭國旗問題。
我們把荷蘭國旗問題用數組的形式表達一下是這樣的:
給定一個整數數組,給定一個值K,這個值在原數組中一定存在,要求把數組中小於K的元素放到數組的左邊,大於K的元素放到數組的右邊,等於K的元素放到數組的中間,最終返回一個整數數組,其中只有兩個值,分別是等於K的數組部分的左右兩個下標值。
要求額外空間複雜度O(1),時間複雜度O(n)
解這道題需要將數組劃分爲3部分,即小於num、等於num、大於num,這樣一來我們建立三個索引,分別是左邊界的,當前位置索引,右邊界的索引,通過移動索引並交換位置即可得到答案。具體代碼如下:
/**
* Copyright (C), 2015-2019, XXX有限公司
* FileName: Netherland
* Author: guangod
* Date: 19-11-27 下午10:33
* Description: 荷蘭國旗問題
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改時間 版本號 描述
*/
package myalgorithms;
/**
* 〈一句話功能簡述〉<br>
* 〈荷蘭國旗問題〉
* 要學會分析這種解法的來歷,簡單的問題往往可以看到更真實的思想
*
* @author guangod
* @create 19-11-27
* @since 1.0.0
*/
public class Netherland {
public static int[] coreAlgorithms(int[] arr , int l , int r , int p) {
int less = l - 1;//less代表左索引
int more = r + 1;//more代表右索引
while (l < more) {//l代表當前位置,p代表比較值
if (arr[l] < p) swap(arr , ++ less , l++);
else if (arr[l] > p) swap(arr , -- more , l);
else l++;
}
return new int[] {less + 1 , more - 1};//less+1代表右索引的邊界,more-1代表左索引的邊界
}
public static void swap(int[] arr,int num1,int num2){
int temp=arr[num1];
arr[num1]=arr[num2];
arr[num2]=temp;
}
public static int[] generateArray(){
int[] arr =new int[10];
for(int i=0;i<arr.length;i++){
arr[i]=(int)(Math.random()*100);
}
return arr;
}
public static void printfArr(int[] arr){
if(arr == null){
return;
}
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+" ");
}
System.out.println();
}
public static void main(String[] args) {
int[] test=generateArray();
printfArr(test);
int[] res=coreAlgorithms(test,0,test.length-1,59);
printfArr(test);
System.out.println(res[0]);
System.out.println(res[1]);
//System.out.println(res[2]);
}
}