Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

重启数据结构与算法2 #7

Open
Ray-56 opened this issue Jun 5, 2020 · 0 comments
Open

重启数据结构与算法2 #7

Ray-56 opened this issue Jun 5, 2020 · 0 comments

Comments

@Ray-56
Copy link
Owner

Ray-56 commented Jun 5, 2020

重启数据结构与算法2

重启数据结构与算法,一些代码案例使用 Deno 与 TypeScript 实现,相关代码都在这里

  1. 重启数据结构与算法1
  2. 重启数据结构与算法2

单向链表的五个面试题

这几个题,就直接在HeroNode类中写了,查看上篇重启数据结构与算法1

1.求单链表中的有效的节点个数

class SingleLinkedList {
    ...
    /** 获取当前单链表 */
    public getHead() {
        return this.head;
    }
    /** 有效节点数 */
    public static getSize(head: HeroNode): number {
        let size = 0;
        let cur = head;
        while (cur.next) {
            size++;
            cur = cur.next;
        }
        return size;
    }
}

定义了getSize(head)静态方法,参数为要获取有效节点的单链表
再定义getHead()方法,获取当前的链表

下面我们验证一下

// 提前已将节点加入进去了
// 验证获取有效节点数量
const size = SingleLinkedList.getSize(singleLinkedList.getHead());
console.log(`有效节点数量为:${size}`);
// 有效节点数量为:4

2.查找单链表倒数第k个节点

...
/** 查找倒数第k个节点 */
public static findLastIndexNode(head: HeroNode, index: number) {
    const size = this.getSize(head);
    // if (index <=0 || index > size) return null;
    let ret  = head;
    for (let i = 0; i < size - index; i++) {
        ret = ret.next as HeroNode;
    }
    return ret;
}
...

window.onload = function main() {
    ...
    // 验证查找倒数第k个节点
    const lastNode = SingleLinkedList.findLastIndexNode(singleLinkedList.getHead(), 2);
    console.log(`倒数第3个节点为:`);
    lastNode.show();
    // 倒数第3个节点为:
    // no = 2; name = 卢俊义; nickName = 玉麒麟
}

添加findLastIndexNode方法后进行了验证,也没有问题

3.单链表反转

反转要比前面有点难度了,前面只需要遍历次数就可以,现在要考虑数据结构的转变方向了

...
    /** 反转 */
    public static reverseList(head: HeroNode) {
        // 思路1 保存上一个,使得当前的下一个是上一个,pre 即为反转后的链表
        // let cur: HeroNode | null = head;
        // let pre = null;
        // while (cur !== null) {
        //     const next: HeroNode | null = cur.next;
        //     cur.next = pre;
        //     pre = cur;
        //     cur = next;
        // }
        // return pre;

        // 思路2 新建链表,遍历旧的使得每一个都放在新链表下的第一位
        const reverseHead = new HeroNode(0, '', '');
        let cur: HeroNode | null = head;
        while (cur !== null) {

            const next: HeroNode | null = cur.next; // 保存 next

            // 保证当前的一直在 reverseHead.next
            cur.next = reverseHead.next;
            reverseHead.next = cur;

            cur = next;
        }
        head.next = reverseHead.next;
    }
...

window.onload = function main() {
    ...
    // 验证反转
    const head = singleLinkedList.getHead();
    SingleLinkedList.reverseList(head);
    console.log(head); // 输出得知已被反转
}

4.从尾到头打印链表

  • 可以是考虑反转后再打印,这样要考虑当前链表是否需要被反转,否则转过来再转过去损耗性能
  • 使用栈stack先进后出的特性
...
    /** 从尾到头打印链表 */
    public static reversePrint(head: HeroNode) {
        const stack = [];
        let cur = head;
        while (cur.next) {
            cur = cur.next;
            stack.push(cur);
        }

        while (stack.length) {
            stack.pop()?.show();
        }
    }
...

window.onload = function main() {
    ...
    // 验证从尾到头打印
    const head = singleLinkedList.getHead();
    SingleLinkedList.reversePrint(head);
}

5.合并有序单链表,合并后依然有序

...
    /** 合并有序单链表,合并后依然有序 */
    public static merge(l1: HeroNode | null, l2: HeroNode | null): HeroNode {
        let cur = new HeroNode(0, '', '');
        const ret = cur;

        while (l1 !== null && l2 !== null) {
            if (l1.no < l2.no) {
                cur.next = l1;
                l1 = l1.next;
            } else {
                cur.next = l2;
                l2 = l2.next;
            }
            cur = cur.next;
        }
        if (l1 !== null) {
            cur.next = l1;
        }
        if (l2 !== null) {
            cur.next = l2
        }

        return ret.next as HeroNode;
    }
...

window.onload = function main() {
    ...
    // 验证合并有序单链表,合并后依然有序
    const singleLinkedList1 = new SingleLinkedList();
    const singleLinkedList2 = new SingleLinkedList();
    singleLinkedList1.add(hero1);
    singleLinkedList1.add(hero3);
    singleLinkedList2.add(hero2);
    singleLinkedList2.add(hero4);
    console.log('链表1:');
    singleLinkedList1.show();
    console.log('链表2:');
    singleLinkedList2.show();

    const merged = SingleLinkedList.merge(singleLinkedList1.getHead().next, singleLinkedList2.getHead().next);
    console.log('合并后的有序:');
    console.log(merged); // 验证后依然有序
}

下期预告

双向链表、环形链表以及约瑟夫问题

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant