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

1.指定区间反转

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

java 复制代码
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 穿针引线法:找到需要裁切的地方,将子链表整体反转,然后再缝到切开的地方。

java 复制代码
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;
    }
}

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

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

java 复制代码
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;
}

3.单链表加1

3.1 基于栈实现。

java 复制代码
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;
}

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

java 复制代码

4.链表加法

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

java 复制代码
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;
}

4.2 链表反转实现。

java 复制代码
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;
    }
}

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

java 复制代码

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

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

java 复制代码
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;
}

如果对您有帮助,请点赞关注支持我,谢谢!❤

如有错误或者不足之处,敬请指正!❤

相关推荐
特立独行的猫a4 分钟前
11款常用C++在线编译与运行平台推荐与对比
java·开发语言·c++
louisgeek14 分钟前
Java 位运算
java
绝无仅有42 分钟前
企微审批对接错误与解决方案
后端·算法·架构
hweiyu001 小时前
Maven 私库
java·maven
Super Rookie1 小时前
Spring Boot 企业项目技术选型
java·spring boot·后端
写不出来就跑路1 小时前
Spring Security架构与实战全解析
java·spring·架构
用户5040827858392 小时前
1. RAG 权威指南:从本地实现到生产级优化的全面实践
算法
ZeroNews内网穿透2 小时前
服装零售企业跨区域运营难题破解方案
java·大数据·运维·服务器·数据库·tcp/ip·零售
sleepcattt2 小时前
Spring中Bean的实例化(xml)
xml·java·spring