24:两两交换列表中的结点
注意对循环结束条件的控制,涉及到由当前结点推算下一个结点,下下一个结点的时候要注意结点为空的情况。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode swapPairs(ListNode head) {
if((head==null)||(head.next==null))
return head;
ListNode dummy = new ListNode(0,head);
ListNode p = dummy, left = head, right = left.next;
while(left!=null){
p.next = right;
left.next = right.next;
right.next = left;
p = left;
left = left.next;
if(left==null)
break;
right = left.next;
if(right == null){
break;
}
}
return dummy.next;
}
}
第一次的想法:计算链表长度,然后再用总长度减去N,从而知道正向是第几个,找到后再进行结点删除。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
if(head==null)
return null;
int size = 0;
ListNode dummy = new ListNode(0,head);
ListNode p = head;
while(p!=null){
p=p.next;
size++;
}
int k = size - n;
int i;
for(p=dummy,i=0;i<size;i++,p=p.next){
if(i==k){
p.next = p.next.next;
}
}
return dummy.next;
}
}
双指针法:利用快慢指针进行遍历,定义slow和fast指针都指向head结点,快指针前进N+1个结点,然后slow和fast指针每次向前移动一个结点,如果fast指针指向为null,则说明到了结尾,slow指针的下一个结点就是倒数第N个结点,删除即可。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
if(head==null)
return null;
ListNode dummy = new ListNode(0,head);
ListNode slow = dummy, fast = dummy;
for(int i=0;i<=n;i++)
fast = fast.next;
while(fast!=null){
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return dummy.next;
}
}
面试题 02.07:链表相交
如果headA长于headB,curA指向headA,curB指向headB,移动curA使得curA和curB长度一致,之后curA和curB依次向前移动,如果curA和curB指向同一个结点,说明这个结点就是相交结点。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int sizeA = 0;
int sizeB = 0;
for(ListNode p=headA;p!=null;p=p.next)
sizeA++;
for(ListNode p=headB;p!=null;p=p.next)
sizeB++;
int d = sizeA > sizeB ? sizeA - sizeB : sizeB - sizeA;
ListNode curA = headA, curB = headB;
if(sizeA > sizeB){
for(int i=0;i<d;i++){
curA = curA.next;
}
}else if(sizeA < sizeB){
for(int i=0;i<d;i++){
curB = curB.next;
}
}
while(curA!=null){
if(curA == curB){
return curA;
}else{
curA = curA.next;
curB = curB.next;
}
}
return null;
}
}
9:环形列表II
参考Carl哥的题解,思路还是很清楚的,很有收获。
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head == null) return null;
ListNode fast = head, slow = head;
while((fast!=null)&&(fast.next!=null)){
slow = slow.next;
fast = fast.next.next;
if(fast == slow){
ListNode curA = head, curB = slow;
while(curA!=curB){
curA = curA.next;
curB = curB.next;
}
return curA;
}
}
return null;
}
}
总结:经过这段时间,对链表的操作方式和双指针方法熟练了很多,找到思路的话代码实现速度也快了不少。希望能坚持下去。