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

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);

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值