算法基础(三)
桶排序、计数排序、基数排序的介绍
1,非基于比较的排序,与被排序的样本的实际数据状况很有关系,所以实际中并不经常使用
2,时间复杂度O(N),额外空间复杂度O(N)
3,稳定的排序
例子
给定一个数组,求如果排序之后,相邻两数的最大差值,要求时 间复杂度O(N),且要求不能用非基于比较的排序
public static int maxGap(int[] nums){ if(nums==null||nums.length<2) return 0; int len=nums.length; int min=Integer.MAX_VALUE; int max=Integer.MIN_VALUE; //找出数组中的最大数和最小数 for (int i = 0; i < len; i++) { min=Math.min(min,nums[i]); max=Math.max(max,nums[i]); } //如果数组中只有一种数字,直接返回 if(min==max) return 0; //记录是否是空桶,true表示不是空桶 boolean[] hasNum=new boolean[len+1]; //记录每个桶的最大值和最小值 int[] maxs=new int[len+1]; int[] mins=new int[len+1]; int bid=0; for (int i = 0; i < len; i++) { bid=bucket(nums[i],len,min,max); mins[bid]=hasNum[bid]?Math.min(mins[bid],nums[i]):nums[i]; maxs[bid]=hasNum[bid]?Math.max(maxs[bid],nums[i]):nums[i]; hasNum[bid]=true; } int res=0; int lastMax=maxs[0]; int i=1; //找一个非空桶及离它最近的非空桶,后桶的最小值减去前桶的最大值,找出最大差值 for (; i <=len ; i++) { if(hasNum[i]){ res=Math.max(res,mins[i]-lastMax); lastMax=maxs[i]; } } return res; } //当前数字属于几号桶 public static int bucket(long num,long len,long min,long max){ return (int)((num-min)*len/(max-min)); }
题目:用数组结构实现大小固定的栈
public class ArrayStack { private Integer[] arr; private Integer index; public ArrayStack(int initSize){ if(initSize<0) throw new IllegalArgumentException("the init size is less than 0"); arr=new Integer[initSize]; index=0; } //压栈 public void push(int obj){ if(index==arr.length) throw new ArrayIndexOutOfBoundsException("the queue if full"); arr[index++]=obj; } //返回栈顶,不弹出 public Integer peek(){ if(index==0) return null; return arr[index-1]; } //返回栈顶,弹出 public Integer pop(){ if(index==0) throw new ArrayIndexOutOfBoundsException("the queue is empty"); return arr[--index]; } }
题目:用数组结构实现大小固定的队列
public class ArrayQueue { private Integer[] arr; private Integer size; private Integer start; private Integer end; public ArrayQueue(int initSize){ if(initSize<0) throw new IllegalArgumentException("the init size is less than 0"); arr=new Integer[initSize]; size=0; start=0; end=0; } public void push(int obj){ if(size==arr.length) throw new ArrayIndexOutOfBoundsException("the queue is full"); size++; arr[end]=obj; end=end==arr.length-1?0:end+1; } public Integer peek(){ if(size==0) return null; return arr[start]; } public Integer poll(){ if(size==0) throw new ArrayIndexOutOfBoundsException("the quere is empty"); size--; int temp=start; start=start==arr.length-1?0:start+1; return arr[temp]; } }
题目
实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返 回栈中最小元素的操作。
【要求】 1.pop、push、getMin操作的时间复杂度都是O(1)。 2.设计的栈类型可以使用现成的栈结构
public class MinStack { private Stack<Integer> stackData; private Stack<Integer> stackMin; public MinStack(){ stackData=new Stack<Integer>(); stackMin=new Stack<Integer>(); } public void push(int newNum){ if(stackMin.isEmpty()){ stackMin.push(newNum); }else if(newNum<getmin()){ stackMin.push(newNum); }else{ int newMin=stackMin.peek(); stackMin.push(newMin); } stackData.push(newNum); } public int pop(){ if(stackMin.isEmpty()) throw new RuntimeException("stack is empty"); stackMin.pop(); return stackData.pop(); } public int getmin(){ if(stackMin.isEmpty()){ throw new RuntimeException("stack is empty"); } return stackMin.peek(); } }
题目:如何仅用队列结构实现栈结构?
public class TwoQueueStack { private Queue<Integer> data; private Queue<Integer> help; public TwoQueueStack(){ data=new LinkedList<Integer>(); help=new LinkedList<Integer>(); } public void push(int pushInt){ data.add(pushInt); } public int pop(){ if(data.isEmpty()){ throw new RuntimeException("Stack is empty"); } //把data队列的数拿出添加到help,只剩下1个数 while(data.size()>1) { help.add(data.poll()); } //剩下的数,一会返回这个数 int res=data.poll(); //data队列是空的,拿出的数都在help中,交换两个队列 swap(); return res; } public int peek(){ if(data.isEmpty()){ throw new RuntimeException("Stack is empty"); } while(data.size()!=1){ help.add(data.poll()); } int res=data.poll(); //不弹出,所以重新添加回去 help.add(res); swap(); return res; } private void swap(){ Queue<Integer> tmp=help; help=data; data=tmp; } }
题目:如何仅用栈结构实现队列结构?
public class TwoStackQueue { private Stack<Integer> stackPush; private Stack<Integer> stackPop; public TwoStackQueue(){ stackPush=new Stack<Integer>(); stackPop=new Stack<Integer>(); } public void push(int pushInt){ stackPush.push(pushInt); dao(); } public int poll(){ if(stackPush.isEmpty()&&stackPop.isEmpty()) throw new RuntimeException("queue is empty"); dao(); return stackPop.pop(); } public int peek(){ if(stackPush.isEmpty()&&stackPop.isEmpty()) throw new RuntimeException("queue is empty"); dao(); return stackPop.peek(); } public void dao(){ if(!stackPop.isEmpty()){ return; } while (!stackPush.isEmpty()){ stackPop.push(stackPush.pop()); } } }