算法学习篇(未完)

声明:所有题目都是自己曾经做过,也只作了部分测试,一定存在错漏之处,如能帮忙指出,感激不尽。其他题目等整理之后再更新

1.求一个数字的二进制表示有多少个1

 

public class CountOfOne {

	public static void main(String[] args) {

		//求一个数字的二进制表示有多少个1

		int number=-1;

		print(number);

		System.out.println(NumberOf1(number));

	}

	public static int NumberOf1(int n){

		int count=0;

		while(n!=0){

			count++;

			n=(n-1)&n;

			print(n);

		}

		return count;

	}

	public static void print(int n){

		String binary=Integer.toBinaryString(n);

		int count=32-binary.length();

		for(int i=0;i<count;i++){

			System.out.print("0");

		}

		System.out.println(binary+" "+n);

	}

}

2.最短路径

 

题目路径:http://acm.hdu.edu.cn/vcontest/vtl/problem/showproblem/vtlid/4642/problemid/1011

 

public class Shortest {

//http://acm.hdu.edu.cn/vcontest/vtl/problem/showproblem/vtlid/4642/problemid/1011

	private int[][] table=new int[10][10];

	private boolean[][] map=new boolean[10][10];

	private void initTable(){

		int i=5;

		int j=4;

		int number=2;

		table[i][j]=1;

		int a=1,b=2;

		while(number<73){

			for(int d=0;d<a;d++){

				table[i][++j]=number++;

			}

			for(int d=0;d<a;d++){

				table[--i][j]=number++;

			}

			a+=2;

			for(int d=0;d<b;d++){

				table[i][--j]=number++;

			}

			for(int d=0;d<b;d++){

				table[++i][j]=number++;

			}

			b+=2;		

		}

		for(int d=0;d<a;d++){

			table[i][++j]=number++;

		}

		for(int d=0;d<a;d++){

			table[--i][j]=number++;

		}

		for(int d=0;d<b-1;d++){

			table[i][--j]=number++;

		}

	}

	private void initMap(){

		map[0][3]=true;

		map[1][4]=map[1][6]=true;

		map[2][1]=map[2][7]=map[2][9]=true;

		map[3][0]=map[3][2]=map[3][6]=true;

		map[4][3]=map[4][5]=map[4][7]=true;

		map[5][2]=map[5][5]=map[5][6]=map[5][8]=true;

		map[6][1]=map[6][3]=true;

		map[7][0]=map[7][4]=true;

		map[8][1]=map[8][5]=map[8][9]=true;

		map[9][0]=map[9][6]=true;

	}

	private int aim;

	public Shortest(int a,int b){

		initTable();

		initMap();

		aim=b;

		for(int i=0;i<10;i++)

			

			for(int j=0;j<10;j++){

				if(table[i][j]==a){

					process(i,j,0);

					break;

				}

			}

		if(bestPath==1000000){

			System.out.println("impossible");

		}else{

			System.out.println(bestPath);

		}

	}

	//表示很远

	private int bestPath=1000000;

	

	private void process(int i,int j,int path){

		if(table[i][j]==aim){

			if(path<bestPath){

				bestPath=path;

			}

		}

		map[i][j]=true;

		//没有数据 有数据的为true,

		if(i-1>=0&&!map[i-1][j]){

			//向上	

			process(i-1,j,path+1);

		}

		if(i+1<=9&&!map[i+1][j]){

			//向下

			process(i+1,j,path+1);

		}

		if(j-1>=0&&!map[i][j-1]){

			//向左

			process(i,j-1,path+1);

		}

		if(j+1<=9&&!map[i][j+1]){

			//向右

			process(i,j+1,path+1);

		}

		map[i][j]=false;

	}

	public static void main(String[] args) {

		int start=9;

		int end=32;

		new Shortest(start,end);

	}

	

}


3.青蛙跳跃

 

游戏地址:http://www.macroblue.net/bbs/ShowPost.asp?ThreadID=5932

六个位置从左到右依次编号为:1,2,3,4,5,6

 

import java.util.ArrayList;

import java.util.List;



public class FrogJump {

	private int[] pos=new int[]{1,1,1,0,2,2,2};

	private int count=0;

	private List<String> content=new ArrayList<String>();

	public void jump(){

		

		if(isComplete()){

			

			for(String str:content){

				System.out.println(str);

			}

			System.out.println("总共移动的次数为:"+count+"次");

			System.out.println("=======================");

		}

		for(int i=0;i<7;i++){

			int type=canJump(i);

			if(type!=-1){

				content.add(print(i,type));

				swap(type,i);

				count++;

				jump();

				swap(type,i);

				count--;

				content.remove(count);

			}

		}



	}

