递归与分治

1.递归的概念

  • 直接或间接地调用自身的算法称为递归算法
  • 用函数自身给出的定义的函数称为递归函数

1.1 阶乘函数

public class FactorialDemo {
	public static void main(String[] args) {
		System.out.println("1!="+factorial(1));
		System.out.println("2!="+factorial(2));
		System.out.println("3!="+factorial(3));
		System.out.println("4!="+factorial(4));
	}
	public static int factorial(int n) {
		
		if(n==0)
			return 1;
		return n*factorial(n-1);
		
	}

}

在这里插入图片描述

1.2 Fibonacci数列

public class Fibonacci {
	/**
	 * 
	 * f(n)=1  n=0,1
	 * f(n)=f(n-1)+f(n-2) n>1
	 */
	public static void main(String[] args) {
		
		System.out.println("f(0)="+fibonacci(0));
		System.out.println("f(1)="+fibonacci(1));
		System.out.println("f(2)="+fibonacci(2));
		System.out.println("f(3)="+fibonacci(3));
		
	}
	
	public static int fibonacci(int n) {
		
		if(n==0||n==1)
			return 1;
		return fibonacci(n-1)+fibonacci(n-2);
		
	}

}

在这里插入图片描述

1.3 全排列



public class FullPermutation {
	public static void main(String[] args) {
		int list[]= {1,2,3};
	    System.out.println("[1 2 3]的全排列:");
		perm(list, 0, list.length-1);
	}
	public static void perm(int list[],int k,int m) {
		
		if(k==m)//遍历到最后一个元素
		{ 
			for(int i=0;i<=m;i++)
				System.out.print(list[i]);
			
			System.out.println();
		}
		else {
			for(int i=k;i<=m;i++) 
			{ 
				swap(list, i, k);//将当前元素list[k]固定到i的位置上
				perm(list, k+1, m);
				swap(list, i, k);//还原元素list[k]的位置
				
			}
		}
		
	}
	public static void swap(int list[],int a,int b) {
		
		int temp=list[a];
		list[a]=list[b];
		list[b]=temp;
		
	}

}

在这里插入图片描述

1.4 整数划分问题

将正整数n表示成一系列正整数之和,n=n1+n2+n3+…+n k _k k
n1>=n2>=n3…>=n k _k k
p(n)表示划分的种数

(1)当n=1时,不论m的值为多少(m>0),只有一种划分即{1};

(2)当m=1时,不论n的值为多少,只有一种划分即n个1,{1,1,1,…,1};

(3)当n=m时,根据划分中是否包含n,可以分为两种情况:

  (a)划分中包含n的情况,只有一个即{n};

  (b)划分中不包含n的情况,这时划分中最大的数字也一定比n小,即n的所有(n-1)划分。 因此 q(n,n) =1 + q(n,n-1);

(4)当n<m时,由于划分中不可能出现负数,因此就相当于q(n,n);

(5)但n>m时,根据划分中是否包含最大值m,可以分为两种情况:

   (a)划分中包含m的情况,即{m, {x1,x2,...xi}}, 其中{x1,x2,... xi} 的和为n-m,因此这情况下为q(n-m,m)

   (b)划分中不包含m的情况,则划分中所有值都比m小,即n的(m-1)划分,个数为q(n,m-1);

  因此 q(n, m) = q(n-m, m)+q(n,m-1);

参考文章



public class IntegerPartition {
	static int num[]=new int[256];//保存划分结果
	static int ans=0;//保存划分种数
	public static void main(String[] args) {
		System.out.println("p(6)="+q(6, 6));
		dfs(0, 0, 6,6);
		System.out.println("p(6)="+ans);
	}
	
