算法的意义:不在于你考虑大神们是怎么考虑到的方法,你为什么想不到。而是你在遇到相似的问题时候,能想起这种问题的解决方法。自己不是笨,他们当初遇到同样的问题时,也曾绞尽脑汁,只不过,他们更早的实践过了。
------------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]);
}
}