数据结构专题——反转链表问题(java实现)
问题:给定一个单链表的头结点,反转该链表后,返回新链表的表头
首先依旧是链表的定义:(leetcode方式)
class ListNode {
int val;
ListNode next;
public ListNode(int val) {
this.val = val;
next = null;
}
}
方法一:使用栈(不推荐,需要额外开辟O(n)的空间)
public static ListNode reverseLinkedListByStack(ListNode head) {
if (head == null || head.next == null) {
return head;
}
//创建栈将结点并将链表结点从头到尾入栈
Stack<ListNode> stack = new Stack<>();
while (head != null) {
stack.push(head);
head = head.next;
}
//拿出栈中第一个结点作为新链表的表头
if(!stack.isEmpty())
head = stack.pop();
ListNode cur = head;
//依次拿出结点以尾插的方式接入表头
while (!stack.empty()) {
ListNode Node = stack.pop();
Node.next = null;
cur.next = Node;
cur = Node;
}
return head;
}
方法二:使用一个临时结点以头插法的方式进行连接新链表(最简单也最好理解)
public static ListNode reverseLinkedListByNode(ListNode head) {
if (head == null || head.next == null) {
return head;
}
//创建一个辅助结点
ListNode Node = new ListNode(0);
//从原来链表上一个一个拿用头插法的方式接到这个辅助结点上
ListNode cur = head;
while(cur != null) {
ListNode temp = cur.next;
cur.next = Node.next;
Node.next = cur;
cur = temp;
}
//返回辅助结点的next结点就是反转后的表头
return Node.next;
}
方法三:使用双指针的方式进行(不需要额外开辟内存,推荐)
public static ListNode reverseLinkedListNoByNode(ListNode head) {
if (head == null || head.next == null) {
return head;
}
//使用双指针的方式,两个指针往前走,依次进行改变指针指向向前
ListNode pre = null;
ListNode cur = head;
while (cur != null) {
//这里需要一个临时指针,要不cur往前指的时候就找不到后面了
ListNode temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
//返回辅助结点的next结点就是反转后的表头
return cur;
}
方法四:递归(不好理解,本人理解的不是很好,这里没写注释,就不影响读者思路了)
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;
}
测试方法(注:该测试方法需要分开测试)
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5};
ListNode list = initList(arr);
System.out.println(printList(list));
ListNode newList = null;
//第一种方法反转链表
newList = reverseLinkedListByNode(list);
System.out.println(printList(newList));
//第二种方法反转链表
// newList = reverseLinkedListNoByNode(list);
// System.out.println(printList(newList));
//第三种方法反转链表
// newList = reverseLinkedListByStack(list);
// System.out.println(printList(newList));
//第四种方法反转链表
// newList = reverseLinkedListByRecursive(list);
// System.out.println(printList(newList));
}
初始化链表的方法
/**
* 初始化链表
* @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();
}