来源路径:http://blog.csdn.net/zheng0518/article/details/39211909
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;
- }