• 算法通关村第二关|白银|链表反转拓展【持续更新】


    1.指定区间反转

    1.1 头插法:将区间内遍历到的结点插入到起始处之前。

    public ListNode reverseBetween(ListNode head, int left, int right) {
    	ListNode dummyNode = new ListNode(-1);
        dummyNode.next = head;
        ListNode pre = dummyNode;
        // 将pre移动到区间的前一位,pre.next指向每次遍历到的需要插入到起始处的结点
        for (int i = 0; i < left - 1; i++) {
            pre = pre.next;
        }
        // cur负责遍历
        ListNode cur = pre.next;
        // next存储遍历到的结点
        ListNode next;
        for (int i = 0; i < right - left; i++) {
            //存储遍历到的结点cur.next
            next = cur.next;
            //将cur.next向后移动,下次循环继续遍历
            cur.next = next.next;
            //让遍历到的结点指向起始处的结点
            next.next = pre.next;
            //pre指向新的起始处
            pre.next = next;
        }
        return dummyNode.next;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    1.2 穿针引线法:找到需要裁切的地方,将子链表整体反转,然后再缝到切开的地方。

    public ListNode reverseBetween(ListNode head, int left, int right){
    	ListNode dummyNode = new ListNode(-1);
        dummyNode.next = head;
        ListNode pre = dummyNode;
        // 找 left 结点的前一个结点
        for (int i = 0; i < left - 1; i++) {
            pre = pre.next;
        }
        // 找 right 结点
        ListNode rightNode = pre;
        for (int i = 0; i < right - left + 1; i++) {
            rightNode = rightNode.next;
        }
        // 切割子链表
    	ListNode leftNode = pre.next;
        ListNode succ = rightNode.next;
        rightNode.next = null;
        // 反转链表
        reverseList(leftNode);
        // 拼接
        pre.next = rightNode;
        leftNode.next = succ;
        return dummyNode.next;
    }
    // 反转链表算法
    public ListNode reverseList(ListNode head) {
            ListNode prev = null;
            ListNode curr = head;
            while(curr != null){
                ListNode next = curr.next;
                
                // 这里对链表的结构进行了更改
                // 所以不需要返回值,但是上面的leftNode结构已经更改了
                curr.next = prev;
                
                prev = curr;
                curr = next;
            }
            return prev;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    2.两两交换链表中的节点

    捋清楚成对交换结点时的指针指向即可。

    public ListNode swapPairs(ListNode head) {
    	ListNode dummyHead = new ListNode(0);
    	dummyHead.next = head;
    	ListNode temp = dummyHead;
    	while (temp.next != null && temp.next.next != null) {
            ListNode node1 = temp.next;
            ListNode node2 = temp.next.next;
            temp.next = node2;
            node1.next = node2.next;
            node2.next = node1;
            temp = node1;
        }
    	return dummyHead.next;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3.单链表加1

    3.1 基于栈实现。

    public ListNode plusOne(ListNode head) {
    	Stack<Integer> stack = new Stack();
    	while (head != null) {
            stack.push(head.val);
            head = head.next;
        }
    	int carry = 0;
    	ListNode dummy = new ListNode(0);
    	// 本题要加1,所以设置了adder为1
    	int adder = 1;
    	while (!stack.empty() || carry > 0) {
            int digit = stack.empty() ? 0 : stack.pop();
            int sum = digit + carry + adder;
            carry = sum / 10;
            sum = sum % 10;
            ListNode cur = new ListNode(sum);
            cur.next = dummy.next;
            dummy.next = cur;
            //加一次以后adder就可以置0了
            adder = 0;
        }
    	return dummy.next;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    3.2 链表反转实现。【持续更新】

    
    
    • 1

    4.链表加法

    4.1 栈实现:栈顶都是两个数的最低位,所以可以一起弹出。

    public ListNode addInListByStack(ListNode head1, listNode head2) {
    	Stack<ListNode> stack1 = new Stack<>();
        Stack<ListNode> stack2 = new Stack<>();
        while (head1 != null) {
            stack1.push(head1);
            head1 = head1.next;
        }
        while (head2 != null) {
            stack2.push(head2);
            head2 = head2.next;
        }
        ListNode newHead = new ListNode(-1);
        int carry = 0;
        while (!stack1.empty() || !stack2.empty() || carry != 0) {
            ListNode a = new ListNode(0);
            ListNode b = new ListNode(0);
            if (!stack1.empty()) {
                a = stack1.pop();
            }
            if (!stack2.empty()) {
                b = stack2.pop();
            }
            int get_sum = a.val + b.val + carry;
            int ans = get_sum % 10;
            carry = get_sum / 10;
            ListNode cur = new ListNode(ans);
            cur.next = newHead.next;
            newHead.next = cur;
        }
        return newHead.next;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    4.2 链表反转实现。

    public class Solution {
        public ListNode addInList(ListNode head1, ListNode head2) {
            head1 = reverse(head1);
            head2 = reverse(head2);
            ListNode head = new ListNode(-1);
            ListNode cur = head;
            int carry = 0;
            while (head1 != null || head2 != null || carry != 0) {
                int sum = carry;
                if (head1 != null) {
                    sum += head1.val;
                    head1 = head1.next;
                }
                if (head2 != null) {
                    sum != head2.val;
                    head2 = head2.next;
                }
                cur.next = new ListNode(sum % 10);
                carry = sum / 10;
                cur = cur.next;
            }
            return reverse(head.next);
        }
    
        // 链表反转方法
        public ListNode reverse(ListNode head){
            ListNode cur = head;
            ListNode pre = null;
            while (cur != null) {
                ListNode temp = cur.next;
                cur.next = pre;
                pre = cur;
                cur = temp;
            }
            return pre;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    4.3 链表减法:【持续更新】。

    
    
    • 1

    5.再论链表的回文序列问题

    书接上回,可以使用栈或者链表反转来做。

    public boolean isPalindrome(ListNode head) {
    	if (head == null || head.next == null) {
            return true;
    	}
    	ListNode slow = head, fast = head;
    	ListNode pre = head, prepre = null;
    	while (fast != null && fast.next != null) {
            pre = slow;
            slow = slow.next;
            fast = fast.next.next;
            pre.next = prepre;
            prepre = pre;
        }
    	if (fast != null) {
        	slow = slow.next;
        }
    	while (pre != null && slow != null) {
            if (pre.val != slow.val) {
                return false;
            }
            pre = pre.next;
            slow = slow.next;
        }
    	return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    如果对您有帮助,请点赞关注支持我,谢谢!❤
    如有错误或者不足之处,敬请指正!❤

  • 相关阅读:
    EasyLazyload系列之实现图片懒加载
    淘宝app商品详情源数据API接口(解决滑块问题)可高并发采集
    【SpringCloud】Ribbon负载均衡原理、负载均衡策略、饥饿加载
    SpringMVC(一)
    规范预算编制,打造企业全面预算管理新章程
    Vue项目中使用element-plus UI库-并对下拉搜索框样式修改-el-select代码封装
    蔚来杯_2022牛客暑期多校训练营(加赛) E.Everyone is bot
    《QT实用小工具·三十二》九宫格炫酷主界面
    数据结构题型17-树、森林
    STM32H723加上ThreadX,时钟不准确
  • 原文地址:https://blog.csdn.net/m0_57130776/article/details/133936753