	private String print(int start,int end){

		//int type=pos[start];

		return (start+1)+"位置的青蛙跳到空地"+(end+1);

	}

	private boolean isComplete(){

		boolean result=true;

		for(int i=0;i<3;i++){

			if(pos[i]!=2)return false;

		}

		for(int i=4;i<7;i++){

			if(pos[i]!=1)return false;

		}

		return result;



	}

	private void swap(int i,int j){

		int temp=pos[i];

		pos[i]=pos[j];

		pos[j]=temp;

	}

	

	private int canJump(int index){

		if(pos[index]==0)return -1;

		//左边的青蛙

		if(pos[index]==1){

			if(index==6)return -1;

			if(pos[index+1]==0){

				return index+1;

			}else if((index<=4&&pos[index+2]==0)){

				return index+2;

			}

		}else{//右边的青蛙

			if(index==0)return -1;

			if(pos[index-1]==0){

				return index-1;

			}else if((index>=2&&pos[index-2]==0)){

				return index-2;

			}	

		}

		return -1;

	}

	public static void main(String[] args) {

		new FrogJump().jump();

	}

	

}

输出:

 

 

3位置的青蛙跳到空地4

5位置的青蛙跳到空地3

6位置的青蛙跳到空地5

4位置的青蛙跳到空地6

2位置的青蛙跳到空地4

1位置的青蛙跳到空地2

3位置的青蛙跳到空地1

5位置的青蛙跳到空地3

7位置的青蛙跳到空地5

6位置的青蛙跳到空地7

4位置的青蛙跳到空地6

2位置的青蛙跳到空地4

3位置的青蛙跳到空地2

5位置的青蛙跳到空地3

4位置的青蛙跳到空地5

总共移动的次数为:15次

=======================

5位置的青蛙跳到空地4

3位置的青蛙跳到空地5

2位置的青蛙跳到空地3

4位置的青蛙跳到空地2

6位置的青蛙跳到空地4

7位置的青蛙跳到空地6

5位置的青蛙跳到空地7

3位置的青蛙跳到空地5

1位置的青蛙跳到空地3

2位置的青蛙跳到空地1

4位置的青蛙跳到空地2

6位置的青蛙跳到空地4

5位置的青蛙跳到空地6

3位置的青蛙跳到空地5

4位置的青蛙跳到空地3

总共移动的次数为:15次

=======================


4.将小写的数字转换成中文大写数字,如:456789  对应中文大写的:肆拾伍万陆仟柒佰捌拾玖元整

public class MoneyReverse {

	public static void main(String[] args) {

		

		String str=new MoneyReverse().process("456789");

		System.out.println(str);

	}

	private char[] map=new char[]{'壹','貳','弎','肆','伍','陆','柒','捌','玖'};

	private String[] typeMap=new String[]{"","拾","佰","仟","万","亿"}; 

	private String [] lastMap=new String[]{"元整","万","亿","万亿"};

	public String process(String str){

		//去掉前面的零

		str=str.replaceFirst("^0*", "");

		int i=str.length();

		int count=i%4==0?i/4:i/4+1;

		String[] part=new String[count];

		int t=0;

		for(;t<count-1;t++){

			part[t]=str.substring(i-4*(t+1),i-4*t);

		}

		part[count-1]=str.substring(0,i-4*t);	

		t=count-1;

		StringBuilder builder=new StringBuilder();

		for(;t>=0;t--){

			builder.append(processPart(part[t], t));

		}

		return builder.toString();

	}

	private String processPart(String number,int type){

		int count=number.length();

		String result="";

		for(int i=count-1;i>=0;i--){

			char c=number.charAt(i);

			if((i!=count-1&&c=='0'&&number.charAt(i+1)!='0')||(i==0&&c=='0')){

				result="零"+result;

			}

			else if(c!='0'){

				result=map[c-49]+typeMap[count-1-i]+result;

			}

		}		

		return result+lastMap[type];

	}

	

}


5.将1~9九个数字,组合成三个三位数A,B,C使其满足:B/A=2 C/A=3 有多少种这种组合?

 

 

public class NumberMerger {

	//false表示还没有使用

	private boolean[] map=new boolean[9];

	