	public static int q(int n,int m) {
		
		if(n<1||m<1)
			return 0;
		if(n==1||m==1)
			return 1;
		if(n<m)
			return q(n, n);
		if(n==m)
			return 1+q(n, m-1);
		return q(n, m-1)+q(n-m, m);
		
	}
	/**
	 * 
	 * @param sum   当前遍历的和
	 * @param depth   当前划分中元素的个数
	 * @param max  当前剩余的最大值
	 * @param n  待划分的值n
	 */
	public static void dfs(int sum,int depth,int max,int n) {
		
		if(sum==n)
		{ 
			System.out.print(num[0]);
			for(int i=1;i<depth;i++)
				System.out.print("+"+num[i]);
			System.out.println();
			ans++;
		}
		else if(sum<n)
		{ 
			for(int i=max;i>=1;i--)
			{ 
				num[depth]=i;
				dfs(sum+i, depth+1, i, n);
			}
		}
		
	}

}


在这里插入图片描述

1.5 汉诺塔问题



public class HanoiDemo {
	public static void main(String[] args) {
		
		hanoi(3, 'a', 'b', 'c');
		
	}
	
	public static void hanoi(int n,char a,char b,char c) {
		
		if(n>0)
		{ 
			hanoi(n-1, a, c, b);//将a上面n-1个圆盘从a-->c 以b作为辅助
			move(n,a,b);//将圆盘n从a-->b(a、b在递归过程中不一定代表柱a和柱b)
			hanoi(n-1, c, b, a);//将c上面n-1个圆盘从c-->b 以a作为辅助
		}
		
	}
	
	public static void move(int n,char a,char b) {
		
		System.out.println("圆盘"+n+" from "+a+" to "+b);//模拟移动过程
	}

}

在这里插入图片描述

2.分治法的基本思想

  • 分治法的基本思想是将一个规模为n的问题分解成k个规模较小的子问题,这些子问题互相独立且与原问题相同

2.1 二分搜索技术

二分搜索算法等待基本思想是将n个元素分成个数大致相同的两半,取a[n/2]与x进行比较,如果x=a[n/2]则找打x算法终止;如果x<a[n/2],则只要在数组a的左半部分继续搜索x;如果x>a[n/2],则只要在数组a的右半部分继续搜索x

2.1.1 不带边界的二分搜索算法

public static int binary_search(int arr[],int target) {
		
		int left=0,right=arr.length-1;
		while(left<=right)
		{ 
			int mid=left+(right-left)/2;
			if(arr[mid]==target)
				return mid;
			else if(arr[mid]>target)
				right=mid-1;
			else if(arr[mid]<target)
				left=mid+1;
		}
		return -1;
		
	}

2.1.2 查找左边界的二分搜索算法

public static int binary_search_leftBound(int arr[],int target) {
		int left=0,right=arr.length;// [left,right) 左闭右开
		while(left<right)
		{ 
			int mid=left+(right-left)/2;
			if(arr[mid]==target)
				right=mid;
			else if(arr[mid]>target)
				right=mid;//[left,mid)<==>[left,mid-1]
			else if(arr[mid]<target)
				left=mid+1;//[mid+1,right)
		}
		
	    return arr[left]==target?left:-1;
	}

2.1.3 查找右边界的二分搜索算法

public static int binary_search_rightBound(int arr[],int target) {
		int left=0,right=arr.length;// [left,right) 左闭右开
		while(left<right)
		{ 
			int mid=left+(right-left)/2;
			if(arr[mid]==target)
				left=mid+1;
			else if(arr[mid]>target)
				right=mid;
			else if(arr[mid]<target)
				left=mid+1;
		}
		
		  return arr[left-1]==target?left-1:-1;
	}

完整代码:



public class BinarySearch {
	
	public static void main(String[] args) {
		int arr[]= {1,2,3,3,3,4,5,6};
		System.out.println(binary_search(arr, 3));
		System.out.println(binary_search_leftBound(arr, 3));
		System.out.println(binary_search_rightBound(arr, 3));
		
	}
	public static int binary_search(int arr[],int target) {
		
		int left=0,right=arr.length-1;
		while(left<=right)
		{ 
			int mid=left+(right-left)/2;
			if(arr[mid]==target)
				return mid;
			else if(arr[mid]>target)
				right=mid-1;
			else if(arr[mid]<target)
				left=mid+1;
		}
		return -1;
		
	}
	public static int binary_search_leftBound(int arr[],int target) {
		int left=0,right=arr.length;// [left,right) 左闭右开
		while(left<right)
		{ 
			int mid=left+(right-left)/2;
			if(arr[mid]==target)
				right=mid;
			else if(arr[mid]>target)
				right=mid;//[left,mid)<==>[left,mid-1]
			else if(arr[mid]<target)
				left=mid+1;//[mid+1,right)
		}
		
	    return arr[left]==target?left:-1;
	}
	
