数据结构专题——指定区间反转链表(java实现)

数据结构专题——指定区间反转链表(java)
首先依旧是链表的定义:(leetcode方式)
class ListNode {
    int val;
    ListNode next;

    public ListNode(int val) {
        this.val = val;
        next = null;
    }
}
方法一(推荐):头插法:拿到反转区间的前一个结点,进行一个个头插
public static ListNode reverseByHeadInsert(ListNode list, int n, int m) {

    if(list == null || list.next == null) {
        return list;
    }
    // 这里准备一个临时结点,准备让其充当反转区间的"头"
    ListNode pre = new ListNode(-1);
    pre.next = list;
    for (int i = 0; i < n-1; i++) {
        pre = pre.next;
    }
    //从cur开始反转,长度为m-n
    ListNode cur = pre.next;
    for (int j = 0; j < m-n; j++) {
        ListNode temp = cur.next;
        cur.next = temp.next;
        temp.next = pre.next;
        pre.next = temp;
    }
    return list;
}
方法二:穿针引线法:将链表要反转的区间单独切割出来,再"缝合"回去
public static ListNode reverseByCut(ListNode list, int n, int m) {
		if(list == null || list.next == null) {
			return list;
		}
		ListNode pre = new ListNode(-1);
		pre.next = list;
		//找到反转区间的前一个结点
		for (int i = 0; i < n-1; i++) {
			pre = pre.next;
		}
		ListNode leftNode = pre.next;
		ListNode rightNode = pre;
		//找到反转区间的最后一个结点
		for (int i = 0; i < m-n+1; i++) {
			rightNode = rightNode.next;
		}
		ListNode behind = rightNode.next;
		//这里一定要把切割出来的链表末节点跟原来链表完全断开,否则反转时会带着后面一起反转了
		rightNode.next = null;
		//这里回归到了最原始的反转链表问题,参考上一篇博客,这里用一下递归方法。
		ListNode newList = reverseLinkedListByRecursive(leftNode);
		pre.next = newList;
		// 原来的区间头变成了区间尾
		leftNode.next = behind;
		return list;
	}
/**
* 递归反转链表的方法
*/
public static ListNode reverseLinkedListByRecursive(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode newHead = reverseLinkedListByRecursive(head.next);
        head.next.next = head;
        head.next = null;
        return newHead;
    }
初始化链表的方法
	/**
	 *  初始化链表
	 * 	@return 链表头结点
	 */   
public static ListNode initList(int[] array) {
        ListNode node = new ListNode(0);
        ListNode head = node;
        for(int i = 0; i < array.length; i++) {
            ListNode temp = new ListNode(array[i]);
            node.next = temp;
            node = node.next;
        }
        return head.next;
    }
打印链表的方法
	/**
	 * 打印链表
	 * @param head
	 * @return 链表所有元素组成的字符串
	 */
public static String printList(ListNode head) {

    if(head == null) {
        return "";
    }

    ListNode cur = head;
    StringBuilder sb = new StringBuilder();
    while(cur != null) {
        sb.append(cur.val).append("->");
        cur = cur.next;
    }
    sb.append("null");
    return sb.toString();
}
测试方法
	public static void main(String[] args) {
		
        int[] arr = new int[]{1,2,3,4,5,6,7,8}; 
        ListNode list = initList(arr);
        System.out.println(printList(list));
        ListNode newList = null;
        //newList = reverseByHeadInsert(list, 3, 5);
        newList = reverseByCut(list, 2, 7);
        System.out.println(printList(newList));
		
	}
其中一个结果:

在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值