TreeNode* ClosestNode(TreeNode* root, double target) { if(target == root->val) { return root; } if(target < root->val) { if(root->left == NULL) { return root; } TreeNode* left = ClosestNode(root->left, target); if(abs(left->val - target) < abs(root->val - target)) { return left; } return root; } if(root->right == NULL) { return root; } TreeNode* right = ClosestNode(root->right, target); if(abs(right->val - target) < abs(root->val - target)) { return right; } return root; }
vector<int> closestKValues(TreeNode* root, double target, int k) { TreeNode* start = ClosestNode(root, target); vector<TreeNode*> left_stack; BuildStack(root, start, left_stack); vector<TreeNode*> right_stack(left_stack.begin(), left_stack.end()); vector<int> result; result.push_back(start->val); TreeNode* larger_node = NULL; TreeNode* smaller_node = NULL; while(result.size() < k) { if(larger_node == NULL) { larger_node = LargerNode(right_stack); } if(smaller_node == NULL) { smaller_node = SmallerNode(left_stack); } if(larger_node == NULL) { result.push_back(smaller_node->val); smaller_node = NULL; continue; } if(smaller_node == NULL) { result.push_back(larger_node->val); larger_node = NULL; continue; } if(abs(smaller_node->val - target) < abs(larger_node->val - target)) { result.push_back(smaller_node->val); smaller_node = NULL; } else { result.push_back(larger_node->val); larger_node = NULL; } } return result; }
BOOL CcdrawDoc::AddArcSegment(CComplex p0, CComplex p1, CArcSegment &asegm, double tol) { int i,j,k; CSegment segm; CArcSegment newarc; CComplex c,p[2]; CArray< CComplex, CComplex&> newnodes; double R,d,dmin,t; asegm.n0=ClosestNode(p0.re,p0.im); asegm.n1=ClosestNode(p1.re,p1.im); newnodes.RemoveAll(); // don't add if line is degenerate if (asegm.n0==asegm.n1) return FALSE; // don't add if the arc is already in the list; for(i=0;i<arclist.GetSize();i++){ if ((arclist[i].n0==asegm.n0) && (arclist[i].n1==asegm.n1) && (fabs(arclist[i].ArcLength-asegm.ArcLength)<1.e-02)) return FALSE; // arcs are ``the same'' if start and end points are the same, and if // the arc lengths are relatively close (but a lot farther than // machine precision... } // add proposed arc to the linelist asegm.IsSelected=FALSE; // check to see if there are intersections for(i=0;i<linelist.GetSize();i++) { j=GetLineArcIntersection(linelist[i],asegm,p); if(j>0) for(k=0;k<j;k++) newnodes.Add(p[k]); } for(i=0;i<arclist.GetSize();i++) { j=GetArcArcIntersection(asegm,arclist[i],p); if(j>0) for(k=0;k<j;k++) newnodes.Add(p[k]); } // add nodes at intersections if (tol==0) { if (nodelist.GetSize()<2) t=1.e-08; else{ CComplex p0,p1; p0=nodelist[0].CC(); p1=p0; for(i=1;i<nodelist.GetSize();i++) { if(nodelist[i].x<p0.re) p0.re=nodelist[i].x; if(nodelist[i].x>p1.re) p1.re=nodelist[i].x; if(nodelist[i].y<p0.im) p0.im=nodelist[i].y; if(nodelist[i].y>p1.im) p1.im=nodelist[i].y; } t=abs(p1-p0)*CLOSE_ENOUGH; } } else t=tol; for(i=0;i<newnodes.GetSize();i++) AddNode(newnodes[i].re,newnodes[i].im,t); // add proposed arc segment; arclist.Add(asegm); // check to see if proposed arc passes through other points; // if so, delete arc and create arcs that link intermediate points; // does this by recursive use of AddArcSegment; UnselectAll(); GetCircle(asegm,c,R); if (tol==0) dmin=fabs(R*PI*asegm.ArcLength/180.)*1.e-05; else dmin=tol; k=(int) arclist.GetSize()-1; for(i=0;i<nodelist.GetSize();i++) { if( (i!=asegm.n0) && (i!=asegm.n1) ) { d=ShortestDistanceFromArc(CComplex(nodelist[i].x,nodelist[i].y), arclist[k]); if (d<dmin){ CComplex a0,a1,a2; a0.Set(nodelist[asegm.n0].x,nodelist[asegm.n0].y); a1.Set(nodelist[asegm.n1].x,nodelist[asegm.n1].y); a2.Set(nodelist[i].x,nodelist[i].y); arclist[k].ToggleSelect(); DeleteSelectedArcSegments(); newarc=asegm; newarc.n1=i; newarc.ArcLength=arg((a2-c)/(a0-c))*180./PI; AddArcSegment(newarc,dmin); newarc=asegm; newarc.n0=i; newarc.ArcLength=arg((a1-c)/(a2-c))*180./PI; AddArcSegment(newarc,dmin); i=(int) nodelist.GetSize(); } } } return TRUE; }
BOOL CcdrawDoc::AddSegment(CComplex p0, CComplex p1, CSegment &segm, double tol) { int i,j,k,n0,n1; double xi,yi,t; CComplex p[2]; CArray< CComplex, CComplex&> newnodes; newnodes.RemoveAll(); n0=ClosestNode(p0.re,p0.im); n1=ClosestNode(p1.re,p1.im); // don't add if line is degenerate if (n0==n1) return FALSE; // don't add if the line is already in the list; for(i=0;i<linelist.GetSize();i++){ if ((linelist[i].n0==n0) && (linelist[i].n1==n1)) return FALSE; if ((linelist[i].n0==n1) && (linelist[i].n1==n0)) return FALSE; } segm.IsSelected=FALSE; segm.n0=n0; segm.n1=n1; // check to see if there are intersections with segments for(i=0;i<linelist.GetSize();i++) if(GetIntersection(n0,n1,i,&xi,&yi)==TRUE) newnodes.Add(CComplex(xi,yi)); // check to see if there are intersections with arcs for(i=0;i<arclist.GetSize();i++){ j=GetLineArcIntersection(segm,arclist[i],p); if (j>0) for(k=0;k<j;k++) newnodes.Add(p[k]); } // add nodes at intersections if(tol==0) { if (nodelist.GetSize()<2) t=1.e-08; else{ CComplex p0,p1; p0=nodelist[0].CC(); p1=p0; for(i=1;i<nodelist.GetSize();i++) { if(nodelist[i].x<p0.re) p0.re=nodelist[i].x; if(nodelist[i].x>p1.re) p1.re=nodelist[i].x; if(nodelist[i].y<p0.im) p0.im=nodelist[i].y; if(nodelist[i].y>p1.im) p1.im=nodelist[i].y; } t=abs(p1-p0)*CLOSE_ENOUGH; } } else t=tol; for(i=0;i<newnodes.GetSize();i++) AddNode(newnodes[i].re,newnodes[i].im,t); // Add proposed line segment linelist.Add(segm); // check to see if proposed line passes through other points; // if so, delete line and create lines that link intermediate points; // does this by recursive use of AddSegment; double d,dmin; UnselectAll(); if (tol==0) dmin=abs(nodelist[n1].CC()-nodelist[n0].CC())*1.e-05; else dmin=tol; k=(int) linelist.GetSize()-1; for(i=0;i<nodelist.GetSize();i++) { if( (i!=n0) && (i!=n1) ) { d=ShortestDistance(nodelist[i].x,nodelist[i].y,k); // catch a special case... if (abs(nodelist[i].CC()-nodelist[n0].CC())<dmin) d=2.*dmin; if (abs(nodelist[i].CC()-nodelist[n1].CC())<dmin) d=2.*dmin; if (d<dmin){ linelist[k].ToggleSelect(); DeleteSelectedSegments(); AddSegment(n0,i,&segm,dmin); AddSegment(i,n1,&segm,dmin); i=(int) nodelist.GetSize(); } } } return TRUE; }