不足地方还请多多指教,欢迎大家多多分享
2、用O(n)的算法,实现对一组无序的字母进行从小到大排序(区分大小写),相同的字母,小写在大写前
思路:空间换时间,把52个字母映射为52个数字,并记录出现的次数,然后迭代输出
public static void main(String[] args) { // A=65,Z=90 a=97,z=122 char[] src = { 'R', 'B', 'B', 'b', 'W', 'W', 'B', 'R', 'B', 'w' }; src = sortCharsOn(src); for (char c : src) { System.out.print(c + " "); } } /** * O(n)的时间复杂度对给定的字符数组进行排序 * * @param src * 原数组 * @return 排序后的数组 */ private static char[] sortCharsOn(char[] src) { int[] items = new int[54];// 用于保存52个字符 char[] des = new char[src.length]; for (int i = 0; i < src.length; i++) { if (src[i] < 'z' && src[i] > 'a') { // 小写对应于items中下标为偶数 items[(src[i] - 'a') * 2]++; } else if (src[i] < 'Z' && src[i] > 'A') { // 大写对应于items中下标为奇数 items[(src[i] - 'A') * 2 + 1]++; } } int index = 0; for (int i = 0; i < items.length; i++) { if (items[i] != 0) {// items[i],就是该字符出现的次数 if (i % 2 == 0) { for (int j = 0; j < items[i]; j++) { des[index++] = (char) (i / 2 + 'a');// 转化成小写 } } else { for (int j = 0; j < items[i]; j++) { des[index++] = (char) ((i - 1) / 2 + 'A');// 转化成大写 } } } } return des; }
3、给定N个磁盘,每个磁盘大小为D[i],i=0...N-1,现在要在这N个磁盘上"顺序分配"M个分区,每个分区大小为P[j],
j=0....M-1,顺序分配的意思是:分配一个分区P[j]时,如果当前磁盘剩余空间足够,则在当前磁盘分配;如果不够,则
尝试下一个磁盘,直到找到一个磁盘D[i+k]可以容纳该分区,分配下一个分区P[j+1]时,则从当前磁盘D[i+k]的剩余
空间开始分配,不在使用D[i+k]之前磁盘末分配的空间,如果这M个分区不能在这N个磁盘完全分配,则认为分配失败,请
实现函数,is_allocable判断给定N个磁盘(数组D)和M个分区(数组P),是否会出现分配失败的情况。
举例:磁盘为[120,120,120],分区为[60,60,80,20,80]可分配 ,如果为[60,80,80,20,80]则分配失败
public static void main(String[] args) { int[] d = { 120, 120, 120 };// 磁盘 // int[] p = { 60, 60, 80, 20, 80 };// 分区 int[] p = { 60, 80, 80, 20, 80 };// 分区 if (is_allocable(d, p)) { System.out.println("分配成功"); } else { System.out.println("分配失败"); } } private static boolean is_allocable(int[] d, int[] p) { int pindex = 0;//记录已分配的分区 boolean isAllocable = false;//用来记录是否分配成功 for (int i = 0; i < d.length; i++) {//对所有磁盘遍历 while (d[i] > 0) {//如果该磁盘还有剩余空间,就一直迭代 if (p[pindex] <= d[i]) {//如果磁盘空间足够,就分配,否则,进入下一个磁盘 d[i] -= p[pindex++]; if (pindex == p.length) {//如果已分配的分区数跟传入的一值,意味着分配成功 isAllocable = true; break; } } else { break; } } if (isAllocable) { break; } } return isAllocable; }
4、给定正整数X,定义函数A(n)=1+x+x^2+x^3+...+x^n(n为整数且>=0),已知乘运算的时间远大于加运算,
输入x,n:如何尽可能快的求出A(n)
这题应该有更好的解决方法吧。。
public static void main(String[] args) { Scanner s = new Scanner(System.in); int x = s.nextInt(); int n = s.nextInt(); long temp = x+1; for(int i=0;i<n-1;i++){ temp = temp*x+1; } System.out.println(temp); }
5、请实现方法:print_rotate_matrix(int matrix,int n),来将一个n X n二维数组
* 逆时针旋转45度后打印,例如,下图显示一个3X3的二维数组及其旋转后屏幕输出的效果
* <br/>
* 123 旋转45度 3 3
* 456------> 2 6 屏幕输出 2 6
* 789 1 5 9 -----> 1 5 9
* 4 8 4 8
* 7 7
*
* 思路:从右上角开始打印....
3
26
159
48
7
public static void main(String[] args) { Scanner s = new Scanner(System.in); System.out.println("请输入几维数组:"); int n = s.nextInt(); int [][]matrix = new int[n][n]; for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ matrix[i][j]=i*n+(j+1); } } print_rotate_matrix(matrix,n); } private static void print_rotate_matrix(int[][] matrix, int n) { //a[0][2] //a[0][1] a[1][2] //a[0][0] a[1][1] a[2][2] //a[1][0] a[2][1] //a[2][0] int f,s;//第一维,第二维坐标 for(int i=n-1;i>=0;i--){//打印上半部分 f=0; s=i; while(s<n){ System.out.print(matrix[f++][s++]); } System.out.println(); } for(int i=1;i<n;i++){//打印下半部分 f=i; s=0; while(f<n){ System.out.print(matrix[f++][s++]); } System.out.println(); } }
6、已知队列支持先进先出的操作(add/remove),而栈则直技先进后出的操作push/pop,请用两个队列实现栈
先进后出的操作,希望该栈的push/pop时间复杂度尽量小。
请写出push/pop的代码,需要考虑栈溢出(stackoverflow)的情况
思路:顺序不一样,队列1接收的数据,由队列2来反转顺序。队列1只进,队列2只出
public class MyStack<T> { Queue<T> q1, q2; public MyStack() { q1 = new LinkedBlockingQueue<T>(); q2 = new LinkedBlockingQueue<T>(); } public void push(T value) { q1.add(value); } public T pop() { if(!q2.isEmpty()) return q2.poll(); while(!q1.isEmpty()) q2.add(q1.poll()); return q2.poll(); } }
举一反三,由两个栈实现队列:
public class MyQueue<E> { private Stack<E> s1, s2; public MyQueue() { s1 = new Stack<E>(); s2 = new Stack<E>(); } public int size() { return s1.size() + s2.size(); } public void add(E value) { s1.push(value); } public E peek() { if (!s2.empty()) s2.peek(); while (!s1.empty()) s2.push(s1.pop()); return s2.peek(); } public E remove() { if (!s2.empty()) s2.pop(); while (!s1.empty()) s2.push(s1.pop()); return null; } }
7、假设有一个中央调度机,有n个相同的任务需要调度到m台服务器上去执行,由于每台服务器的配置不一样,因此服务器
执行一个任务所花费的时间也不同。现在假设第i个服务器执行一个任务所花费的时间也不同。现在假设第i个服务器执行 一个任务需要的时间为t[i].
例如:有2个执行机a,b,执行一个任务分别需要7min,10min,有6个任务待调度。如果平分这6个任务,即a,b各3个
任务,则最短需要30min执行完所有。如果a分4个任务 ,b分2个任务,则最短28min执行完。 请设计调度算法,使得所有任务完成所需要的时间最短。
输入m台服务器,每台机器处理一个任务的时间为t[i],完成n个任务,输出n个任务在m台服务器的分布。 int
estimate_process_time(int[] t,int m,int n)
思路:用一个数组记录每台机器已执行的时间(初始为0),在调度每一个任务的时候,对每一台机器需要执行的时间进行对比(已执行的时间加上需要执行该任务的时间
public static void main(String[] args) { Scanner s = new Scanner(System.in); int t[] = new int[100]; System.out.println("请输入几台机子:"); int m = s.nextInt(); int i = 0; System.out.println("输入每台机子的时间:"); while (m-- > 0) { t[i++] = s.nextInt(); } System.out.println("请输入多少任务:"); int n = s.nextInt(); int total = estimate_process_time(t, i, n); System.out.println("最小需要" + total); } /** * @param t 每个服务器处理的时间 * @param m 多少台服务器 * @param n 多少个任务 * @return */ private static int estimate_process_time(int[] t, int m, int n) { int total = 0; int k; int apply[] = new int[m];// 记录m个机器已执行的时间,初始全为0 for (int i = 0; i < n; i++) {// 遍历n个任务 int tmp = apply[0] + t[0];//用来记录分配该任务给第j个机器所需要的时间(已执行的时间加需要执行的时间) k = 0; for (int j = 1; j < m; j++) {// 遍历m个机器 if (tmp > apply[j] + t[j]) {//遍历所有机器,选择时间最短的 tmp = apply[j] + t[j]; k = j;// 把该任务分配给第j个机器 } } apply[k] += t[k]; total = tmp; } for (int i = 0; i < m; i++) { System.out.println("第"+(i+1)+"台服务器有"+apply[i]/t[i]+"个任务,运行了"+apply[i]); } return total; }
8、n(1,2,3.....n)个元素有N!个不同的排列,将这n!个数按字典序排列,并编号0,1...n!-1,每个排号为其字典序的值,如n=3时,字典排序为123,132,213,231,312,321,这6个数的字典序分别为0,1,2,3,4,5.,现给定n,请输出字典序为k 的排列(0<=k<n!)
public static void main(String[] args) { long l1 = System.currentTimeMillis(); System.out.println("请输入要对前n个数字进行排列:"); Scanner s = new Scanner(System.in); int n = s.nextInt(); System.out.println("请输入需要的第K个:"); int k = s.nextInt(); int[] arry = new int[n]; for (int i = 0; i < arry.length; i++) { arry[i] = i + 1; } // System.out.println(Arrays.toString(getInt(arry))); do { if (k == 0){ System.out.println(Arrays.toString(getInt(arry))); break; } k--; } while (next(arry)); long l2 = System.currentTimeMillis(); System.out.print("共耗时" + (l2 - l1) + "耗秒"); } private static int[] getInt(int[] arry) { int[] arry1 = new int[arry.length]; System.arraycopy(arry, 0, arry1, 0, arry.length); return arry1; } private static boolean next(int[] arry) { int pos1 = -1; int pos2 = -1; // 从右到左,找到第一个比右边小的数,记录位置pos1 for (int i = arry.length - 1; i > 0; i--) { if (arry[i - 1] < arry[i]) { pos1 = i - 1; break; } } if (pos1 < 0) { return false; } // 在pos1位置后的数字中找出比它大的数中最小的一个,然后交换位置,在逆转 for (int i = arry.length - 1; i > pos1; i--) { if (arry[i] > arry[pos1]) { pos2 = i; swap(arry, pos2, pos1); reserve(arry, pos1 + 1, arry.length - 1); break; } } if (pos2 < 0) { return false; } return true; } /** * * 逆转数组中第i个到第j个的数,比如数组为123,i=0,j=2,则逆转为321 * * @param arry * @param i * @param j */ private static void reserve(int[] arry, int i, int j) { for (; i <= j; i++, j--) { swap(arry, i, j); } } /** * 交换一个数组中第i个和第j个数的值 * * @param array * @param i * @param j */ private static void swap(int[] array, int i, int j) { int temp = array[j]; array[j] = array[i]; array[i] = temp; }