给定一颗二叉树的头节点head,求符合搜索二叉树的最大结构的大小
class Node{
int value;
Node right;
Node left;
Node(int data){
this.value = data;
}
}
class Record{
int l;
int r;
Record(int _l,int _r) : l(_l), r(_r){}
}
int bstTopoSize2(Node head){
unordered_map<Node,Record> map;
return posOrder(head,map);
}
int posOrder(Node h,unordered_map<Node,Record> & map){
if(h == null){
return 0;
}
int ls = posOrder(h.left,map);
int rs = posOrder(h.right,map);
modifyMap(h.left,h.value,map,true);
modifyMap(h.right,h.value,map,false);
Record lr = map[h.left];
Record rr = map[h.right];
int lbst = lr == null ? 0 : lr.l + lr.r + 1;
int rbst = rr == null ? 0 : rr.l + rr.r + 1;
map.insert(h,new Record(lbst,rbst));
return max(lbst + rbst + 1,max(ls,rs));
}
int modifyMap(Node h,int v,unordered_map<Node,Record> & map,bool s){
if(h == null || (!map.contains(h))){
return 0;
}
Record r = map[h];
if((s && h.value > v) || ((!s) && h.value < v){
map.erase(h);
return r.l + r.r + 1;
}else{
int minus = modifyMap(s ? h.right : h.left, v, map,s);
if(s){
r.r = r.r - minus;
}else{
r.l = r.l - minus;
}
map.insert(h,r);
return minus;
}
}
完美洗牌问题
3^k -1的偶数数有固定的触发点(3 ^ (k-1))
例如8: 1,3 ; 26: 1,3,9
int modifiyIndex1(int i,int len){
if(i < len / 2){
return 2 * i;
}else{
return 2 * ( i - (len / 2)) - 1;
}
int modifiyIndex2(int i,int len){
return (2 * i) % (len + 1);
}
void shuffle(vector<int> & arr){
if(arr != null && arr.size() != 0 && (arr.size() & 1) == 0){
shuffle(arr,0,arr.size() - 1);
}
}
void shuffle(vector<int> & arr,int l,int r){
while(r - l + 1 > 0){
int len = r - l + 1;
int base = 3;
int k = 1;
while(base <= (len + 1) / 3){
base *= 3;
k ++;
}
int half = (base - 1) / 2;
int mid = (l + r) / 2;
rotate(arr, l + half,mid,mid + half);
cycles(arr,l,base - 1,k);
l = l + base - 1;
}
}
void cycles(vector<int> & arr,int start,int len,int k){
for(int i = 0,trigger = 1; i < k; i ++,trigger *= 3){
int preValue = arr[trigger + start -1];
int cur = modifyIndex2(trigger, len);
while(cur != trigger){
int tmp = arr[cur + start -1];
arr[cur + start - 1] = preValue;
preValue = tmp;
cur = modifyIndex2(cur,len);
}
arr[cur + start -1] = preValue;
}
}
void rotate(vectro<int>& arr,int start,int mid,int end){
reverse(arr.begin() + start,arr.begin() + end);
reverse(arr.begin() + start,arr.begin() + mid);
reverse(arr.begin() + mid + 1,arr.begin() + end);
}
给定一个无序数组,将数组变为第一个小于等于第二个数,第二个数大于等于第三个数,第三个数小于等于第四个数…
思路(空间复杂度O(1)):
- 先将数组堆排序
- 判断数组大小奇数偶数
- 如果为偶数,直接将数组进行完美洗牌,并以两两一组对数组的数数字进行交换
- 如果为奇数,第一个数不参与,将剩余数按照偶数的步骤进行
字符串匹配问题
bool isVaild(string &str,string & exp){
for(int i = 0; i < str.size(); i++){
if(str[i] == '*' || str[i] == '.'){
return false;
}
}
for(int i = 0;i < exp.size(); i++){
if(exp[i] == '*' && (i == 0 || exp[i - 1] == '*'){
return false;
}
}
return true;
}
bool isMath(string str,string exp){
if(str == null || exp == null){
return false;
}
if(!isValid(str,exp)){
return false;
}
int slen = str.size(),elen = exp.size();
vector<vector<bool>> dp(slen + 1,vector<bool>(elen + 1,false));
dp[slen][elen] = true;
for(int j = elen - 2;j >= 0;j -= 2){
if(exp[j] != '*' && exp[j + 1] == '*'){
dp[slen][j] = true;
}else{
break;
}
}
if(slen > 0 && elen > 0){
if(exp[elen - 1] == '.' || str[slen - 1] == exp[elen - 1]){
dp[slen - 1][elen - 1] = true;
}
}
for(int
for(int i = str.size() - 1; i >= 0;i--){
for(int j = exp.size() - 2;j >= 0;j--){
if(str[j + 1] != '*'){
dp[i][j] = (str[i] == exp[j] || exp[j] == '.') && dp[i + 1][j + 1];
}else{
int si = i;
while(si != str.size() && (str[si] == exp[j] || exp[j] == '.')){
if(dp[si][j + 2]){
dp[i][j] = true;
break;
}
si ++;
}
if(dp[i][j] != true){
dp[i][j] = dp[si][j + 2];
}
}
}
}
return dp[0][0];
}
给定一个数组,求最大异或和
class Node{
Node nexts[2];
}
class NumTrie{
Node head = new Node();
void add(int num){
Node cur = head;
for(int move = 31; move >= 0;move --){
int path = ((num >> move) & 1);
cur.nexts[path] = cur.nexts[path] == null ? new Node() : cur.nexts[path];
cur = cur.nexts[path];
}
}
int maxXor(int sum){
Node cur = head;
int res = 0;
for(int move = 31; move >= 0; move --){
int path = (sum >> move) & 1;
int best = move == 31 ? path : (path ^ 1);
best = cur.nexts[path] != null ? best : (best ^ 1);
res |= (path ^ best) << move;
cur = cur.nexts[best];
}
}
}
int maxXorSubarray(vector<int> & arr){
if(arr == null || arr.size() == 0){
return 0;
}
int max = INT_MAX;
int sum = 0;
NumTire numTire = new NumTire();
numTire.add(0);
for(int i = 0; i < arr.size(); i ++){
sum ^= arr[i];
max = max (max,numTire.maxXor(sum));
numTire.add(sum);
}
return max;
}
气球得分问题
例如3,2,5
打3 32 ,打2 2 5,打5 5 最后得21
3 32,5 25 ,2 2, 18
2,325,3 3*5,5 50
…最后最高得分为50
int maxCoins(vector<int> & arr){
if(arr == null || arr.size() == 0){
return 0;
}
int n = arr.size();
if(n == 1){
arr[0];
}
vector<int> help(n + 2,1);
for(int i = 0;i < n; i ++){
help[i + 1] = arr[i];
}
return process(help,1,n);
}
int process(vector<int> & arr,int l,int r){
if(l == r){
return arr[l -1] * arr[l] * arr[r + 1];
}
int max = max(arr[l - 1] * arr[l] * arr[r + 1] + process(arr,l + 1,r),arr[l - 1] * arr[r] * arr[r + 1] + process(arr,l,r -1);
for(int i = l + 1;i < r; i ++){
max = max(max,arr[l - 1] * arr[i] * arr[r + 1] + process(arr,l,i - 1) + process(arr,i + 1, r));
}
return max;
}
给定数组判断是最优汉洛洛塔的第几步,无效返回-1
int process(vector<int> & arr,int i,int from,int other,int to){
if(i == -1){
return 0;
}
if(arr[i] != from && arr[i] != to){
return -1;
}
if(arr[i] == from){
return process(arr,i - 1,from,other,to);
}else{
int rest = process(arr, i - 1,other,from, to);
if(rest == -1){
return -1;
}
return (1 << i) + rest;
}
}
给定两个字符串,判断是不是s2是否为s1的旋变字符串
int process(string &s1,string &s2,int l1,int l2,int size){
if(size == 1){
return s1[l1] == s2[l2];
}
for(int leftpart = 1;leftpart < size;leftpart ++){
if((process(s1,s2,l1,l2,leftpart) && process(s1,s2,l1 + leftpart,l2 + leftpart,size - leftpart) || (process(s1,s2,l1,l2 + size - leftpart,leftpart) &&process(s1,s2,l1 + leftpart,l2,size - leftpart)){
return true;
}
}
return false;
}
bool sameTypeNumber(string &s1,string &s2){
if(s1.length != s2.length){
return false;
}
vector<int> cnt(256);
for(char c : str1){
cnt[c] ++;
}
for(char c : str2){
if(--cnt[c] < 0){
return false;
}
}
return true;
}
bool isScreamble1(string &s1,string & s2){
if((s1 == null && s2 != null) || (s1 != null && s2 == null){
return false;
}
if(s1 == s2){
return true;
}
if(!sameTypeNumber(s1,s2)){
return false;
}
int n = s1.length;
return process(s1,s2,0,0,n);
}
给定两字符串,求s1中含有s2的所有字符的最小子串长度
滑动窗口,加个数
给定油数组和距离数组,路为环形,求一个合格的出发点数组(bool)
先计算两数组差,小于0的点一定不是合格出发点
定义rest,need,判断范围内是否联通
然后向两边扩张[start,end)
先向end方向扩张如果rest + nums[end] >0表示可以进入联通区域,小于0表示当前start不是合格出发点。
然后向start方向扩张,1、如果nums[start] < 0,则need += nums[start];该节点不是合格出发点。2、如果nums[start]>0,则判断该点是否与前面的出发点联通,如果可以则rest += nums[i] + need;重复向end的动作;
如果该点是合格出发点,则只需要向start的方向扩张,判断该点与合格点是否联通是则该点是合格出发点。
当判断到start 为end的前一个节点,如果前面没有合格出发点,则还没有判断的点也是不合格出发点
求线段的最大重叠问题
先将线段按照起始节点排序,然后定义一个有序表(储存线段的结尾位置,开始时为空)
依次遍历线段的节点,如果有序表中的节点有小于遍历节点的起始位置,则弹出有序表中小于起始位置的值。然后将该节点的结束 位置加入有序表,有序表节点的个数为重叠的线段的个数,重复该步骤直到结束。
求矩形重叠最大问题
先将矩形的右下节点排序,定义一个容器储存矩形
遍历矩形,将容器中所有矩形左上点的y小于等于当前矩形的右下删除,一直到不能删除时候,加入当前矩形。将容器所有矩形压缩为线段,求线段最大重叠问题。重复该步骤。