前言
最近要参加蓝桥杯,感觉虽然学过算法这门课,但是一旦真正做题就感觉力不从心,真的不会,在网上找了基础课程指导,正在一步步学习,希望可以对算法有一个新的理解。
整体思路
递归步骤:我做一部分,委托出去一部分
(1)找重复:找子问题
(2)找变化:看每次重复之间的变化,参数中要有变化的量
(3)找边界:找截止条件
题目
1、 切蛋糕思维
将蛋糕一分为二,然后逐步递推
1、字符串翻转
问题:
给一个字符串,利用递归的方式将其进行翻转
代码:
package com.lanqiao.vidio;
public class reverse {
public static void main(String[] args) {
System.out.println(reverse1("abcd",3));
}
public static String reverse1(String src,int end)
{
if(end==0)
{
return ""+src.charAt(0);
}
return src.charAt(end)+reverse1(src,end-1);
}
}
思路:
每次从最后向前推进一个字符,即将字符串从最后一个不断向前切割
变化参数:end结束位置在不断变化
2、插入排序
1、代码:
public class insertSort {
public static void main(String[] args) {
int[] arr = {6,5,4,3,2,1};
sort1(arr,arr.length-1);
for(int a:arr)
{
System.out.print(a+" ");
}
}
public static void sort1(int[] arr,int k)
{
if(k==0)
{
return ;
}
sort1(arr,k-1);
int temp = arr[k];
int index = k-1;
while(index>-1&&arr[index]>temp)
{
arr[index+1]=arr[index];
index--;
}
arr[index+1]=temp;
}
}
2、思路
(1)将数组分成最后一个和前面k-1个元素,将前面k-1个元素顺序排好了,最后一个元素插入到前面即可
(2)每次变化的只有需要排序的元素的个数
(3)截止条件是推到第一个元素,不用排序,直接返回
3、注意点:
(1)while循环判断条件注意加上 index>-1条件,如果没有,当遇到排在第一个位置的元素会一直向前判断,数组下标异常
(2)因为在while循环中,先移动位置再对index–,所以最终指针落到的是arr[k]放的位置之前的位置,所以应放在index+1的位置
3、汉诺塔问题
1、代码:
public class hannuo {
public static void main(String[] args) {
Hannuo1(3,"A","B","C");
}
private static void Hannuo1(int i, String from, String to, String help) {
if(i==1)
{
System.out.println("move "+i+"from "+from+"to "+to);
return;
}
Hannuo1(i-1,from,help,to);
System.out.println("move "+i+"from "+from+"to "+to);
Hannuo1(i-1,help,to,from);
}
}
2、思路
(1)从简单入手:当仅有三个圆盘时
1:from->help
2:from->to
1:to->help
3:from->help
…
(2)N个圆盘时:
将N-1:from->help
最下面一个:from->to
N-1个:help->to
在进行了一次之后,
from空,to:1 help:i-1
from就变为的help,help就变成了from
(3)代码实现:
当仅有一个圆盘的时候,直接从form->to
当N个的时候,下面散步即为上述过程 输出相当于移动一个从from->to
4、字符串查找问题(二分法变形)
1、问题
2、代码
package com.lanqiao.vidio;
public class StringSearch {
public static void main(String[] args) {
String[] arr = {"a","","ab","","abc","b","ba"};
System.out.println(search(arr,"aa"));
}
private static int search(String[] arr, String str) {
int begin = 0;
int end = arr.length-1;
while(begin<=end)
{
int mid = begin + ((end-begin)/2);
while(arr[mid].equals(""))//!!!
{
mid++;
//注意!!
if(mid>end) return -1;
}
if(str.compareTo(arr[mid])>0)
begin=mid+1;
else if(str.compareTo(arr[mid])<0)
end=mid-1;
else if(str.compareTo(arr[mid])==0)
return mid;
}
return -1;
}
}
3、思想
(1)直接套二分法代码,把比大小的地方换成compareTo即可
(2)在中点定位到空串的时候,加一,默认右边一个为中值
4、注意点
(1)在定位到空串+1的时候,不能使用if判断,因为判断之后只+1,后面还是需要判断一次空串,浪费了时间。不断向前判断,直到没有空串为止。
(2)验证的时候,使用aa进行检验的时候,判断到前面的空串+1,到”ab“,陷入死循环。因此加一步判断,mid与end,如果mid高于end直接返回-1.
2、递推公式/等价转换
1、斐波那契数列 f(n)=f(n-1)+f(n-2)
2、最大公约数 f(m,n)=f(n,m%n)
代码:
public class gcd {
public static void main(String[] args) {
int a=30;
int b=50;
System.out.println(gcd1(a,b));
}
public static int gcd1(int m,int n)
{
if(n==0)
return m;
return gcd1(n,m%n);
}
}
3、二分查找
1、代码:
public class BinarySearch {
public static void main(String[] args) {
int[] arr = {1,3,5,7,9};
System.out.println(search(arr,0,4,3));
}
public static int search(int[] arr,int low,int high,int k)
{
if(low>high)
{
return -1;
}
int mid =low+(high-low)/2;
int midVal = arr[mid];
if(midVal<k)
return search(arr,mid+1,high,k);
else if(midVal>k)
return search(arr,low,mid-1,k);
else
return mid;
}
}
2、思路:
(1)找重复:都是从一组数中找到一个位置,即从中搜索
(2)找变化:每次high low值变化
(3)找边界:当low>high指针/找到值是结束
3、代码:
没啥好说的,注意return
4、台阶问题f(n)=f(n-3)+f(n-2)+f(n-1)
1、问题:
上台阶可以一次上3、2、1个,输入一个数字(表示距楼顶台阶数),输出一共可以有几种方式上到楼顶
2、代码
import java.util.Scanner;
public class jieti {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println(f(n));
}
private static int f(int n) {
if(n==0) return 1;
if(n==1) return 1;
if(n==2) return 2;
return f(n-1)+f(n-2)+f(n-3);
}
}
3、思路
(1)上台阶有三种方式:上一级:一种方式 上两级:两种方式(1+1、2) 上三级:四种方式(1+1+1、1+2、2+1、3)
(2)由上三级可以看出,三级=2级方式+1级方式+1(一次上三个台阶),因此可以把f(0)=1,这样既表示一次直接到达的方案