javascript剑指offer编程练习#7

第五十六题

题目描述
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

/*function ListNode(x){
    this.val = x;
    this.next = null;
}*/
function deleteDuplication(pHead)
{
    // write code here
    if(!pHead||pHead.next===null){
       return pHead
    }
    let p = pHead
    if(pHead.val === p.next.val){
        p=p.next.next
        while(p!==null&&p.val===pHead.val){
            p=p.next // 跳过值与当前结点相同的全部结点,找到第一个与当前结点不同的结点
        }
        return deleteDuplication(p)
    }else{
        p=pHead.next
        pHead.next=deleteDuplication(p)
        return pHead
    }
    
}

第五十七题

题目描述
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

/*function TreeLinkNode(x){
    this.val = x;
    this.left = null;
    this.right = null;
    this.next = null;
}*/
function GetNext(pNode)
{
    // write code here
    if(pNode===null)
        return null;
    // write code here
    //如果该节点有右子树,那么该节点的下一个节点,就是右子树最左的节点
    if(pNode.right){
        let root=pNode.right;
        while(root.left!==null){
            root=root.left;
        }
        return root;
    }
    //没右子树,则找第一个当前节点是父节点左孩子的节点
     while(pNode.next!==null){
            if(pNode.next.left===pNode)
                return pNode.next;
            pNode = pNode.next;
        }
    return null;
}

第五十八题

题目描述
请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。

/* function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
} */
function isSymmetrical(pRoot)
{
    // write code here
    if(pRoot==null){
        return true
    }
    return judge(pRoot.left,pRoot.right)
}
function judge(left,right){
    if(left==null){return right==null}
    if(right==null){return false}
    if(left.val!=right.val){return false}
    return judge(left.left,right.right)&&judge(left.right,right.left)
}

第五十九题

题目描述
请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。

/* function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
} */
function Print(pRoot)
{
    // write code here
    if(!pRoot){
        return []
    }
    let que=[],res=[]
    que.push(pRoot)
    let flag=false
    while(que.length>0){
        let vec=[]
        let len=que.length
        for(let i=0;i<len;i++){
            let tmp=que.shift()
            vec.push(tmp.val)
            if(tmp.left){
                que.push(tmp.left)
            }
            if(tmp.right){
                que.push(tmp.right)
            }
        }
        if(flag){
            vec.reverse()
        }
        res.push(vec)
        flag=!flag
    }
     return res
    
}

第六十题

题目描述
从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。

/* function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
} */
function Print(pRoot)
{
    // write code here
    if(!pRoot){
        return []
    }
    let que=[],res=[]
    que.push(pRoot)

    while(que.length>0){
        let vec=[]
        let len=que.length
        for(let i=0;i<len;i++){
            let tmp=que.shift()
            vec.push(tmp.val)
            if(tmp.left){
                que.push(tmp.left)
            }
            if(tmp.right){
                que.push(tmp.right)
            }
        }
        res.push(vec)
   
    }
     return res
    
}

第六十一题

题目描述
请实现两个函数,分别用来序列化和反序列化二叉树

/* function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
} */
function Serialize(pNode) {
    var str = [];
    ser(pNode);

    for(var i = str.length - 1; i >= 0; i--){
      if(str[i] !== '#'){
        break;
      }
      str.pop();
    }

    return str.join();

    function ser(node){
        if(!node){
            str.push('#');
            return;
        }
        str.push(node.val);
        ser(node.left);
        ser(node.right);
    }
}
function Deserialize(str) {
    var index = -1;
    var len = str.length;
    if(index >= len){
        return null;
    }
    var arr = str.split(",");
    var head = des();

    return head;

    function des(node){
        index++;
        if(arr[index] && arr[index] !== '#'){
            var temp = new TreeNode(arr[index]);
            node = temp;
            node.left = des();
            node.right = des();
        }
        return node;
    }
}
  • 对于序列化:使用前序遍历,递归的将二叉树的值转化为字符,并且在每次二叉树的结点
    不为空时,在转化val所得的字符之后添加一个’ , '作为分割。对于空节点则以 ‘#’ 代替。
  • 对于反序列化:按照前序顺序,递归的使用字符串中的字符创建一个二叉树(特别注意:
    在递归时,递归函数的参数一定要是char ** ,这样才能保证每次递归后指向字符串的指针会
    随着递归的进行而移动!!!)

