您的位置:首页 > Web前端 > JavaScript

11天刷剑指offer——JavaScript版——第三天

2019-03-06 11:25 295 查看

文章目录

  • 14、链表中倒数第k个结点
  • 15、反转链表
  • 16、合并两个排序的链表
  • 17、树的子结构
  • 18、二叉树镜像
  • 13、调整数组顺序

    题目描述:

    输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

    思路一

    定义两个数组,array1存奇数,array2存偶数,用数组forEach的循环迭代方法,判断奇偶分别存入,这里判断奇数偶数用了按位与的方法。

    代码

    function reOrderArray(array)
    {
    var array1 = [];
    var array2 = [];
    //forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。
    //item当前元素、index当前元素的索引值、array当前元素所属的数组对象
    array.forEach(function(item,index,array){
    item & 1 ? array1.push(item):array2.push(item);
    //位与运算 判断奇偶
    //三相运算符
    });
    //concat() 方法用于连接两个或多个数组。
    return array1.concat(array2);
    }

    思路二

    通过map函数,判断每个数组元素是否为偶数

    代码

    function reOrderArray(array)
    {
    // write code here
    var arr1=[],arr2=[];
    /* map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
    map() 方法按照原始数组元素顺序依次处理元素。
    注意: map() 不会对空数组进行检测。
    注意: map() 不会改变原始数组。 */
    array.map(function(a){
    //a是当前元素
    a%2==0?arr2.push(a):arr1.push(a);
    })
    return arr1.concat(arr2);
    }

    14、链表中倒数第k个结点

    题目描述

    输入一个链表,输出该链表中倒数第k个结点

    思路一

    确定链表k前k后的长度。

    代码

    /*function ListNode(x){
    this.val = x;
    this.next = null;
    }*/
    function FindKthToTail(head, k)
    {
    if(head == null || k <= 0) return null;
    var init = head;
    var count = 0;
    while(head != null){
    head = head.next; //链表的取后一位
    count++;  //链表总长度
    }
    var rek = count - k; //k后的长度
    if(rek < 0) return null;
    for(var i = 0 ; i < rek ; i++){
    init = init.next;
    }
    return init;
    }

    思路二

    通过prev和tail来获取距离为k的一段,然后就tail指向链表最后

    代码

    function FindKthToTail(head, k)
    {
    // write code here
    if(head==null||k<=0) return null;
    var prev = head;
    var tail = head;
    
    for(var index=0;index<k-1;index++){
    if(tail.next!=null){
    tail=tail.next;
    }else{
    return null;
    }
    }
    //保持k的距离
    while(tail.next!=null){
    prev=prev.next;
    tail=tail.next;
    }
    return prev;
    }

    15、反转链表

    题目描述

    输入一个链表,反转链表后,输出链表的所有元素。

    思路

    通过prev固定反转后链表头,通过head来反转,通过next指向剩下的链表头部。

    代码

    function ReverseList(pHead)
    {
    //链表
    if(pHead == null || pHead.next == null) return pHead;
    var prev = null;
    var next = null;
    while(pHead != null){
    //存储一下头
    next = pHead.next;
    //断开连接 将最开始的头覆个空指针
    pHead.next = prev;
    //依次后移 pre pHead next
    prev = pHead;
    pHead = next;
    }
    return prev;
    }

    16、合并两个排序的链表

    题目描述

    输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

    思路一

    非递归方法,不消耗内存,两个指针分别指向链表元素,然后比较两个元素大小,小的则连到合成后链表,直到达到一个链表的末尾。然后如果哪一个链表还有元素,直接连到合成后链表后面即可。过程中head一直是那个head,但是head表示的位置却不是刚开始的head了,但是因为构造函数出来的对象是引用类型,pHead还是那个head,表示的位置也还是那个位置。(此处重在理解)
    两个指针分别指向链表元素,然后比较两个元素大小,小的则连到合成后链表,直到达到一个链表的末尾。然后如果哪一个链表还有元素,直接连到合成后链表后面即可。

    代码

    /*function ListNode(x){
    this.val = x;
    this.next = null;
    }*/
    function Merge(pHead1, pHead2)
    {
    function ListNode(x){
    this.val = x;
    this.next = null;
    }
    var head = new ListNode(0);
    var pHead = head;
    while(pHead1 != null && pHead2 != null){
    if(pHead1.val >= pHead2.val){
    head.next = pHead2;
    pHead2 = pHead2.next;
    }else{
    head.next = pHead1;
    pHead1 = pHead1.next;
    }
    head = head.next;
    }
    if(pHead1 != null){
    head.next = pHead1;
    }
    if(pHead2 != null){
    head.next = pHead2;
    }
    return pHead.next;
    }

    思路二

    递归方法,消耗内存,使用自身进行比较合并。比思路1好理解有没有!

    代码

    function Merge(pHead1, pHead2)
    {
    if(pHead1 == null) return pHead2;
    if(pHead2 == null) return pHead1;
    var node = null;
    if(pHead1.val > pHead2.val){
    node = pHead2;
    node.next = Merge(pHead1,pHead2.next);
    }else{
    node = pHead1;
    node.next = Merge(pHead1.next,pHead2);
    }
    return node;
    }

    17、树的子结构

    题目描述

    输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

    思路

    比较B是不是A的子树,B是不是A的右子树的子树,B是不是A的左子树的子树。如果根元素相同,则开始判断左子树和右子树。

    代码

    /* function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
    } */
    function isSubtree(pRoot1,pRoot2){
    if(pRoot2 == null) return true;  //pRoot2为null,表示子树已经遍历完
    if(pRoot1 == null) return false;
    if(pRoot1.val == pRoot2.val){
    return isSubtree(pRoot1.left,pRoot2.left) && isSubtree(pRoot1.right,pRoot2.right)
    }else{
    return false;
    }
    }
    function HasSubtree(pRoot1, pRoot2)
    {
    if(pRoot1 == null || pRoot2 == null){
    return false;
    }
    return isSubtree(pRoot1,pRoot2) || HasSubtree(pRoot1.left, pRoot2) || HasSubtree(pRoot1.right, pRoot2);
    }

    18、二叉树镜像

    题目描述

    操作给定的二叉树,将其变换为源二叉树的镜像。

    思路

    先将根的左右节点互换,然后就是递归调用,对左右子树进行分别处理

    代码

    /* function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
    } */
    function Mirror(root)
    {
    // write code here
    if(root==null) return null;
    //首先先将左右节点互换
    var  tmp = root.left;
    root.left=root.right;
    root.right=tmp;
    //递归
    Mirror(root.left);
    Mirror(root.right);
    
    }
    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: