题目:
- 从尾到头打印链表
输入一个链表,从尾到头打印链表每个节点的值。 - 链表中倒数第k个结点
输入一个链表,输出该链表中倒数第k个结点。 - 反转链表
输入一个链表,反转链表后,输出新链表的表头。 - 合并两个排序的链表
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。 - 复杂链表的复制(复制带随机指针的链表)
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空) - 两个链表的第一个公共结点(相交链表)
输入两个链表,找出它们的第一个公共结点。 - 链表中环的入口结点
一个链表中包含环,请找出该链表的环的入口结点。 - 删除链表中重复的结点
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5 - 删除链表中的节点
请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。(只给定被删除的节点)
输入: head = [4,5,1,9], node = 5
输出: [4,1,9]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9. - 回文链表
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true - 链表A+B求和 (两数相加)
给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807 - 奇偶链表
给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。
请尝试使用原地算法完成。你的算法的空间复杂度应为 O(1),时间复杂度应为 O(nodes),nodes 为节点总数。
示例 1:
输入: 1->2->3->4->5->NULL
输出: 1->3->5->2->4->NULL
示例 2:
输入: 2->1->3->5->6->4->7->NULL
输出: 2->3->6->7->1->5->4->NULL
说明:
应当保持奇数节点和偶数节点的相对顺序。
链表的第一个节点视为奇数节点,第二个节点视为偶数节点,以此类推。 - 合并K个元素的有序链表
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6 - 链表排序
在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3
输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0
输出: -1->0->3->4->5
代码如下:
1、从尾到头打印链表
输入一个链表,从尾到头打印链表每个节点的值
/**
* public class ListNode {
* int val;
* ListNode next = null;
* ListNode(int val) {
* this.val = val;
* }
* }
*/
//方法1:栈思想:先进后出
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode)
{
Stack<Integer>stack=new Stack<Integer>();
ListNode pNode=listNode;
//入栈
while(pNode!=null){
stack.push(pNode.val);
pNode=pNode.next;
}
//出栈
ArrayList<Integer> al=new ArrayList<>();
while(!stack.isEmpty()){
al.add(stack.pop());
}
return al;
}
}
//方法2:递归思想
public class Solution {
ArrayList<Integer>al=new ArrayList<>();
public ArrayList<Integer> printListFromTailToHead(ListNode listNode)
{
if(listNode!=null){
this.printListFromTailToHead(listNode.next);
al.add(listNode.val);
}
return al;
}
}
2、链表中倒数第k个结点
输入一个链表,输出该链表中倒数第k个结点。
public class FindKthToTail {
public ListNode FindKthToTail(ListNode head,int k){
//定义两个指针,p1,p2,
//倒数第k个,即正数走n-k,总共n-1步,则p1先走k-1步,
// 然后p1,p2一起走,p1到结尾,此时p2刚好走n-k,到达倒数第k个节点
if(head==null||k<=0)
return null;
ListNode p1=head;
ListNode p2=head;
for (int i = 0; i <k-1 ; i++) {
if(p1.next!=null)
p1=p1.next;
else
return null;//这句至关重要,判断链表长度是否大于k
}
while(p1.next!=null){
p1=p1.next;
p2=p2.next;
}
return p2;
}
}
3、反转链表
输入一个链表,反转链表**后,输出新链表的表头
public class Solution {
public ListNode ReverseList(ListNode head) {
if(head==null)
return null;
//当前节点是head,pre为当前节点的前一节点,next为当前节点的下一节点
//需要pre和next的目的是让当前节点从pre->head->next1->next2变成pre<-head next1->next2
//即pre让节点可以反转所指方向,但反转之后如果不用next节点保存next1节点的话,此单链表就此断开了
//所以需要用到pre和next两个节点
//1->2->3->4->5
//1<-2<-3 4->5
ListNode pre=null;
ListNode next=null;
ListNode cur=head;
//pre, head, next
while(cur!=null)//不是while(cur.next!=null)
{
//先用next保存head的下一个节点的信息,保证单链表不会因为失去head节点的原next节点而就此断裂
// cur=head;
next=cur.next;
//保存完next,就可以让head从指向next变成指向pre了,
cur.next=