笔试题: 二叉排序数左移k个c / 二叉树的打印 / js有向图 【根据父子关系建树】

补题:
给定n最大10^5 ,1<=k<=100 , 给定n个数生成二叉排序树。然后都左移k位,输出左移后的前序遍历结果

样例
6 1 
3 1 2 5 4 6
输出
3 5 4 1 6 2

 

 移动后
        3
   5        1
      4    6  2 
前序(根左右)3 5  4 1 6 2
前方的k应该是往左移动

[ ----  代码中的move_val差不多是一横行里面的id、ans是横着记录的值 -----]

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <vector>
 4 using namespace std;
 5 typedef long long ll;
 6 int n, k;
 7 int a;
 8 int max_depth;
 9 bool print_first = true;
10 //vector<vector<int>> ans;
11 vector<vector<int>> ans;
12 struct node{
13     node *left=NULL;
14     node *right=NULL;
15     int val=-1;
16     int move_val = -1;
17     int step = -1;
18     node(int a,int stepp) { 
19         val = a;
20         step = stepp;
21     };
22 };
23 void find_and_place(int val,node* p,int step){
24     step = step + 1;
25     if(val<p->val){
26         if(p->left==NULL){
27             node *p2 = new node(val,step);
28             p->left = p2;
29             max_depth = max(max_depth, step);
30         }else{
31             find_and_place(val, p->left,step);
32         }
33     }else{
34         if(p->right==NULL){
35             node *p2 = new node(val,step);
36             p->right = p2;
37             max_depth = max(max_depth, step);
38         }else{
39             find_and_place(val, p->right,step);
40         }
41     }
42 }
43 
44 void record(node* p){
45     ans[p->step].push_back(p->val);
46     p->move_val = ans[p->step].size()-1;
47     if(p->left!=nullptr){
48         record(p->left);    
49     }
50     if(p->right!=nullptr){
51         record(p->right);
52     }
53 }
54 
55 
56 void print(node* p){
57     int size = ans[p->step].size();
58     int new_id = (p->move_val + size + k) % size;
59     if(print_first==true){   
60         print_first = false;
61     }else{
62         cout << " ";
63     }
64     cout << ans[p->step][new_id];//
65 
66 
67     if(p->left){
68         print(p->left);   
69     }
70     if(p->right){
71         print(p->right);
72     }
73 }
74 int main(){
75    // ans[0].push_back(1);
76     cin >> n >> k;
77     cin >> a;
78     node *root = new node(a,0);
79     //place
80     for (int i = 2; i <= n;i++){
81         cin >> a;
82         find_and_place(a,root,0);  
83     }
84     //vector<vector<int> > ans push
85     vector<int> v;
86     for (int i = 0; i <= max_depth;i++){
87         ans.push_back(v);
88     }
89     //move
90     record(root);
91 
92     //print
93     print(root);
94     cout << endl;
95 
96     system("pause");
97     return 0;
98 }
View Code

 

指针如果不初始化成NULL 怕是有随机变量、因为它并不是全局变量哦,但是NULL的话再初始化就是规范的0x0(十六进制地址)
这里一直往下left似乎没问题,在gdb调试下,就是这样的[并不是多重循环不停导致..,.,.]

标准的写法 建的树还挺完整的?先看,如果小了就往左,子已经NULL了就挂那,不null就继续找left那边

depth不对了,建树的时候,树、子树没搞明白;子树生成的时候depth应该+1,max_depth也要记录+1,root的应该是1,就生成的时候也统一一下是1
 emmm... 但是,vector套vector可不这么想,它 是从0开始计数的,那么这儿就错了=_=

修改了从0开始计数后,ans还少了一块,我一看我ans是从1开始push到n,但实际上vector里可并不是这样【和数组不同,数组可以赋值1-n,vector天然从0开始的呐】

那么以上都是vector的问题,解决了这个~~ record没问题了,开始print
这里是vector[ans] 不仅记录了当前的序号,(子树的横向顺序信号),还记录了子树的值

move_val实际上是: id
在子树的值,这一横排里,比如
2 4 6 8 
实际上我是往前移动了k才得到的,那么我的序号就是(p->move_val + size+k)%size

我们可以知道这个move_val实际上是id,就是它是这一横排里面的第几个。
不能简单的+2,我们可以看到是往前移,那么是+k就好了,当时-2应该是特定的3个情况下……  
为了避免越界,+size再%size
为了解决下标问题,直接从0开始吧,给move_val(也就是id)也从0开始记录

现在调整一下输出,既然正常前序没问题,那么---?
先看ans,好吧,发现ans是错的,那么应该各个depth都有错
啊这,竟然还是前面忘记step+1的小bug,看来应该每次进入直接+1~ 

