24. 两两交换链表中的节点
我的代码实现:
public ListNode swapPairs(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode newhead = head.next;
ListNode pre = head ,fir ,sec ;
head.next = newhead.next;
newhead.next = head;
if(pre != null){
fir = pre.next;
if(fir != null){
sec = fir.next;
while (fir != null && fir.next !=null){
pre.next = sec;
fir.next = sec.next;
sec.next = fir;
pre = fir;
if(pre != null){
fir = pre.next;
}if(fir != null){
sec = fir.next;
}
}
}
}
return newhead;
}
在我实现的过程中首先对头结点和第二个节点是否为空进行判断,如果头节点为空或第二个节点为空(只有一个节点,不需进行交换),则直接返回head,否则的话因为头结点的原因,需要单独先对前两个元素进行处理,
从后往前进行链接,先将newhead赋值为链表的第二个节点,作为以后的返回值,然后把原链表的第二个节点的next赋给原链表头节点的next,然后将原链表的第二个节点的next赋为原链表头节点的head,然后将原链表头节点赋给pre,
接下来判断pre是否为空(这里应该没什么用),如果为空则把pre.next赋值给fir,接下来判断fir.next是否为空,如果为空不进入if分支直接return newhead(只剩fir一个数据没做处理,但因为只有一个数据,不需要做交换,所以直接返回),如果不为空则进入循环,
对pre,fir,sec,三个指针进行处理,从后往前进行连接,交换fir和sec,pre作为辅助节点存储fir的父节点,直至fir为空或fir.next为空(只剩0个或1个未处理节点)。然后返回newhead。
在老师给的解法中,老师利用了一个虚拟头节点dummyhead,省去了我对头结点和第二个节点的单独处理,也就是创建虚拟节点dummyhead,next指向head,而将这个节点作为pre,对第一个节点和第二个节点进行操作。在循环结束后直接而返回虚拟节点的next。
19.删除链表的倒数第N个节点
我的代码实现:
public ListNode removeNthFromEnd(ListNode head, int n) {
List<ListNode> list = new ArrayList<ListNode>();
ListNode node = head;
while (node!=null){
if(list.size()>n){
list.remove(0);
}
list.add(node);
node = node.next;
}
if(list.size() == n+1){
list.get(0).next = list.get(0).next.next;
}
if(list.size() == n){
head = list.get(0).next;
}
return head;
}
在我的实现方法中我利用了ArrayList,从头开始遍历链表,依次将每个节点加入list中,当list的大小大于n的时候,先移除第一个元素后再继续在尾部添加元素,遍历完成后,通过判断list的大小进行处理,
如果 list.size() == n+1 说明待删除节点不是头结点,list.get(0)是待删除节点的父节点,下一个节点就是待删除节点,然后进行删除。
如果 list.size() == n 说明待删除节点是头结点,需要对头节点进行重新赋值,
如果以上两种条件都不满足,因为循环里的remove操作 list.size不可能大于 n+1 所以只剩下 list.size < n的情况没做处理,当这种情况时说明输入值不合法,不需做处理。
最后返回处理后的头结点。
在老师给的解法中运用了双指针,快指针比慢指针快n+1个节点,当快指针指空时慢指针指的就是待删除节点的父节点,这也比我简单太多了吧o(╥﹏╥)o
面试题 02.07. 链表相交
我的代码实现:
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ArrayList<ListNode> list1 = new ArrayList<ListNode>();
ArrayList<ListNode> list2 = new ArrayList<ListNode>();
ListNode l = null;
while (headA != null){
list1.add(headA);
headA = headA.next;
}
while (headB != null){
list2.add(headB);
headB = headB.next;
}
if(headA == headB){
return headA;
}
while (!list1.isEmpty() && !list2.isEmpty()){
if(list1.get((list1.size()-1)) == list2.get((list2.size()-1))){
l = list1.remove((list1.size()-1));
list2.remove((list2.size()-1));
}else {
return l;
}
}
if (list1.isEmpty())
return headA;
else
return headB;
}
在这道题里我又用了两个list,将每个链表存入list中,然后从后面开始对比,发现不一样的节点的下一个节点就是汇聚的节点。如果从一开始就不一样就是没有汇聚的链表。
老师给的解法是获得两个链表的长度,获得两个链表的差值,然后长的链表从差值开始,这样两个链表就同步了,回顾我的代码。。好愚蠢o(╥﹏╥)o
142.环形链表II
我的代码
public ListNode detectCycle(ListNode head) {
ArrayList<ListNode> arrayList = new ArrayList<>();
while (head!=null){
if(arrayList.contains(head)){
return head;
}else {
arrayList.add(head);
head = head.next;
}
}
return head;
}
在这道题里我又双叒用了一个list,从头开始遍历,把每个节点头加入到list里,加入前先判断list是否存在当前对象,如果存在了就说明当前节点是环形入口直接返回,否则接着往下遍历,直至head 为null,说明list里没有重复的节点,说明没有环,返回null。
老师给的解法是双指针,快指针一次走两步,慢指针一次走一步,在圈里慢指针会遇到快指针。没有遇到遍历到头就说明没环