	public static int binary_search_rightBound(int arr[],int target) {
		int left=0,right=arr.length;// [left,right) 左闭右开
		while(left<right)
		{ 
			int mid=left+(right-left)/2;
			if(arr[mid]==target)
				left=mid+1;
			else if(arr[mid]>target)
				right=mid;
			else if(arr[mid]<target)
				left=mid+1;
		}
		
		  return arr[left-1]==target?left-1:-1;
	}
	

}

在这里插入图片描述

2.2 棋盘覆盖

在一个2 k ^k k × \times × 2 k ^k k 方格组成的棋盘中,恰有一个方格与其他的方格不同,在棋盘覆盖问题中,要用四种L型骨牌覆盖住棋盘,且任意两个L型骨牌不能重合

特殊方格必定处于4个较小子棋盘之一,其余3个子棋盘中无特殊方格,可以用一个L型骨牌覆盖住这3个较小棋盘的会和处,从而将问题转化为4个较小规模的棋盘覆盖问题

在这里插入图片描述

如果某一个子棋盘里没有特殊方格,遵循如下规则:

  • 左上角子棋盘填充右下角方格
  • 右上角子棋盘填充左下角方格
  • 左下角子棋盘填充右上角方格
  • 右下角棋盘填充左上角方格


package chapter2;

public class ChessboardCoverage {
	static int title=1;//L型骨牌初始编号为2   区别于棋盘中的特殊方格标志1
	public static void main(String[] args) {
		int board[][]= {    {0,1,0,0},
							{0,0,0,0},
							{0,0,0,0},
							{0,0,0,0}
				       };
		
		chessBoard(board, 0, 0, 0, 1,4);
		
		for(int i=0;i<board.length;i++)
		{ 
			for(int j=0;j<board[0].length;j++)
				System.out.print(board[i][j]+"  ");
			System.out.println();
		}
				
}
	/**
	 * 
	 * @param board  棋盘
	 * @param tr  棋盘左上角方格的行号
	 * @param tc  棋盘左上角方格的列号
	 * @param dr  特殊方格所在的行号
	 * @param dc  特殊方格所在的列号
	 * @param size  棋盘规格为2^k*2^k
	 */
	 
	public static void chessBoard(int board[][],int tr,int tc,int dr,int dc,int size) {
		  if(size==1)//棋盘划分到只有一个格子了
			  return;
		  
		  int t=++title;//L型骨牌号
		  int sz=size/2;//分割棋盘
		  
		  //覆盖左上角子棋盘
		  if(dr<tr+sz&&dc<tc+sz)//此棋盘中有特殊方格
			  chessBoard(board, tr, tc, dr, dc, sz);//(tr,tc)是左上角子棋盘的开始点(左上角的点)
		  else {//此棋盘中无特殊方格
			board[tr+sz-1][tc+sz-1]=t;//用t号L型骨牌覆盖右下角   左上子棋盘填充右下角
			chessBoard(board, tr, tc, tr+sz-1, tc+sz-1, sz);//覆盖其余方格  (tr+sz-1, tc+sz-1)是上一步填充过的
			
		}
		  
		 //覆盖右上角子棋盘
		  if(dr<tr+sz&&dc>=tc+sz)
			  chessBoard(board, tr, tc+sz, dr, dc, sz);//(tr,tc+sz)是右上角子棋盘的开始点(左上角的点)
		  else {//此棋盘中无特殊方格
			board[tr+sz-1][tc+sz]=t;//用t号L型骨牌覆盖左下角   右上子棋盘填充左下角
			chessBoard(board, tr, tc+sz, tr+sz-1, tc+sz, sz);//覆盖其余方格
		}
		  
		  
		//覆盖左下角子棋盘
		  if(dr>=tr+sz&&dc<tc+sz)
			  chessBoard(board, tr+sz, tc, dr, dc, sz);//(tr,tc)是右下角子棋盘的开始点(左上角的点)
		  else {//此棋盘中无特殊方格
			board[tr+sz][tc+sz-1]=t;//用t号L型骨牌覆盖右上角   左下子棋盘填充右上角
			chessBoard(board, tr+sz, tc, tr+sz, tc+sz-1, sz);//覆盖其余方格
		}
		  
		//覆盖右下角子棋盘
		  if(dr>=tr+sz&&dc>=tc+sz)
			  chessBoard(board, tr+sz, tc+sz, dr, dc, sz);//(tr,tc)是右下角子棋盘的开始点(左上角的点)
		  else {//此棋盘中无特殊方格
			board[tr+sz][tc+sz]=t;//用t号L型骨牌覆盖右上角  右下子棋盘填充左上角
			chessBoard(board, tr+sz, tc+sz, tr+sz, tc+sz, sz);//覆盖其余方格
		}
		  
		
	}
	 
}