	public void process(){

	

		int firstNumber=0;

		//第一个数

		for(int i=1;i<=3;i++){

			//已用

			map[i-1]=true;

			firstNumber+=i*100;

			//第二个数

			for(int j=1;j<=9;j++){

				if(!map[j-1]){

					map[j-1]=true;

					firstNumber+=j*10;

					for(int k=1;k<=9;k++){

						if(!map[k-1]){

							map[k-1]=true;

							firstNumber+=k;

							validate(firstNumber);

							firstNumber-=k;

							map[k-1]=false;

						}

					}

					firstNumber-=j*10;

					

					map[j-1]=false;

				}

			}

			firstNumber-=i*100;

			map[i-1]=false;

		}

		

	}

	public void validate(int number){



		int secondNumber=number*2;

		int thridNumber=number*3;

		if(secondNumber>=1000||thridNumber>=1000)return;

		String text=""+secondNumber+thridNumber;

		if(text.contains("0"))return;

		int m=100;

		String mapProcess="";

		for(int i=0;i<3;i++){

			//已经使用过

			if(map[secondNumber/m-1]||map[thridNumber/m-1]){

				if(!"".equals(mapProcess)){

					for(int t=0;t<mapProcess.length();t++){

						map[mapProcess.charAt(t)-49]=false;

					}

				}

				return;

			}else{

				map[secondNumber/m-1]=true;

				map[thridNumber/m-1]=true;

				mapProcess=mapProcess+(secondNumber/m);

				mapProcess=mapProcess+(thridNumber/m);

				secondNumber=secondNumber%m;

				thridNumber=thridNumber%m;

				m/=10;

			}

		}

		for(int t=0;t<mapProcess.length();t++){

			map[mapProcess.charAt(t)-49]=false;

		}

		System.out.println(number+","+2*number+","+3*number);

	}

	

	

	public static void main(String[] args) {

		new NumberMerger().process();

	}

}


 

6.求一个数字序列中最长连续递增子序列有多少个?

如这样一组序列:17 2 5 77 99 93 11 97 65 35 

其最长连续递增子序列是从第二个数字2到数字99,一共4个。

 

import java.util.Random;

public class SlopeUp {

	public static void main(String[] args) {

		int count=10;

		int[] nums=new int[count];

		Random random=new Random();

		for(int i=0;i<count;i++){

			nums[i]=random.nextInt(100);

			System.out.print(nums[i]+" ");

		}

		System.out.println();

		new SlopeUp().process(nums);

	}

	

	private int[] a; //a[i]表示从开始到i最长连续递增子序列个数,最后的结果为:a[a.length-1]

	private int[] b; //b[i]表示到当前i位置有多少个连续递增个数,如-1,2,4,0,3 则b[2]=3;b[4]=2

	public void process(int[] nums){

		a=new int[nums.length];

		b=new int[nums.length];	

		for(int i=1;i<nums.length;i++){

			

			if(nums[i]>nums[i-1]){

				b[i]=b[i-1]+1;

				if(b[i]+1>a[i-1]){

					System.out.println("The End Number Is:"+nums[i]);

					a[i]=b[i]+1;

				}else{

					a[i]=a[i-1];

				}

			}else{

				a[i]=a[i-1];

			}

		}

		System.out.println(a[a.length-1]);

	}

	

}

7.假设这有一个各种字母组成的字符串,假设这还有另外一个字符串,而且这个字符串里的字母数相对少一些。从算法是讲,什么方法能最快的查出所有小字符串里的字母在大字符串里都有?
比如,如果是下面两个字符串:
String 1: ABCDEFGHLMNOPQRS
String 2: DCGSRQPOM
答案是true,所有在string2里的字母string1也都有。 

 

解法1:

 

public class StringProcess01 {

	public static void main(String[] args) {

		String s1="ABCDEFGHLMNOPQRS";

		String s2="DCGSRQPOM";

		new StringProcess01().process(s1,s2);

	}

	

	public void process(String lengthStr,String ShortStr){

		boolean hash[]=new boolean[26];

		char[] scs=ShortStr.toCharArray();

		int count=0;//短字符串中不同字符的个数

		for(int i=0;i<scs.length;i++){

			int index=scs[i]-'A';

			if(!hash[index]){//为了保障count的准确

				hash[index]=true;

				count++;

			}

			

		}

		char[] lcs=lengthStr.toCharArray();

		for(int i=0;i<lcs.length;i++){

			int index=lcs[i]-'A';

			if(hash[index]){

				hash[index]=false;

				count--;

				if(count==0)break;

			}

		}

		if(count==0){

			System.out.println("True");

		}else{

			System.out.println("False");

		}

	}

}


解法2

 

 

import java.math.BigInteger;

