Given an array of n integer, and a moving window(size k), move the window at each iteration from the start of the array, find the median of the element inside the window at each moving. (If there are even numbers in the array, return the N/2-th number after sorting the element in the window. )
这道题在Lintcode上面的通过率只有3%,确实这道题花了我一个晚上的时间,主要是在处理一个细节上上让我检查了一个晚上,也是由于自己思维不够缜密吧
这道题我是用红黑树做的,对于重复元素维护一个val值来进行计数,插入时如果遇到相同相同元素 val值自增,删除时如果val值大于1则自减,否则按照正常逻辑操作,
首先建树花费klogk时间,然后(k+1)/2找到第一个中位数, 然后对于剩下的(n-k)次找中位数,每次都执行一次删除和一次插入查找以及一次后继或者前驱操作,时间复杂度logk,所以总得时间复杂度为 (n-k)logk
首先对前N个数构建红黑树,然后中序遍历找到第一个中位数,
由于窗口在移动过程中只改变首尾两个值,所以只要判断收尾两个值和当前中位数的值的关系就很容易找到新的中位数,然后删除首增加尾直到完成遍历。
关键点在于怎么根据首尾值及当前中位数来获取新的中位数,对于同一个元素有多个的情况下,还需要p值来记录当前中位数是元素中得第几个,而算法实现的难点也在于怎么处理p值的变化。
具体操作也是先进行插入,求中位数,再进行删除。
设首值l,尾值c,当前中位数m(在实现中为树节点)
如果l>c>m || l
如果c
如果l
如果l=m
//
// main.cpp
// Sliding Window Median
//
// Created by 孟文斌 on 15/4/29.
// Copyright (c) 2015年 孟文斌. All rights reserved.
//
#include
#include
#include
using namespace std;
const int COLOR_RED = 0;
const int COLOR_BLACK = 1;
struct TreeNodes{
int key;
int val;
int color;//0red 1black
TreeNodes* p;
TreeNodes *left;
TreeNodes *right;
TreeNodes(int x,int c,TreeNodes *init):key(x),val(1),color(c),p(init),left(init),right(init){}
TreeNodes(int x,int c):key(x),val(1),color(c),p(NULL),left(NULL),right(NULL){}
};
TreeNodes * const nill = new TreeNodes(-1,COLOR_BLACK);
class RBTree{
private:
TreeNodes * root;
//when val is not the minmun of the Tree find the Node which key is min less than the val
//when val is the minmun of the Tree find the Node which key is min larger than the val
TreeNodes* findPos(int val){
TreeNodes *t = root;
TreeNodes *pre = root;
while(t != nill){
if(t->key == val) return t;
pre = t;
if(t->key < val) t = t->right;
else t = t->left;
}
return pre;
}
void RB_left_rotate(TreeNodes* t){//t call left rotation operation
if(t == NULL || t == nill) return;
TreeNodes* p = t->p,*s = t->right;
if(s == nill) return;
t->right = s->left;
if(s->left != nill) s->left->p = t;
s->left = t;
t->p = s;
if(p != nill){
if(p->left == t) p->left = s;
else p->right = s;
}else{
root = s;
}
s->p = p;
}
void RB_right_rotate(TreeNodes* t){//t call right rotation operation
if(t == NULL || t == nill) return;
TreeNodes* p = t->p,*s = t->left;
if(s == nill) return;
t->left = s->right;
if(s->right != nill) s->right->p = t;
s->right = t;
t->p = s;
if(p != nill){
if(p->left == t) p->left = s;
else p->right = s;
}else{
root = s;
}
s->p = p;
}
void RB_insert_fixup(TreeNodes* t){
if(t == nill || t->p == root) return;
while(t->p->color == COLOR_RED){
if(t->p == t->p->p->left){//t's father is in left tree
// t's father and uncle are both red: change father and uncle into black and t's grandfather into red
if(t->p->p->right->color == COLOR_RED){
t->p->color = COLOR_BLACK;
t->p->p->right->color = COLOR_BLACK;
t->p->p->color = COLOR_RED;
t = t->p->p;
}else{
if(t == t->p->right) {//uncle is black and t is the right child
t = t->p;
RB_left_rotate(t);
}
t->p->color = COLOR_BLACK;//uncle is black and t is the left child
t->p->p->color = COLOR_RED;
RB_right_rotate(t->p->p);
}
}else {//exchange the direction
if(t->p->p->left->color == COLOR_RED){
t->p->color = COLOR_BLACK;
t->p->p->left->color = COLOR_BLACK;
t->p->p->color = COLOR_RED;
t = t->p->p;
}else{
if(t == t->p->left) {
t = t->p;
RB_right_rotate(t);
}
t->p->color = COLOR_BLACK;
t->p->p->color = COLOR_RED;
RB_left_rotate(t->p->p);
}
}
}
root->color = COLOR_BLACK;
}
void RB_delete_fixup(TreeNodes* t){
if(t == NULL) return;
TreeNodes* w = NULL;
while(t != root && t->color == COLOR_BLACK){
if(t == t->p->left){//t is left child
w = t->p->right;
if(w->color == COLOR_RED){//brother is red
w->color = COLOR_BLACK;
t->p->color = COLOR_RED;
RB_left_rotate(t->p);
w = t->p->right;
}
if(w->left->color==COLOR_BLACK && w->right->color==COLOR_BLACK){
//brother is black and his children are also black
w->color = COLOR_RED;
t = t->p;
}else {
if(w->right->color == COLOR_BLACK){//left child is black and right child is red
w->left->color = COLOR_BLACK;
w->color = COLOR_RED;
RB_right_rotate(w);
w = t->p->right;
}
w->color = t->p->color;//right child is red
t->p->color = COLOR_BLACK;
w->right->color = COLOR_BLACK;
RB_left_rotate(t->p);
t = root;
}
}else{//exchanged all direction
w = t->p->left;
if(w->color == COLOR_RED){//brother is red
w->color = COLOR_BLACK;
t->p->color = COLOR_RED;
RB_right_rotate(t->p);
w = t->p->left;
}
if(w->left->color==COLOR_BLACK && w->right->color==COLOR_BLACK){//brother is black and his children are also black
w->color = COLOR_RED;
t = t->p;
}else {
if(w->left->color == COLOR_BLACK){//left child is black and right child is red
w->right->color = COLOR_BLACK;
w->color = COLOR_RED;
RB_left_rotate(w);
w = t->p->left;
}
w->color = t->p->color;//right child is red
w->left->color = COLOR_BLACK;
t->p->color = COLOR_BLACK;
RB_right_rotate(t->p);
t = root;
}
}
}
t->color = COLOR_BLACK;
}
/**
* insert a Node into the Tree
*/
void insertTreeNodes(TreeNodes* t){
TreeNodes * pre = findPos(t->key);//find the pos to insert
if(pre->key == t->key) {
pre->val++;
return;
}
if(pre->key < t->key) pre->right = t;
else pre->left = t;
t->p = pre;
RB_insert_fixup(t);// fix the tree
}
/**
* delete a Node from the Tree
*/
void deleteTreeNodes(TreeNodes* z){
if(z == NULL || z==nill) {
return;
}
TreeNodes *y = NULL,*x = NULL;
if(z->left==nill || z->right==nill) y = z;//t is single
else y = Tree_Successor(z,z->val);// t has both right and left child
if(y->left != nill) x = y->left;//t's left child is not nill point x to s's left
else x = y->right;
x->p = y->p; //point x's parent to s's parent even if it is a NIL for the fix of the tree
if(y->p == nill) root = x;
else if(y->p->left == y) y->p->left = x;
else y->p->right = x;
if(y != z) {
z->key = y->key; // chage the z to y and y is deleted
z->val = y->val;
y->left = NULL;
y->p = z;
y->right = NULL;
}
if(y->color == COLOR_BLACK) RB_delete_fixup(x);//fix the tree
}
TreeNodes * Tree_Minimum(TreeNodes *x){
TreeNodes *r = x;
while(r->left != nill)
r = r->left;
return r;
}
TreeNodes * Tree_Maximum(TreeNodes *x){
TreeNodes *r = x;
while(r->right != nill)
r = r->right;
return r;
}
public:
RBTree(){
root = nill;
}
/**
* insert val into tree
*/
void insertVal(int val){
if(root == NULL || root == nill) {
root = new TreeNodes(val,COLOR_BLACK,nill);
return;
}
TreeNodes *t = new TreeNodes(val,COLOR_RED,nill);
insertTreeNodes(t);
}
void deleteVal(int val){
TreeNodes *z = findPos(val);
if(z->key != val) return;// can't find the val
if(z->val > 1) {
z->val--;
return;
}
deleteTreeNodes(z);
}
TreeNodes * Tree_Predecesor(TreeNodes *x,int& p){
if(p > 1) {
p--;
return x;
}
if(x->left != nill){
TreeNodes *t = Tree_Maximum(x->left);
p = t->val;
return t;
}
TreeNodes *y = x->p;
while(y != nill && x == y->left){
x = y;
y = y->p;
}
p = y->val;
return y;
}
TreeNodes * Tree_Successor(TreeNodes *x,int& p){
if(p < x->val) {
p++;
return x;
}
if(x->right != nill){
p = 1;
return Tree_Minimum(x->right);
}
TreeNodes *y = x->p;
while(y != nill && x == y->right){
x = y;
y = y->p;
}
p = 1;
return y;
}
TreeNodes* getPosM(int m,int &p){
if(!root) return root;
stack<TreeNodes*> s;
TreeNodes* tmp = root;
int num=0;
while(tmp!=nill){
s.push(tmp);
tmp = tmp->left;
}
while(!s.empty()){
tmp = s.top();
s.pop();
num += tmp->val;
if(num >= m) {
p = tmp->val - num + m;
return tmp;
}
tmp = tmp->right;
while(tmp != nill){
s.push(tmp);
tmp = tmp->left;
}
}
return root;
}
};
class Solution {
public:
/**
* @param nums: A list of integers.
* @return: The median of the element inside the window at each moving
*/
vector<int> medianSlidingWindow(vector<int> &nums, int k) {
// write your code here
int n = (int)nums.size();
vector<int> res;
if(n==0 || k == 0 || n
if(k==1) return nums;
RBTree b;
for(int i=0;i b.insertVal(nums[i]); } int p = 1; TreeNodes *m = b.getPosM((k+1)/2,p); res.push_back(m->key); int l,c; for(int i=k;i l = nums[i-k];c = nums[i]; if(l == c){ res.push_back(m->key); continue; } b.insertVal(c); if(l > c){ if(c < m->key && l >= m->key){ m = b.Tree_Predecesor(m,p); } }else if(l < c){ if(c == m->key) { p++; }else if(l == m->key){//here is very easy to enter trap.............important if(p == m->val)m = b.Tree_Successor(m,p); }else if(l < m->key && c > m->key) { m = b.Tree_Successor(m,p); } } b.deleteVal(l); if(m->left == NULL) m = m->p; res.push_back(m->key); } return res; } }; void displayVector(vector<int> &res){ for(int i=0;i cout< } cout<<endl; } int main(int argc, const char * argv[]) { // 1811,1202,917,535,570,883, // vector vector<int> nums = {34,454,6,4,36,345,7547,654,8,65,7,65,7,54,6,45,6,45,345,23,4,234,23,423,4,32,4,234,23,4,234,32,423,4,234,4,324,32,4,354326,547,57,56,8,6,456,342,5,34534,5,342,6,547568,657,54,6,435,345,43,5,43647,567,65,7,546,34,5,34,523,5,543,45,34,5,43,654,7,5,7,56,4,634,5,23,43,54326,456,5,7,564,7,546,43,6,435,23,4,234,2,4,234,3,45,43,6,46,45,6,456,45,64,56,45,645,6,546,54,6,456,45,6,546,435,423,64,57,56,87,69,80,5462,43,5,435,235,423,5,43,6,45,65,7,658,65,4,754,7,457,54,6745,457,453,7,345,7,547,634,25,34,5,2,5,6457,456,8,9,76,9,7,65754,6,45,32,5,34,52,345,34}; // vector vector<int> res; Solution sol; res = sol.medianSlidingWindow(nums,3); displayVector(res); return 0; }