* 算法系列 <https://blog.csdn.net/nakiri_arisu/article/details/79341527#算法系列>
* 最小栈实现 <https://blog.csdn.net/nakiri_arisu/article/details/79341527#最小栈实现>
* 判断2的乘方 <https://blog.csdn.net/nakiri_arisu/article/details/79341527#判断2的乘方>
* 找出缺失的整数
<https://blog.csdn.net/nakiri_arisu/article/details/79341527#找出缺失的整数>
* 辗转相除法是什么鬼
<https://blog.csdn.net/nakiri_arisu/article/details/79341527#辗转相除法是什么鬼>
* Bitmap 算法
<https://blog.csdn.net/nakiri_arisu/article/details/79341527#bitmap-算法>

<https://mp.weixin.qq.com/s/n2QA0q_NGDcnrg6a50fy9Q>

stackMin第一个元素正常入栈，之后入栈的元素和stackMin栈顶的元素相比，若小于等于
(等于这个条件非常关键，想想为什么)则入stackMin。getMin直接返回stackMin栈顶元素（peek）。pop的时候如果Stack栈顶的值等于最小值，则双Stack同步pop。

public class StackPro{ private Stack<Integer> storeData; private
Stack<Integer> storeMin;public StackPro(){ storeData = new Stack<Integer>();
storeMin =new Stack<Integer>(); } public void push(Integer item){ if
(storeMin.isEmpty()){ storeMin.push(item); }else if(item<=storeMin.peek()){
storeMin.push(item); } storeData.push(item); }public Integer pop(){ if
(storeData.isEmpty())throw new RuntimeException("Your stack is Empty!"); if
(storeData.peek()==getMin()){//minStack的判断在getMin()里进行 storeMin.pop(); } return
storeData.pop(); }public Integer getMin(){ if(storeMin.isEmpty()) throw new
RuntimeException("Your stack is Empty"); return storeMin.peek(); } }

/** 只需要相应改写push和pop方法就行了，其他的省略 **/ public void push(Integer item){ if
(storeMin.isEmpty()){ storeMin.push(item); }else{ if(item<storeMin.peek()){
storeMin.push(item); }else{ storeMin.push(storeMin.peek()); } }
storeData.push(item); }public Integer pop(){ if(storeData.isEmpty()) throw new
RuntimeException("Your stack is Empty!"); storeMin.pop(); return
storeData.pop(); }

public boolean is2Fang(int target){ int tmp = 1; while(tmp<=target){ if
(tmp==target)return true; else tmp<<=1; } return false; }

public boolean is2FangPro(int target){ return 0==(target&target-1);
//由于运算符优先级关系，target-1不需要括号 }

public int getLackNum(int [] arr){ int [] bitMap = new int[100]; //100个0 for(
int j=0;j<arr.length;j++){ bitMap[arr[j]-1]=1; //存在100则把下标为99的格子染黑 } for(int x=0
;x<100;x++){ if(1!=bitMap[x]) return x+1; } return -1; //找不到返回-1 }

public int getLackNum(int [] arr){ Map<Integer,Integer> map = new
HashMap<Integer,Integer>();for(int i=1;i<=100;i++){ map.put(i, 0); } //初始化map
for(int x : arr){ //涂黑 map.put(x,1); } Iterator<Entry<Integer,Integer>> it =
map.entrySet().iterator();while(it.hasNext()){ Map.Entry<Integer, Integer>
entry = it.next(); Integer key = entry.getKey(); Integer value =
entry.getValue();if(value==0) return key; } return -1; }

public int getLackNum(int [] arr){ Arrays.sort(arr); for(int i=1
;i<arr.length;i++){if((arr[i]-arr[i-1])!=1) return arr[i-1]+1; } return -1; }

public int getLackNum(int [] arr){ int sum = 5050; for(int i=0
;i<arr.length;i++){ sum-=arr[i]; }return sum; }

public int getLackNum(int [] arr){ int result = 0; //根据亦或的规律 for(int i=0
;i<arr.length;i++) result = result^arr[i];return result; }

public int[] getLackNum(int[] arr) { int [] result = new int[2]; //结果集 int []
bitMap =new int[100]; //无序数组全量表长度 for (int n : arr) { bitMap[n - 1] = bitMap[n -
1] == 1 ? 0 : 1; } int index = 0; for(int i=0;i<bitMap.length;i++){ if
(bitMap[i]==1) result[index++] = i+1; if(index == 2) return result; } return
result; }

public int gcb(int a, int b) { if(a==b) return a; if(a<b) return gcd(b,a);
return gcd(b,a%b); }

return 1。 于是1001和1000的最大公约数为1。

public static int gcb(int a,int b){ if(a==b) return a; if(a<b) return gcd(b,a);
return gcd(b,a-b); }

/** 同时利用 &1运算来判断奇数偶数。 */ public static int gcd(int a, int b) { if(a==b) return
b;if(a<b){ return gcd(b,a); }else{ if((a&1)==0&&(b&1)==0) return gcd(a>>1,b>>1
)<<1; //关键点 不然结果会小2的N次幂 else if((a&1)==0&&(b&1)==1) return gcd(a>>1,b); else if
((a&1)==1&&(b&1)==0) return gcd(a,b>>1); else return gcd(b,a-b); } }

1. 暴力枚举法：时间复杂度是O(min(a, b)))
2. 辗转相除法：时间复杂度不太好计算，可以近似为O(log(max(a, b)))，但是取模运算性能较差。
3. 更相减损术：避免了取模运算，但是算法性能不稳定，最坏时间复杂度为O(max(a, b)))
4. 更相减损术与移位结合：不但避免了取模运算，而且算法性能稳定，时间复杂度O(log(max(a, b)))

Bitmap 算法

EWAHCompressedBitmap