第六十二题

题目描述
给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。

/* function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
} */
function KthNode(pRoot, k)
{
    // write code here
    if(!pRoot||!k){
        return null
    }
    return KthCore(pRoot)
    function KthCore(node){
        let target=null
        if(node.left){
            target=KthCore(node.left)
        }
        if(!target){
            if(k===1){
                target=node
            }
            k--
        }
        if(!target&&node.right){
            target=KthCore(node.right)
        }
        return target
    }
}

二叉查找树(英语:Binary Search Tree),也称为二叉搜索树、有序二叉树(ordered binary tree)或排序二叉树(sorted binary tree),是指一棵空树或者具有下列性质的二叉树:

  • 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
  • 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
  • 任意节点的左、右子树也分别为二叉查找树;
  • 没有键值相等的节点。

第六十三题

题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

let arr=[]
function Insert(num)
{
    // write code here
    arr.push(num)
    arr.sort(function(a,b){
             return a-b
     })
    return arr
}
function GetMedian(){
	// write code here
    let mid=Math.floor(arr.length/2)
    if((arr.length&1)===0){
        return (arr[mid-1]+arr[mid])/2
    }else{
        return arr[mid]
    }
}

第六十四题

题目描述
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。

function maxInWindows(num, size)
{
    // write code here
    let res=[]
    if(!num||num.length===0||size===0){
        return res
    }
    let count=num.length-size
    for(let i=0;i<=count;i++){
        let temp=num.slice(i,i+size)
        res.push(Math.max.apply(this,temp))
    }
    return res
    
}

第六十五题

题目描述
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。 例如 a b c e s f c s a d e e 这样的3 X 4 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。

function hasPath(matrix, rows, cols, path)
{
    // write code here
    let visited=[]
    let pathLen=0
    for(let i=0;i<cols*rows;i++){
        visited[i]=false
    }
    for(let i=0;i<rows;i++){
        for(let j=0;j<cols;j++){
            if(run(i,j)){
                return true
            }
        }
    }
    return false
    function run (row,col){
        if(path.length===pathLen){
            return true
        }
        let hasPath=false
        if(row>=0&&row<rows&&col>=0&&col<cols&&matrix[row*cols+col]===path[pathLen]&&!visited[row*cols+col]){
            pathLen++
            visited[row*cols+col]=true
            hasPath=run(row+1,col)+run(row-1,col)+run(row,col+1)+run(row,col-1)
            if(!hasPath){
                pathLen--
                visited[row*cols+col]=false
            }
        }
        return hasPath
    }
    
}

第六十六题

题目描述
地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?

function movingCount(threshold, rows, cols)
{
    // write code here
        var visited = [];
    for(var i = 0; i < rows * cols; ++i)
        visited[i] = false;
    var count = movingCountCore(0, 0);
    visited.length = 0;
    return count;

    function getDigitSum(number){
        var sum = 0;
        while(number > 0){
            sum += number % 10;
            number = Math.floor(number / 10);
        }
        return sum;
    }

    function check(row, col){
        if(row >= 0 && row < rows && col >= 0 && col < cols && getDigitSum(row) + getDigitSum(col) <= threshold && !visited[row * cols + col])
            return true;
        return false;
    }

    function movingCountCore(row, col){
        var count = 0;
        if(check(row, col)) {
            visited[row * cols + col] = true;
            count = 1 + movingCountCore(row - 1, col)
                    + movingCountCore(row, col - 1)
                    + movingCountCore(row + 1, col)
                    + movingCountCore(row, col + 1);
        }
        return count;
    }
}

完结撒花[]~( ̄▽ ̄)~*

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值