算法奇妙屋(五)-链表

一. 力扣 2. 两数相加

1. 题目

2. 算法原理

3. 代码

java 复制代码
    public ListNode addTwoNumbers(ListNode cur1, ListNode cur2) {
        ListNode newHead = new ListNode();
        ListNode tail = newHead;
        int tmp = 0;
        while (cur1 != null && cur2 != null) {
            tmp += (cur1.val + cur2.val);
            ListNode node = new ListNode(tmp % 10);
            tmp /= 10;
            tail.next = node;
            tail = node;
            cur1 = cur1.next;
            cur2 = cur2.next;
        }
        while (cur1 != null) {
            tmp += cur1.val;
            ListNode node = new ListNode(tmp % 10);
            tmp /= 10;
            tail.next = node;
            tail = node;
            cur1 = cur1.next;
        }
        while (cur2 != null) {
            tmp += cur2.val;
            ListNode node = new ListNode(tmp % 10);
            tmp /= 10;
            tail.next = node;
            tail = node;
            cur2 = cur2.next;
        }
        if ((tmp % 10) != 0) {
            ListNode node = new ListNode(tmp % 10);
            tail.next = node;
        }
        return newHead.next;
    }

二. 力扣 24. 两两交换链表中的节点

1. 题目

2. 算法原理

3. 代码

java 复制代码
    public ListNode swapPairs(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode newHead = new ListNode();
        ListNode prev = newHead;
        ListNode cur = head;
        ListNode next = cur.next;
        ListNode nnext = next.next;
        while (cur != null && cur.next != null) {
            prev.next = next;
            next.next = cur;
            cur.next = nnext;
            if (nnext == null || nnext.next == null) {
                break;
            }
            prev = cur;
            cur = nnext;
            next = nnext.next;
            nnext = next.next;
        }
        return newHead.next;
    }

三. 力扣 143. 重排链表

1. 题目

2. 算法原理

3. 代码

(1) 方法一:从中间点prev处开始逆序

java 复制代码
    public void reorderList(ListNode head) {
        if (head == null || head.next == null || head.next.next == null) {
            return;
        }
        ListNode prev = head;
        ListNode cur = head;
        // 寻找中间节点 prev
        while (cur != null && cur.next != null) {
            cur = cur.next.next;
            prev = prev.next;
        }
        // 逆序头插法
        ListNode mid = prev;
        cur = prev;
        prev = null;
        while (cur != null) {
            ListNode curN = cur.next;
            cur.next = prev;
            prev = cur;
            cur = curN;
        }
        // 交替合并
        // 逆序后的 头结点是 prev
        ListNode cur1 = head;
        ListNode cur2 = prev;
        cur = new ListNode();
        while (cur1 != mid && cur2 != null) {
            cur.next = cur1;
            cur = cur.next;
            cur1 = cur1.next;
            cur.next = cur2;
            cur = cur.next;
            cur2 = cur2.next;
        }
    }

(2) 方法二:从中间点next处开始逆序

java 复制代码
    public void reorderList(ListNode head) {
        if (head == null || head.next == null || head.next.next == null) {
            return;
        }
        ListNode prev = head;
        ListNode cur = head;
        // 寻找中间节点 prev
        while (cur != null && cur.next != null) {
            cur = cur.next.next;
            prev = prev.next;
        }
        // 逆序头插法
        cur = prev.next;
        prev.next = null;
        prev = null;
        while (cur != null) {
            ListNode curN = cur.next;
            cur.next = prev;
            prev = cur;
            cur = curN;
        }
        // 交替合并
        // 逆序后的 头结点是 prev
        ListNode cur1 = head;
        ListNode cur2 = prev;
        cur = new ListNode();
        while (cur1 != null) {
            cur.next = cur1;
            cur = cur.next;
            cur1 = cur1.next;
            if (cur2 != null) {
                cur.next = cur2;
                cur = cur.next;
                cur2 = cur2.next;
            }
        }
    }

四. 力扣 23. 合并 K 个升序链表

1. 题目

这道题目就是把多个有序链表连接成一个, 这里不过多赘述题意, 直接上算法原理

2. 算法原理

(1) 算法一:堆排序求解

