据说链表是面试是比较容易出现的数据结构。把leetcode上关于链表的题之前差不多刷完了。
AC不过的最主要原因就是考虑的情况不完全,尤其是头指针,以及最后一个元素,空指针等。
面试题第五题:从尾到头打印链表
第一想法是用栈。
考虑到java中栈的定义为:
Stack<ListNode> sk = new Stack<ListNode>();
判断栈空的条件是sk.isEmpty()
第二个是用递归
每一次调用自身传进去的参数是当前值的next
public static void reverseList(ListNode head) {
if (head == null && head.next == null) {
System.out.println(head.val);
} else {
if (head.next != null) {
reverseList(head.next);
}
}
System.out.println(head.val);
}
面试题13,:在O(1)的时间删除链表结点
核心想法是为了便于不记录要删除结点的上一个结点,把下一个节点的内容复制到需要删除的节点上覆盖原有的内容,相当于删除了指定结点。但是一定要注意如果头结点为指定结点,指定结点为最后一个节点的情况。
因此,当删除一个节点时,并不一定要删除这个结点本身,可以把下一个节点的内容复制出来覆盖被删除结点的内容,然后再把下一个节点删除!
下面代码只是将最核心的展示,并没有考虑头结点以及尾结点
public static ListNode deleteNode(ListNode head, ListNode de){
ListNode newHead = head;
while(head.val!=de.val&&head.next!=null){
head = head.next;
}
head.val = head.next.val;
head = head.next;
return newHead;
}
同样,编程之美3.4节中无头链表中删除指定结点
函数的参数只是指明了要删除的结点current
因此我们先要找到Current 的下一个节点,然后用current.next.val去覆盖当前的Current.val
然后current = current.next.next
不是很明白有头链表和无头链表的区别?
另外在编程之美上还有一道题比较有意思就是判断两个链表是否相交
比较好的方法有两个:
一、将其中一个链表首尾相连,检测另外一个链表是否存在环,如果存在,则两个链表相交,而检测出来的依赖环入口即为相交的第一个点。
二、如果两个链表相交,那个两个链表从相交点到链表结束都是相同的节点,我们可以先遍历一个链表,直到尾部,再遍历另外一个链表,如果也可以走到同样的结尾点,则两个链表相交。
这时我们记下两个链表length,再遍历一次,长链表节点先出发前进(lengthMax-lengthMin)步,之后两个链表同时前进,每次一步,相遇的第一点即为两个链表相交的第一个点。
Node* findCross(Node* head1,Node* head2)
{
if(head1==NULL||head2==NULL)
return NULL;
/*将第二个链表变成有环链表*/
Node* tail2=head2;
while(tail2->next!=NULL)
tail2=tail2->next;
tail2->next = head2;
Node* temp = findCircle(head1);
if(temp!=NULL)
return temp;
else
return NULL;
}
bool isIntersect(pNode h1, pNode h2)
{
if(!h1 || !h2)
return false;
bool flag = false;
pNode temp_h1 = h1;
pNode temp_h2 = h2;
//找到第一个链表的尾节点,将第二个链表挂在其后
while(temp_h1->next != NULL)
temp_h1 = temp_h1->next;
temp_h1->next = h2;
do
{
temp_h2 = temp_h2->next;
}while(temp_h2 && temp_h2 != h2);
if(temp_h2 == h2)
flag = true;
//将链表恢复原样
temp_h1->next = NULL;
return flag;
}
剑指offer面试题15:链表中的倒数第K个结点
今天先到底为止,看一会操作系统的事。
明天继续,明天一天把所有链表的题看完。