现在看就没什么大问题了,主要是小问题不断,大思路没什么问题,总结如下:
(1)step的0/1关系搞错(子树应该+1、有个地方漏了+1)
(2)vector套vector那个ans没有push好,0和1搞错,不统一
(3)k是往前,样例没完全搞懂,只看片面3个导致错

 

试试其他样例呢?k=2没啥问题。
7 5
5 9 8 14 12 4 3
也没啥问题。那就这样吧

===============上文0515  0811新增js形式=========================

 

/* function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
} */
// 
function PrintFromTopToBottom(root){
    console.log(root);
    var queue=[];
    var ans=[];
    var tmp;
     console.log(queue.length);
    if(root==null)return ans;
    queue.push(root);
  
    while(queue.length){
        tmp=queue[0];
        ans.push(queue[0].val)
        queue.shift();
        if(tmp.left){
            queue.push(tmp.left);
        }
        if(tmp.right){
            queue.push(tmp.right);
        }
    }
    return ans
    // write code here
}
module.exports = {
    PrintFromTopToBottom : PrintFromTopToBottom
};

注意js里的queue要这样模拟,手动front queue[0] 手动shfit() 移除顶部元素 (pop的话是移除底部元素。如果写了返回值接续,那就会返回被删除的那个~

二叉树的话,注意给出的和指向的,接上就行。

 

 

SC 数据补题1 是否有环能到达

console.log(findWhetherExistsPath( 3,[[0, 1],  [1, 2], [1, 2]],0,2  ));
递归。。实际上就是判断正常的环就好了
(1)还是用邻接表来做,所以应该是一个二维数组,也是笨办法创建的
 for(let i=0;i<=max;i++){
        var cc=new Array();
        edges.push(cc);
    }
因为给出的是从0开始的,当时笔试的n也忘了是啥,所以额外做了一个max的筛查,到时候 用的情况自己看情况搞(max、数组长度这种的)
(2)邻接表常规操作 分别push
edges[c1].push(c2)
edges[c2].push(c1)
(3)设置visited数组,因为有环所以期望只访问一次,从start开始,先推入queue (推入start的边们)
(4)while(queue.length>0){
然后保存queue[0]为front  queue再shift弹出
对front遍历【此时front里面就是start里面的数组,所以直接front.length  front[i] 
具体的也就这了
 
function findWhetherExistsPath( n ,  graph ,  start ,  end ) {  
    var edges=[];
    var max=-1;
    for(let i=0;i<graph.length;i++){
        for(let j=0;j<graph.length;j++){
            if(graph[i][j]>max){
                max=graph[i][j];
            }
        }
    }
    for(let i=0;i<=max;i++){
        var cc=new Array();
        edges.push(cc);
    }
    // edges里有max个 但是是从0开始的。。 
    // 所以写了max+1个~ 0可用可不用了就
    for(let i=0;i<graph.length;i++){
        var c1=graph[i][0]
        var c2=graph[i][1]
       edges[c1].push(c2)
       edges[c2].push(c1)
    }
   let queue=new Array();
   let visited=new Array(max+1);
   queue.push(edges[start]);
   // 【直接fill吧】
   //  注意edges里面是2维的 edges[start]是一维的 也就是一维里面仍然是[1 2 4]这样
  //  访问应该是edges[start][i] ==> front=edges[start] => front[i] 
   while(queue.length>0){
       let front=queue[0];
       queue.shift();
       for(let i=0;i<front.length;i++){
            let edge=front[i];
            if(visited[edge])continue;
            else {
                if(edge==end)return true;
                visited[edge]=1;
                queue.push(edge);
            }
       }
   }
   return false;
}

console.log(findWhetherExistsPath( 7,[[1,2],[1,4],[1, 2],  [2, 3], [3, 4],[4,5],[2,6]],3, 6 ));

 

SC 数据补题2===========================

给出一组数组,如[1, 2, 3], [2, 4], [3], [4]
每个数组中第一个是父元素,其他是子元素
求树最长的高度 
getLinkNodeIdList([[1, 2, 3], [2, 4], [3], [4]])
根据这个界定,应该是先【根据父子关系建立二叉树】
还是没啥头绪,继续看看以前的吧
1、【首先。。】我对这个题目意思有一定的误解。。
既然是树,还是从上往下,那么根节点肯定是1了,这个毋庸置疑~~  这个是排列的顺序决定的,如果不是应该会有额外说明。
2、这样题目就可以转化成知道根节点,知道父子关系但是不知道高度(这样也是,符合题意的!)
3、这么说,感觉依然可以用邻接表做。这不是和一个easy dfs一样了么……
Q 还需要visited吗?(不需要了)
Q 对于高度如何做出统计?可以dfs(昨天那样坐牢写法),也可以直接先排序,然后从下往上回去,从子树开始叠加高度,这样比较ok但是,需要写sort
好的,那也是来试一下吧
sort这样的写好了!
注意要给rec数组fill 0 ,这样才能方便后续遍历。(如果是undefined可以相应!rec,但是比较max的时候会是NaN
=============研究一下js里的sort==================
对于sort:array.sort(sortby)
可传入手写的function,对于正常的字母可以按照字母序排列,但数字不太ok
① 从新建数组开始:
var array=new Array() 
var array=new Array(1,2,3) var array=[1,2,3,...]
② 实际上js的sort()是对unicode码来排序的,因此对于简单数组列,会出错~(默认排序顺序是根据字符串UniCode码,转换时也是先转成字符串)
如果是1 2 3 这样的数组是看不出来的。换成10,5,40,25,1000,1则很明显,无论里面的元素是用的“10”还是10,都只会排成 1,5,10,25,40,1000
③ 可以进行自定义,解决上述的 数组问题,也可以对于对象一样操作。
数组问题:sort传入sortby函数
function sortby(a,b) {
    return a-b;
}// 这样 就直接返回升序~如果是倒序传b-a
 
在c++里sort函数 的return
return a>b 那么a-b>0时返回true(满足),a-b<=0时false
所以c++可以写return a>b也可以写return(a-b>0)
这里前面的大为true,所以是从大到小排列,写a<b的时候是从小到大(升序)
 
要明确:
return a-b和return a-b>0是不一样的,前者是直接return一个数字
 
js的:
1 如果想按照其他标准进行排序,就需要提供比较函数,该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。比较函数应该具有两个参数 a 和 b,其返回值如下:
若 a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。
若 a 等于 b,则返回 0。
若 a 大于 b,则返回一个大于 0 的值。
2 js里如果是return a-b>0(像c++那样)就不会有小于0的值了,所以排序不了。(需要return一个数……)记得是return a-b
3 怎么记升序降序呢:
升序是a-b,这个没有>0啊啊啊,所以不能用c++那一套去记,只是我们知道,a小的时候返回负数,就是小于0的值,是常规的操作
b-a不常规,因此是降序(大的在前,不符合预期心理 )
4 如果 是针对对象(对象数组)
var arr1=[
    {name:'1',age:'34'},
    {name:'2',age:'30'},
    {name:'3',age:'60'}
]
// 注意 传入的prop和a b是两个。。 注意区分
function sortby(prop) {
    return function (a,b) {
        return a[prop]-b[prop];
    }
}
arr1.sort(sortby('age'));
或者这么写
        let value1=a[prop];
        let value2=b[prop]
        return value1-value2;
这样就是按照prop(可以传入,比如age)属性来升序了哦~
对象的话,首先注意sortby函数在写的时候,要传入一个属性才行,其次a和b不用手动传入但是参数上还是要有。最后在调用的时候里面也一定要加上参数!!!! arr1.sort(sortby('age'));
===================sortend================================

 

// 根据关系建树部分 
 //  应该也是不能简化的因为你单独的a b哪有fa属性啊。。
function sortby(prop) {
    return function (a,b) {
        return b[props]-a[props];
    }
}
function getLinkNodeIdList( nodeList ) {
    var nodes=[];// array
    for(let i=0;i<nodeList.length;i++){  
        var obj={
            fa:nodeList[i].shift(),// 返回值是数组原来的第一个元素的值。。。
            son:nodeList[i]
        }
        nodes.push(obj);
    }
    nodes.sort(sortby('fa'));
    var rec=new Array(9999).fill(0);
    var maxx=-1;
    for(let i=0;i<nodes.length;i++){  
       let fa=nodes[i].fa;
       for(let j=0;j<nodes[i].son.length;j++){
            let son=nodes[i].son[j];
            if(!rec[son]){
                rec[son]=1;
                console.log('QAQ')
            }
            rec[fa]=Math.max(rec[fa],rec[son]+1);  
            console.log(i,j,nodes[i],fa,rec[fa]);
            maxx=Math.max(rec[fa],maxx);
       }
    }
    return maxx;
}

console.log(getLinkNodeIdList([[1, 2, 3],[2,4,5], [3], [5,6,7],[4],[6,8],[8],[7]]));

///console.log(getLinkNodeIdList([[1, 2, 3], [2, 4], [3], [4]]));

 

 
posted @ 2021-05-15 12:27  send/me/a/cat  阅读(166)  评论(0编辑  收藏  举报