视频地址:帅地玩编程
剑指 Offer 06. 从尾到头打印链表
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
概念
.val()方法
- .val()无参数,获取匹配的元素集合中第一个元素的当前值
- .val( value ),设置匹配的元素集合中每个元素的值
- .val( function ) ,一个用来返回设置值的函数
.next()方法的作用:指针指向下一条记录,有记录(有值)返回true并把记录内容存入到对应的对象中,也就是obj.next()的obj中。如果没有返回false。
解题思路:
1.利用栈的先进后出
时间复杂度O(n) 空间复杂度O(n)
2.反转链表
递归 时间复杂度O(n) 空间复杂度O(n)
原地反转(容易出错) 时间复杂度O(n) 空间复杂度O(1)
3.从右到左遍历数组 时间复杂度O(n) 空间复杂度O(1)
推荐第三种做法:
1.判断链表是否为空,若为空,直接返回一个空数组;
2.若不为空,统计一下一共有多少个节点;
3.新建一个数组,从右往左遍历;
class Solution {
public int[] reversePrint(ListNode head) {
if(head==null){
return new int[0];
}
int count=0;
ListNode temp=head;
while(temp!=null){
count++;
temp = temp.next;
}
int[] res=new int[count];
int k=count-1;
while(head!=null){
res[k--]=head.val;
head=head.next;
}
return res;
}
}
剑指 Offer 24. 反转链表
定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
方法一:递归
1.判断链表为空或者链表中只有一个节点,直接返回这个节点;
2.否则,对他的子链表进行反转,反转后调整顺序;
3.返回新链表;
class Solution {
public ListNode reverseList(ListNode head) {
if(head==null||head.next==null){
return head;
}
ListNode temp=reverseList(head.next);
head.next.next=head;
head.next=null;
return temp;
}
}
时间复杂度O(n) 空间复杂度O(n)
方法二:原地排序
时间复杂度O(n) 空间复杂度O(1)
1.判断链表为空或者链表中只有一个节点,直接返回这个节点;
2.定义两个节点,cur指向当前第一个节点,pre是cur的前驱结点,开始时pre=null;
3.保存cur后边的全部节点,防止反转时丢失,temp=cure->next;
4.反转,cur->next=pre;
pre=cur;
cur=temp;
不断循环,直至当前节点为null;
5.返回pre,最后时pre指向的是最后一个节点。
class Solution {
public ListNode reverseList(ListNode head) {
if(head==null||head.next==null){
return head;
}
ListNode cur=head,pre=null;
while(cur!=null){
//保存后边的节点防止丢失
ListNode temp=cur.next;
//反转,把后边的节点放到前面
cur.next=pre;
//整体向右移动
pre=cur;
cur=temp;
}
return pre;
}
}
剑指 Offer 35. 复杂链表的复制
请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
思路:复制+拆分
解题思路:
1.判断节点是否为空,为空返回null;
2.否则,复制链表节点
3…复制随机节点
4.拆分
class Solution {
public Node copyRandomList(Node head) {
if(head==null){
return null;
}
//复制链表节点
Node cur=head;
while(cur!=null){
//复制之前先保存后续节点
Node next=cur.next;
//让当前节点指向复制节点 A->A1
cur.next=new Node(cur.val);
//这一步是让复制的节点拼凑起来
cur.next.next=next;
//右移一步
cur=next;
}
//复制随机节点
cur=head;
while(cur!=null){
Node curNew=cur.next;
//复制curNew的一个随机节点
curNew.random=cur.random==null?null:cur.random.next;
//cur右移一步
cur=cur.next.next;
}
//拆分
Node headNew=head.next;
cur=head;
Node curNew=head.next;
while(cur!=null){
//A->B
cur.next=cur.next.next;
//让cur从A移动到B
cur=cur.next;
//A1->B1
curNew.next=cur==null?null:cur.next;
//右移一步
curNew=curNew.next;
}
return headNew;
}
}