//O(4^k)

在这里插入图片描述

在这里插入图片描述

2.3 归并排序



import java.util.Arrays;

public class MergeSortDemo {
	public static void main(String[] args) {
		int arr[]= {1,3,2,6,5,7,9,8,4};
		int temp[]=new int[arr.length];
		mergeSort(arr, temp, 0, arr.length-1);
		System.out.println(Arrays.toString(arr));
	}
	
	public static void mergeSort(int arr[],int temp[],int lo,int hi) {
		
		if(lo>=hi)
			return;
		
		int mid=lo+(hi-lo)/2;
		mergeSort(arr, temp, lo, mid);
		mergeSort(arr, temp, mid+1, hi);
		merge(arr, temp, lo, mid, hi);
		
	}
	
	public  static void merge(int arr[],int temp[],int lo,int mid,int hi) {
		
		int i=lo;
		int j=mid+1;
		int t=0;
		while(i<=mid&&j<=hi)
		{ 
			if(arr[i]<=arr[j])
				temp[t++]=arr[i++];
			else
				temp[t++]=arr[j++];
				
		}
		while(i<=mid)
			temp[t++]=arr[i++];
		
		while(j<=hi)
			temp[t++]=arr[j++];
		
		t=0;
	    i=lo;
		while(i<=hi)
			arr[i++]=temp[t++];
			
		
	}

}

在这里插入图片描述

2.4 快速排序



import java.util.Arrays;
import java.util.Random;

public class QuickSortDemo {
	public static void main(String[] args) {
		int arr[]= {1,3,2,6,5,7,9,8,4};
		quickSort(arr, 0, arr.length-1);
		System.out.println(Arrays.toString(arr));
	}
	
	public static void quickSort(int arr[],int lo,int hi) {
		
		if(lo>=hi)
			return;
		int j=randomizedPartion(arr, lo, hi);
		quickSort(arr, lo,j-1);
		quickSort(arr, j+1, hi);
		
	  
		
	}
	
	public static int partion(int arr[],int lo,int hi) {
		
		int i=lo;
		int j=hi+1;
		int v=arr[lo];
		
		while(true)
		{ 
			while(arr[++i]<v)
				if(i==hi)
					break;
			
			while(arr[--j]>v)
				if(j==lo)
					break;
			
			if(i>=j)
				break;
			
			swap(arr, i, j);
		}
		swap(arr, lo, j);
		return j;
		
	}
	public static int randomizedPartion(int arr[],int lo,int hi) {//随机划分
		
		int i=new Random().nextInt(hi-lo+1)+lo;//[lo,hi]之间的随机整数
		swap(arr, i, lo);//将产生的随机数对应的元素放到首位
		return partion(arr, lo, hi);
		
		
		
	}
	public static void swap(int arr[],int a,int b) {
		  int temp=arr[a];
		  arr[a]=arr[b];
		  arr[b]=temp;
	}

}

