头插法
可以理解为头不变,每次插入都在头后面插入,所以头插法,输入123,输出321
头插法一般来作逆序
ListNode newNode = new ListNode(val);
while循环
newNode->next = head->next;
head->next = newNode;
尾插法
可以理解为头在变,一直向下走,所以尾插法,输入123,输出123
所以头插法插入后是顺序的
ListNode newNode = new ListNode(val);
ListNode rear = head;
while循环
newNode->next = rear->next;
rear->next = newNode;
rear = rear.next;
1.反转链表
/**
/**
* 第一种方法:迭代
* @param head
* @return
*/
public ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}
/**
* 第二种方法:递归
* @param head
* @return
*/
public ListNode reverseList(ListNode head) {
if(head == null || head.next ==null){
return head;
}
ListNode newNode = reverseList(head.next);
head.next.next = head;
head.next = null;
return newNode;
}
2.判端是否是回文字符串
解法一:
解法思路:把链表的每个数据放到栈中,然后从前向后和栈中的每一个元素比较,如果相等就是回文字符串
public static boolean isSolve(ListNode head) {
Stack<ListNode> stack = new Stack<ListNode>();
ListNode curr = head;
while(curr != null){
stack.push(curr);
curr = curr.next;
}
curr = head;
while(curr != null){
if(curr.val != stack.pop().val){
return false;
}
curr = curr.next;
}
return true;
}
解法二:
解法思路:把链表的后半部分放入栈中,然后把前半部分和栈中的每一个元素进行比较,如果相等就是回文字符串
public boolean isPalindrome(ListNode head) {
Stack<ListNode> stack = new Stack<ListNode>();
ListNode n1 = head;
ListNode n2= head;
while(n2 != null && n2.next != null){
n1 = n1.next; //mid
n2 = n2.next.next; //rihgt
}
while(n1 != null){
stack.push(n1);
n1 = n1.next;
}
while(!stack.isEmpty()){
if(head.val != stack.pop().val){
return false;
}
head = head.next;
}
return true;
}
解法三:
解法思路:快慢指针找到中点下标,然后将后一半反转,然后用两个指针,一个从前面走,一个从后面走,没有不相同就返回正确,最后将后半部分链表恢复成之前的样子
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
if(head ==null || head.next ==null){
return true;
}
ListNode n1=head;
ListNode n2=head;
// 快慢指针 n1指针走到中间 n2指针走到最后 当前链表1->2->3->2->1
//这里while里也可以写成n2.next != null && n2.next.next != null都是完美的,最好写成下面这种,不论奇数还是偶数都是满足的,可以画图自证
while(n2 != null && n2.next != null){
n1 = n1.next;
n2 = n2.next.next;
}
// 反转后半部分链表
n2 = n1.next;
n1.next = null;
//中间节点3指向空
ListNode n3 = null;
while(n2 != null){
n3 = n2.next;
n2.next = n1;
n1 = n2;
n2 = n3;
}
//保存最后位置 当前链表1->2->3<-2<-1
n3 = n1;
// n1最后位置 n2头结点位置 n1想左走 n2向右走,并比较对应的每一个值,如果不相等break
n2 = head;
boolean res = false;
while(n1 != null && n2 != null){
if(n1.val != n2.val){
res = true;
break;
}
n1 = n1.next;
n2 = n2.next;
}
if(res){
return false;
}
// 最后将链表恢复如初
n1 = n3.next;
n3.next = null;
while(n1 != null){
n2 = n1.next;
n1.next = n3;
n3 = n1;
n1 = n2;
}
//当前链表1->2->3->2->1
return true;
}
}
以上所有内容是皆来自于算法课程
B站-左程云左神的教学视频