1、输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
//方法一
public static int[] reversePrint(ListNode head) {
int k=0;
int nodeCount=0;
ListNode temp=head;
if(temp==null){
return new int[0];
}
//1、计算链表长度用于定义数组
while(temp!=null){
nodeCount++;
temp=temp.next;
}
int[] array=new int[nodeCount];
temp=head;
//2、将链表元素全部放入数组
while(temp!=null){
array[k]=temp.val;
temp=temp.next;
k=k+1;
}
int cur=0;
//3、反转数组
for(int i=0;i<=nodeCount/2-1;i++){
cur=array[i];
array[i]=array[nodeCount-1-i];
array[nodeCount-1-i]=cur;
}
return array;
}
//2、递归加回溯(关键代码)
ArrayList<Integer> tmp = new ArrayList<Integer>();
public void recur(ListNode head) {//调用后tmp存储链表的倒叙
if(head == null) return;//为递归终止条件
recur(head.next);//递归
tmp.add(head.val);//层层回溯时,将当前节点值加入列表
}
2、给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
//双指针解决
1、特例处理: 当应删除头节点 head 时,直接返回 head.next 即可。
2、初始化: pre = head , cur = head.next 。
3、定位节点: 当 cur 为空 或 cur 节点值等于 val 时跳出。
保存当前节点索引,即 pre = cur 。
遍历下一节点,即 cur = cur.next 。
4、删除节点: 若 cur 指向某节点即不为空,则执行 pre.next = cur.next 。
若 cur 指向 null,代表链表中不包含值为 val 的节点。
5、返回值: 返回链表头部节点 head 即可。
public static ListNode deleteNode(ListNode head, int val) {
if(head.val == val) return head.next;
ListNode pre = head, cur = head.next;
while(cur != null && cur.val != val) {
pre = cur;
cur = cur.next;
}
if(cur != null) pre.next = cur.next;
return head;
}
3、删除链表的倒数第k个节点
第一时间想到的解法:
1、先遍历统计链表长度,记为 n ;
2、 设置一个指针走 (n-k) 步,即可找到链表倒数第k个节点。/
//双指针
/
1、初始化: 前指针 former 、后指针 latter ,双指针都指向头节点 head 。
2、构建双指针距离: 前指针 former 先向前走 k步(结束后,双指针 former 和 latter 间相距 k步)。
3、双指针共同移动: 循环中,双指针 former 和 latter 每轮都向前走一步,直至 former 走过链表 尾节点 时跳出
(跳出后, latter 与尾节点距离为 k-1,即 latter 指向倒数第 k个节点)。
4、返回值: 返回 latter 即可。
public static ListNode getKthFromEnd(ListNode head, int k){
ListNode former=head,latter=head;
for(int i=0;i<k;i++){
former=former.next;
}
while (former!=null){
former=former.next;
latter=latter.next;
}
return latter;
}
4、输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
快慢指针解法
1、申请节点,pre和 cur,pre指向null,cur指向head
2、定义辅助节点temp,用于记录cur的下一个节点
3、只要cur不为空
1、记录当前节点的下一个节点
2、然后将当前节点指向pre
3、pre和cur节点都前进一位
4、返回pre
public ListNode reverseList(ListNode head) {
ListNode cur=head;
ListNode pre=null;
ListNode temp=null;
while(cur!=null){
temp=cur.next;
cur.next=pre;
pre=cur;
cur=temp;
}
return pre;
}
5、合并两个有序的链表
1、定义一个新节点newNode
2、初始化一个伪头节点l3,节点l3指向newNode。
3、只要l1没到头并且l2也没到头
if(temp1.val<=temp2.val)
newNode.next=temp1;
temp1=temp1.next;
else:
newNode.next=temp2;
temp2=temp2.next;
4、if(temp2!=null)
newNode.next=temp2;
5、if(temp1!=null)
newNode.next=temp1;
6、return l3.next;
public static ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode temp1=l1;
ListNode temp2=l2;
ListNode newNode = new ListNode(0);
ListNode l3=newNode;
while(temp1!=null&&temp2!=null){
if(temp1.val<=temp2.val){
newNode.next=temp1;
temp1=temp1.next;
}else{
newNode.next=temp2;
temp2=temp2.next;
}
newNode=newNode.next;
}
if(temp2!=null){
newNode.next=temp2;
}
if(temp1!=null){
newNode.next=temp1;
}
return l3.next;
}
6、输入两个链表,找出它们的第一个公共节点。
双链指针同时移动,确保同时到链表尾
1、获取两个链表长度lengthA,lengthB;
2、定义两个辅助指针tempA和tempB分别指向headA和headB
3、首先让长的链表先走|lengthA-lengthB|步
4、然后二者同时走判断tempA.val==tempB.val,成立就返回
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int lengthA = getlength(headA), lengthB = getlength(headB);
ListNode tempA = headA;
ListNode tempB = headB;
if (lengthA > lengthB) {
for (int i = 0; i < lengthA - lengthB; i++) {
tempA = tempA.next;
}
} else {
for (int i = 0; i < lengthB - lengthA; i++) {
tempA = tempA.next;
}
}
while (tempA.val == tempB.val) {
tempA = tempA.next;
tempB = tempB.next;
}
return tempA;
}
private int getlength(ListNode head) {
int count = 0;
ListNode temp = head;
while (head != null) {
count++;
temp = temp.next;
}
return count;
}
7、实现一种算法,删除单向链表中间的某个节点(即不是第一个或最后一个节点),假定你只能访问该节点。
思路:
1、将下一个结点的值赋给当前节点,
2、当前节点的下一个结点为下下一个结点。
public void deleteNode(ListNode node) {
node.val=node.next.val;
node.next=node.next.next;
}
8、编写一个函数,检查输入的链表是否是回文的。
将链表值放入双端队列,比较双端队列是否回文很简单
public static boolean isPalindrome(ListNode head) {
if(head==null||head.next==null){
return true;
}
LinkedList<Integer> list=new LinkedList<>();
ListNode temp=head;
while(temp!=null){//1、遍历链表,将其放入双端队列
list.add(temp.val);
temp=temp.next;
}
int left=0;
int right=list.size()-1;
while(left<right){//2、左右指针判断队列是否回文
int a=list.get(left);
int b=list.get(right);
if(a!=b){
return false;
}
left++;
right--;
}
return true;
}