算法竞赛入门读书笔记(自用,慎入)
2016-05-09 11:29
375 查看
例3.2最长回文子串
书中讲的很好,主要难点在三处
1. 输入字符串要含有空格,对应java下的readLine()方法即可
2. 查找回文串,暴力搜索,书中从中间搜索,没感觉复杂度降低多少
3. 原样输出,这就需要记录去除特殊符号后的串对应原串相应位置.(很常用的方法)
import java.util.Scanner; public class Test { public static void main(String[] args) { Scanner input = new Scanner(System.in); int max = 0,x = 0,y = 0;//分别记录最大值,和对应原位置的下标 String str = input.nextLine(); int[] p = new int[str.length()];//记录原位置的数组 char[] s = new char[str.length()];//记录去除特舒符号后的串 //去除特殊符号并记录新数组中元素在原数组中位置 for (int i = 0,m = 0; i < str.length(); i++) { if (Character.isLetter(str.charAt(i))) { p[m] = i; s[m++] = Character.toLowerCase(str.charAt(i)); } } //开始查找回文串,利用StringBuilder的reverse来进行比较即可 //基本思路就是暴力方法 String strTemp = new String(s).trim(); for (int i = 0; i < strTemp.length(); i++) { for (int j = i+1; j < strTemp.length(); j++) { StringBuilder builder = new StringBuilder(strTemp.substring(i, j)); //当两者正反一致的时候说明为回文串 if (builder.toString().equals(builder.reverse().toString())) { if (j-i > max) { max = j - i; x = i; y = j; } } } } System.out.println(str.substring(p[x],p[y])); } }
5.1.3周期串
对于周期性问题,大多数都可以通过取余来得到一定的周期关系.对于定长字符串最好的操作还是转换成字符数组,方便修改和查找.
import java.util.Arrays; public class Test2 { public static void main(String[] args) { String str = "aaa"; char[] c = (str).toCharArray(); //i的值实际上就是循环节的大小,故要从1开始,还可以避免除0 for (int i = 1; i < c.length; i++) { boolean iscan = true;//标志变量 if ((c.length) % i == 0) {//如果能整除i,则表示可能为当前这个子串 for (int j = i; j < c.length; j++) { //因为是循环,这里利用取余来判断 if (c[j] != c[j%i]) { iscan = false; break; } } if (iscan) { System.out.println(i); } } } System.out.println(Arrays.toString(c)); } }
5.31 6174问题
传统的学习循环,学习怎么取出数字的指定位数
import java.util.Arrays; import java.util.LinkedHashMap; import java.util.Scanner; public class Test3 { public static void main(String[] args) { //利用hash链表来存储每次计算产生的结果 LinkedHashMap<Integer, Integer> map = new LinkedHashMap<>(); Scanner input = new Scanner(System.in); int n = input.nextInt(); map.put(n, n); int count = 0; //循环小于1000,也就是最多找1000个整数 while(count <= 1000){ int max = getNum(n, true); int min = getNum(n, false); n = max - min; //如果计算过了则退出 if (map.containsKey(n)) { break; } map.put(n, n); count++; } System.out.println(map.toString()+"---"+n); } /** * 输入一个整数,计算出他正排和倒排的值 * @param n * @param order true表示正排 * @return */ private static int getNum(int n,boolean order){ int[] arr = new int[4]; int i = 0; while(n>0){ arr[i] = n % 10; n = n / 10; i++; } Arrays.sort(arr); if (order) { return arr[3]*1000+arr[2]*100+arr[1]*10+arr[0]; } return arr[0]*1000+arr[1]*100+arr[2]*10+arr[3]; } }
5.31 字母重排
这里涉及了字符串的比较,一位一位的比较太过于繁琐,所以可以先排序后比较,就方便很多了5.41 Cantor数表
这种找规律得题一般可以用技巧,先用预处理把一些可能用到计算的数据先保存起来,后面直接用,另外注意java里面写好的二分查找方法,很实用,还能自定义比较器import java.util.Arrays; import java.util.Scanner; public class Test4 { public static void main(String[] args) { //预处理计算出前K项的和 int arr[] = new int[1000]; for (int i = 1; i < arr.length; i++) { arr[i] = (i+1)*i/2; } System.out.println(Arrays.toString(arr)); //主程序开始 Scanner input = new Scanner(System.in); // int n = input.nextInt(); int n = 7; //二分查找,找到比这个数小的位置的k int mid = Arrays.binarySearch(arr, n); if (mid<0) {//如果没找到则返回插入位置,也就是第一个小于n得位置 mid = -mid-1;//确定该元素是第mid+1斜线上的元素 System.out.println((mid+1+n-arr[mid])+"/"+(arr[mid]-n+1)); }else {//如果找到了则直接输出 System.out.println(mid+"/"+(n-arr[mid]+1)); } } }
6.1.1卡片游戏
主要是java队列得简单用法,代码很清晰,另外这是双端队列,可以直接操作队头或者队尾
import java.util.ArrayDeque; public class Test5 { public static void main(String[] args) { //构造一个初始容量为10得队列 ArrayDeque<Integer> queue = new ArrayDeque<>(10); //对于队列一般实用offer,poll,peek等方法,这几个可以通过返回值判断是否成功 for (int i = 1; i < 8; i++) { queue.offer(i); } while(!queue.isEmpty()){ System.out.println(queue.pollFirst());; if (queue.peek() != null) { queue.offer(queue.poll()); } } } }
6.3.1小球下落
对于二叉树得数组表示法,因为知道了深度就知道二叉树总节点数,因为二叉树本身是等比数列,可以用1<<D来表示其节点数,而且如果按从上到下从左到右排序得话,节点k得左孩子是2k,右孩子是2k+1
import java.util.Arrays; import java.util.Scanner; public class Test6 { public static void main(String[] args) { int D,I; Scanner input = new Scanner(System.in); D = input.nextInt(); I = input.nextInt(); boolean[] s = new boolean[1<<D];//s[0]不用 for (int j = 0; j < I; j++) {//对小球循环 //每一个小球滚落模拟 int j2 = 1; for (; ;) { s[j2] = !s[j2];//转动开关 if (s[j2]) {//关闭向左 j2 = 2*j2; }else {//开启向右 j2 = 2*j2+1; } if (j2 > s.length-1) { break; } } System.out.println(j2/2);//除以2找到最后经过的节点 } System.out.println(Arrays.toString(s)); } }
6.4最大公约数问题
最大公约数最方便的就是辗转相除法,最小公倍数就是a*b/gcd(a,b)public static int gcd(int a, int b) { //基本公式如果a%b!=0 那么 gcd(a,b) = gcd(b,a%b) while (true) { if ((a = a % b) == 0) return b; if ((b = b % a) == 0) return a; } }
相关文章推荐
- 腾讯云对象存储服务(cos)之PHP实践
- Window 2008 IIS下搭建网站及调试
- Spring 整合 Redis
- Makefile选项CFLAGS,LDFLAGS,LIBS
- 不用任何第三方工具,如何备份InnoDB?生产环境
- 如何在Ubuntu手机click包中打入第三方应用库
- KMP算法
- 离线yum源挂载及yum服务器搭建
- 域名解析中A记录、CNAME、MX记录、NS记录的区别和联系
- 离线yum源挂载及yum服务器搭建
- 标记扩展和 WPF XAML
- InnoDB自增列重复值问题
- Qt元对象系统(二)【根据moc文件解析Q_OBJECT】
- 在ASP.NET 2.0中操作数据之三十二:数据控件的嵌套
- Python正则表达式
- centos各版本含义
- java.util.concurrent.Exchanger应用范例与原理浅析--转载
- 凸包模版 HDU1392 Surround the Trees
- AppCan + 腾讯浏览服务:更快的APP
- 日志减肥