这里可以用优先级队列, 通过建立小根堆的方法来进行链接

(2) 算法二:递归分治解法

该解法与归并排序分治的解法思路类似,只是把对两个数组合并的过程变成了两个链表合并

3. 代码

(1) 方法一代码

java 复制代码
    // 堆排序做法
    public ListNode mergeKLists(ListNode[] lists) {
        ListNode newHead = new ListNode();
        ListNode cur = newHead;
        PriorityQueue<ListNode> priorityQueue = new PriorityQueue<>((v1,v2) -> v1.val - v2.val);
        for(ListNode head : lists) {
            if (head != null) {
                priorityQueue.offer(head);
            }
        }
        // 取出头结点, 并合并
        while (!priorityQueue.isEmpty()) {
            cur.next = priorityQueue.poll();
            cur = cur.next;
            if (cur.next != null) {
                priorityQueue.offer(cur.next);
            }
        }
        return newHead.next;
    }

(2) 方法二代码

java 复制代码
    public ListNode mergeKLists(ListNode[] lists) {
        int n = lists.length;
        if (n == 0) {
            return null;
        }
        return merge(lists, 0, n - 1);
    }
    public ListNode merge(ListNode[] lists, int s, int e) {
        if (s >= e) {
            return lists[s];
        }
        int mid = (s + e) / 2;
        // 左面合并
        ListNode left = merge(lists,s,mid);
        // 右面合并
        ListNode right = merge(lists,mid + 1, e);
        // 合并两个有序链表
        return sort(left,right);
    }
    public ListNode sort(ListNode cur1, ListNode cur2) {
        ListNode newHead = new ListNode();
        ListNode cur = newHead;
        while (cur1 != null && cur2 != null) {
            if (cur1.val <= cur2.val) {
                cur.next = cur1;
                cur1 = cur1.next;
            }else {
                cur.next = cur2;
                cur2 = cur2.next;
            }
            cur = cur.next;
        }
        if (cur1 != null) {
            cur.next = cur1;
        }
        if (cur2 != null) {
            cur.next = cur2;
        }
        return newHead.next;
    }

五. 力扣 25. K 个一组翻转链表

1. 题目

题目意思是每k个节点进行逆序,不满足k个节点的不逆序

2. 算法原理

3. 代码

java 复制代码
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode cur = head;
        int n = 0;
        while (cur != null) {
            n++;
            cur = cur.next;
        }
        n = n / k;
        cur = head;
        ListNode newHead = new ListNode();
        ListNode prev = newHead;
        for (int i = 0; i < n; i++) {
            ListNode tmp = cur;
            for (int j = 0; j < k; j++) {
                ListNode next =  cur.next;
                cur.next = prev.next;
                prev.next = cur;
                cur = next;
            }
            prev = tmp;
        }
        prev.next = cur;
        return newHead.next;
    }
相关推荐
chaser&upper几秒前
矩阵革命:在 AtomGit 解码 CANN ops-nn 如何构建 AIGC 的“线性基石”
程序人生·算法
weixin_499771559 分钟前
C++中的组合模式
开发语言·c++·算法
iAkuya40 分钟前
(leetcode)力扣100 62N皇后问题 (普通回溯(使用set存储),位运算回溯)
算法·leetcode·职场和发展
近津薪荼40 分钟前
dfs专题5——(二叉搜索树中第 K 小的元素)
c++·学习·算法·深度优先
xiaoye-duck42 分钟前
吃透 C++ STL list:从基础使用到特性对比,解锁链表容器高效用法
c++·算法·stl
松☆1 小时前
CANN与大模型推理:在边缘端高效运行7B参数语言模型的实践指南
人工智能·算法·语言模型
java干货1 小时前
为什么 “File 10“ 排在 “File 2“ 前面?解决文件名排序的终极算法:自然排序
开发语言·python·算法
皮皮哎哟1 小时前
数据结构:嵌入式常用排序与查找算法精讲
数据结构·算法·排序算法·二分查找·快速排序
程序员清洒1 小时前
CANN模型剪枝:从敏感度感知到硬件稀疏加速的全链路压缩实战
算法·机器学习·剪枝
vortex51 小时前
几种 dump hash 方式对比分析
算法·哈希算法