/*

假设我们有一个一定个数的字母组成字串,我给每个字母分配一个素数,

从2开始,往后类推。这样A将会是2,B将会是3,C将会是5,等等。

现在我遍历第一个字串,把每个字母代表的素数相乘。你最终会得到一个很大的整数,

对吧?然后——轮询第二个字符串,用每个字母除它。

如果除的结果有余数,这说明有不匹配的字母。

如果整个过程中没有余数,你应该知道它是第一个字串恰好的子集了。

*/

public class StringProcess01_02 {

	public static void main(String[] args) {

		String str1="ABCDEFGHIJKLMNOPQRSTUVWXYZ";

		String str2="SDFF";

		new StringProcess01_02().process(str1, str2);

	}

	

	public void process(String lengthStr,String shortStr){

		int[] primeNumber=new int[]{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59,61, 67, 71, 73, 79, 83, 89, 97, 101};

		BigInteger mulValuse=BigInteger.valueOf(1);

		char[] lca=lengthStr.toCharArray();

		for(int i=0;i<lca.length;i++){

			int index=lca[i]-'A';

			//表示之前没有出现过该字符,可以防止相同的素数一直相乘

			String re=mulValuse.remainder(BigInteger.valueOf(primeNumber[index])).toString();

			if(!"0".equals(re)){

				mulValuse=mulValuse.multiply(BigInteger.valueOf(primeNumber[index]));

				//System.out.println(mulValuse.toString());

			}

			

		}

		

		char[] sca=shortStr.toCharArray();

		boolean temp=true;

		for(int i=0;i<sca.length;i++){

			int index=sca[i]-'A';

			String re=mulValuse.remainder(BigInteger.valueOf(primeNumber[index])).toString();

			if(!"0".equals(re)){

				//只要第一个出现的不合法的字符则马上结束

				//当数据多时,效率将会非常显著的提高

				temp=false;

				break;

			}

		}

		if(temp){

			System.out.println("True");

		}else{

			System.out.println("False");

		}

	}

}


8.三色旗算法(注意看清题意,否则可能不能理解代码)

 

题意可以查看:http://hi.baidu.com/de1zhanjie/item/bdac2bbab11d12afeaba9355

//关键:两头向中间找,找过的可以进行交换,还没有找过的不能处理

public class ThreeColorFlag02 {

	private int blue; //blue指针左边的值一定为蓝色

	private int white; //white一直向右移动,但为白色,则直接移动,当为红色,和红色指针交换,当为蓝色指针,和蓝色指针交换

	private int red; //red指针右边的值一定为红色

	private char[] source;

	public ThreeColorFlag02(char[] s){

		this.source=s;

		blue=0; 

		white=0;

		red=source.length-1;

		process();

	}

	public void process(){

		//blue指针指向的为:非蓝色旗

		while(source[blue]=='蓝'){

			blue++;

			white++;

		}

		//red指针指向的为:非红色旗

		while(source[red]=='红'){

			red--;

		}

		//当白色指针超过红色指针,则表示结束

		while(white<=red){

			if(source[white]=='红'){

				swap(white,red);

				//必须减1,否则刚刚交换完,该位置必定为红

				red--;

				while(source[red]=='红'){

					red--;

				}

			}

			//如果刚刚和red交换过,则可能为蓝色,或者白色

			//否则,为白色

			while(source[white]=='白'){

				white++;

			}

			//此时white可能指向蓝色或者红色

			if(source[white]=='蓝'){

				swap(white,blue);//蓝色指针为遍历过的指针,所以可以交换

				white++;

				blue++;

			}

		}

	}

	private void swap(int i,int j){

		char temp=source[i];

		source[i]=source[j];

		source[j]=temp;

	}

	public static void main(String[] args) {

		char[] source=new char[]{'红','白','蓝','白','白','蓝','红','蓝','白','红'};

		new ThreeColorFlag02(source);

		System.out.println(Arrays.toString(source));

	}

}


9.桶排序(看代码前要先理解桶排序的原理)

 

 

public class BucketSort {

	/**

	 * 

	 * @param data 要进行排序的数据

	 * @param min 数据中最小的数据

	 * @param max 数据中最大的数据

	 */

