算法打卡:第5周

问题一

汉诺塔问题: https://leetcode-cn.com/problems/hanota-lcci/

思路:汉诺塔问题,使用递归解决,主要三个步骤:
(1)、将A上n - 1个盘子移动到B上,借助C
(2)、将A第n个盘子移动到C上
(3)、将B上的n - 1个盘子移动到C上,借助A

public void hanota(List<Integer> A, List<Integer> B, List<Integer> C) {
    move(A.size(), A, B, C);
}

public void move(int n, List<Integer> A, List<Integer> B, List<Integer> C) {
    // 如果只有一个盘子,则直接移动到C
    if (n == 1) {
        C.add(A.remove(A.size() - 1));
        return;
    } else {
        // 将A上 1 至 n - 1的盘子移动到B,以C为辅助
        move(n - 1, A, C, B);
        //将A上的n号盘子移动到C
        C.add(A.remove(A.size() - 1));
        // 将B上的盘子移到C,以A为辅助
        move(n - 1, B, A, C);
    }
}

问题二

排序链表:https://leetcode-cn.com/problems/sort-list/

思路:难点在于节点的指针变动,首先想到了将所有节点都放入list中,然后利用Collections进行排序后,再依次生成新的排序后的链表,但是时间复杂度较高。第二种思路是使用归并排序,归并排序是链表排序的一种有效方法,简单的讲,就是将要排序的链表一分为二之后再递归的一分为二,最后将排好序的链表再进行二合一,最终合成一个排序好的链表。

思路一:使用常规方法

public ListNode sortList(ListNode head) {
    List<ListNode> list = new ArrayList<>();
    while (head != null) {
        list.add(head);
        head = head.next;
    }
    Collections.sort(list, Comparator.comparingInt(o -> o.val));
    ListNode resultNode = null, lastNode = null;
    for (ListNode node : list) {
        node.next = null;
        if (lastNode == null) {
            resultNode = node;
        } else {
            lastNode.next = node;
        }
        lastNode = node;
    }
    return resultNode;
}

思路二:使用归并排序

public ListNode sortList(ListNode head) {
    return mergeSort(head);
}

// 归并排序
public ListNode mergeSort(ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }
    ListNode slow = head, fast = head.next.next;
    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;
    }
    ListNode right = mergeSort(slow.next);
    // 断开连接
    slow.next = null;
    ListNode left = mergeSort(head);
    return mergeList(left, right);
}

// 合并list
public ListNode mergeList(ListNode left, ListNode right) {
    ListNode tmpHead = new ListNode(), currentHead = tmpHead;
    while (left != null && right != null) {
        if (left.val <= right.val) {
            currentHead.next = left;
            currentHead = left;
            left = left.next;
        } else {
            currentHead.next = right;
            currentHead = right;
            right = right.next;
        }
    }
    if (left != null) {
        currentHead.next = left;
    }
    if (right != null) {
        currentHead.next = right;
    }
    return tmpHead.next;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值