在这里插入图片描述

2.5 循环赛程表问题



public class RoundRobinSchedule {
	
	public static void main(String[] args) {
		  int a[][]=new int[9][9];
		  table(3,a);
		  for(int i=1;i<=8;i++)
		  { 
			  for(int j=1;j<=8;j++)
				  System.out.print(a[i][j]+" ");
			  System.out.println();
		  }
	}
	
	public static void table(int k,int a[][]) {
		int n=1;
		for(int i=1;i<=k;i++)
			n*=2;//n表示选手数量 2^k
		
		for(int i=1;i<=n;i++)
			a[1][i]=i;//初始化表格第一行  也就是1号选手的比赛日程
		
		int m=1;//(m+1,m+1)是每一轮复制的开始位置
		for(int s=1;s<=k;s++)//划分的次数  k=3时  8-4->2
		{ 
			n/=2;//选手划分
			for(int t=1;t<=n;t++)//第一次需要复制4次  第二次需要复制2次  第三次需要复制1次(每一次复制涉及两个赋值操作)
			{ 
				for(int i=m+1;i<=2*m;i++)//控制行
				{ 
					for(int j=m+1;j<=2*m;j++)//控制列
					{   
						
						a[i][j+(t-1)*m*2]=a[i-m][j+(t-1)*m*2-m];//将左上角的值复制到右下角
						a[i][j+(t-1)*m*2-m]=a[i-m][j+(t-1)*m*2];//将右上角的值复制到左下角
					}
					
				}
				
			}
			m*=2;
		}
	}

}

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Codestyling Localization 是一款功能强大的wordpress主题汉化翻译插件,使用此插件可以管理和编辑所有的gettext的翻译文件(.PO/MO).它会自动检测gettext的Ready组件像WordPress的自身或任何插件/主题支持gettext的,是能够扫描相关的源文件,可以帮助你在翻译过程中使用谷歌翻译API或微软在线翻译API。 对wordpress来说,只要包含语言文件(.PO/MO)的主题或插件,理论上都可以翻译,像我们常见的很多优秀的国外主题,因为很少有中文版的,特别是一些新主题,为此,伤透了不少爱好wp主题的并且英文不是很好的国内同学。 Codestyling Localization插件的安装 第一种方法:在后台插件管理直接搜索安装即可。 第二方法就是下载到本地,然后上传安装。 Codestyling Localization插件的使用 感受Codestyling Localization插件的强大,还是要从使用开始的。 安装好后启用Codestyling Localization插件,我们很容易的能在工具>菜单下找到Codestyling Localization插件 路径:工具>Localization (如果你使用chome浏览器,有自动翻译功能,Localization会被翻译成本土化。) 在Codestyling Localization插件管理面板中。 我们可以看到,Codestyling Localization插件支持翻译的有 WordPress | 插件 | 外观 | Compatibility | Security Risk这几个分类 我们根据实际情况,选择要翻译的项目,比如,点击外观,就可以显示所有支持翻译的WP主题. 在要翻译的主题项目,添加要翻译我的语言,因为是要翻译成中文,所以添加中文。 点击添加新语言,弹出添加新语言窗口 然后,点击创建po文件,即可进行中文语言包的翻译工作。 然后在右侧我们就可以找到中文语言包,点击编辑,进入语言包的操作界面,选择一个要翻译的项目,点击右侧编辑按钮,进行翻译: 一个,进行逐个翻译。 至此,Codestyling Localization插件的简单使用方法就讲完了。 要注意的是: 1、Codestyling Localization插件是支持API自动翻译的,要申请Google 或bing的翻译接口。 2、Codestyling Localization插件支持翻译的不论是主题还是插件等,都是在存在.po语言包的基础上进行的翻译,如果只包含主题前台的.po语言包,就不能翻译后台内容。如果php文件内的翻译,也是不能实现的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodePanda@GPF

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值