	public void bucketSort(int[] data,int min,int max){

		int arrayLength=data.length;

		//临时数组,data数组的拷贝

		int[] tmp=new int[arrayLength];

		System.arraycopy(data, 0, tmp, 0, arrayLength);

		//桶数组

		int[] buckets=new int[max-min];

		for(int i=0;i<arrayLength;i++){

			//记录每个数出现的次数

			buckets[data[i]-min]++;

		}

		//对桶进行处理

		for(int i=1;i<max-min;i++){

			buckets[i]=buckets[i]+buckets[i-1];

		}

		//根据桶的信息来确定数据的位置

		//tmp.Data和该值对应的具体位置的映射关系为:

		//tmp.Data-映射->buckets.Index-得到->buckets.Data

		//buckets.Data-映射->data.Index-确定->data.Data

		//为了保证算法的稳定性,从最大索引开始

		for(int i=arrayLength-1;i>=0;i--){

			data[--buckets[tmp[i]-min]]=tmp[i];

		}

	}

	public static void main(String[] args) {

		int[] data=new int[]{9,5,-1,8,5,7,3,-3,1,3};

		//因为在bucketSort方法中算桶个数是max-min,所以这里的max应该要比实际的大1

		new BucketSort().bucketSort(data, -3, 10);

		for(int num:data){

			System.out.print(num+" ");

		}

	}

}

 


10.建立最大堆

 

public class MaxHeap {

	public static void main(String[] args) {

		int[] source=new int[]{3,24,-1,10,5};

		new MaxHeap().createHeap(source);

		System.out.println(Arrays.toString(source));

	}

	private int[] source;

	private int length;

	public void createHeap(int[] s){

		this.source=s;

		length=this.source.length-1;

		for(int i=length/2;i>=0;i--){

			process(i);

		}

	}

	private void process(int index){

		int left=getLeftIndex(index);

		int right=getRightIndex(index);

		int maxIndex=index;

		//右子树为有效子树

		if(right<=length&&source[index]<source[right]){

				maxIndex=right;

		}

		if(left<=length&&source[maxIndex]<source[left]){

				maxIndex=left;

		}

		//最大值不是本身

		if(maxIndex!=index){

			swap(maxIndex,index);

			//这一步很重要,要递归处理交换后的新节点,保证所有的结点都符合最大堆的特点

			process(maxIndex);

		}

	}

	//交换

	private void swap(int i,int j){

		int temp=source[i];

		source[i]=source[j];

		source[j]=temp;

	}

	private int getLeftIndex(int index){

		//下标从0开始

		return 2*index+1;

	}

	private int getRightIndex(int index){

		return 2*index+2;

	}

	

}

 


11.打印中文字符序列的每个字符的拼音的第一个字母:如输入:"直来直往",则输出:“ZLZW”

import java.io.UnsupportedEncodingException;

public class js_02 {

	public static void main(String[] args) {

		new js_02().new answer("我深爱我的家人");

	}	

	private class answer{

		private int[][] res=new int[23][2];

		private String[] word={"啊","芭","擦","搭","蛾","发","噶","哈","击","喀","垃","妈","拿","哦","啪","期","然","撒","塌","挖","昔","压","匝"};

		private char[] cs={'A','B','C','D','E','F','G','H','J','K','L','M','N','O','P','Q','R','S','T','W','X','Y'};

		public answer(String str){

			iniRes();

			process(str);

		}

		private void iniRes(){

			for(int i=0;i<word.length;i++){

				try {

					byte[] bs=word[i].getBytes("GB2312");

					res[i][0]=bs[0]&0xff;

					res[i][1]=bs[1]&0xff;

				} catch (UnsupportedEncodingException e) {

					// TODO Auto-generated catch block

					e.printStackTrace();

				}

			}

			for(int i=0;i<res.length;i++){

				

				for(int j=0;j<2;j++){

					System.out.print(res[i][j]+",");

				}

				System.out.println();

			}		

			

		}

		public void process(String str){

			

			for(int i=0;i<str.length();i++){

				String word=str.substring(i, i+1);

				try {

					byte[] b=word.getBytes("GB2312");

					int first=b[0]&0xff;

					int second=b[1]&0xff;

					boolean isZ=true;

					for(int t=0;t<res.length-1;t++){

						if(first>=res[t][0]&&first<res[t+1][0]){

							System.out.print(cs[t]);

							isZ=false;

							break;	

						}else if(first>=res[t][0]&&first==res[t+1][0]){//first==res[t][0]&&first==res[t+1][0]

							if(second<res[t+1][1]){

								System.out.print(cs[t]);

								isZ=false;

								break;	

							}

						}

					}

					if(isZ){

						System.out.print('Z');

					}

				} catch (UnsupportedEncodingException e) {

					// TODO Auto-generated catch block

					e.printStackTrace();

				}

			}

		}

		

	}

		

	

}




你可能感兴趣的:(算法)