问题分析
主要是学习了关于单链表的增删改查操作还有链表节点交换、倒数删除。
思路分析
第一道题单链表还好办,双链表在第一题没敢碰,正好昨晚上熬夜了,正是困得时候,也就只写了单链表。
第二题是相邻互换,一定要画图!!!画完图就知道怎么变换了,总体分三步(我链表里面基本都用的虚拟头结点方法):
1:虚拟头—>2
2: 2—>1
3: 1—>3
我发现很多链表题都需要有个不动的点来连接过去操作过的节点:比如此处的3,在1和2交换的时候,没有3的事,但后面你还要跟3这个节点连接,就可以写个temp来保存它。
然后就定义两个指针:pre和cur指向虚拟头结点和头节点,我看有的方法只有一个cur,反正怎么清醒怎么来。
第三题是一个倒数删除的链表题,链表真是绝了,一直都是双指针解决的多。这里也是双指针:快慢指针。快指针先走n+1或者n,这个无所谓,后面你处理快慢指针同频的时候处理好就行,但你要问我为什么快指针先走n+1然后快慢指针同频就能解决倒数删除问题,我也不清楚,,,,反正我也画了画图,就神奇的解决了,我也不理解这里面啥道理,反正就用了快慢指针,,,离谱,过会我去查查。
第一题
class MyLinkedList {
int size;
ListNode node;//虚拟头节点
public MyLinkedList() {
size = 0;
node = new ListNode();
}
public int get(int index) {
if(size < 0 || index >= size)
return -1;
ListNode cur = node;
for(int i = 0; i <= index; i++){
cur = cur.next;
}
return cur.val;
}
public void addAtHead(int val) {
addAtIndex(0,val);
}
public void addAtTail(int val) {
addAtIndex(size, val);
}
public void addAtIndex(int index, int val) {
if(index > size)
return;
if(index < 0)
index = 0;
size++;
ListNode pre = node;
for(int i = 0; i < index; i++){
pre = pre.next;
}
ListNode addnode = new ListNode(val);
addnode.next = pre.next;
pre.next = addnode;
}
public void deleteAtIndex(int index) {
if(index < 0 || index >= size)
return;
size--;
ListNode pre = node;
for(int i = 0;i < index; i++)
pre = pre.next;
pre.next = pre.next.next;
}
}
第二题:
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode node = new ListNode();
node.next = head;
ListNode pre = node;
ListNode cur = head;
while(pre.next != null && pre.next.next != null){
ListNode tem = cur.next.next;//保存好第三个节点
pre.next = cur.next;//虚拟头节点连接第二个
cur.next.next = cur;//2连接头节点也就是第一个节点
cur.next = tem;//1连接3
pre = cur;
cur = cur.next;
}
return node.next;//注意这个地方,一定是虚拟节点的next
}
}
第三题:
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode fast = new ListNode();
ListNode slow = new ListNode();
ListNode dump = new ListNode();
dump.next = head;
fast = dump;
slow = dump;
for(int i = 0;i < n; i++)
fast = fast.next;//走n步或者n+1步是没有关系的,只是下面快慢指针同频的处理不一样
ListNode pre = new ListNode();//记住待删除节点的上一节点
while(fast != null){
pre = slow;
slow = slow.next;
fast = fast.next;//然后快慢指针再同频走
}
pre.next = slow.next;
return dump.next;
}
}
好了。我查阅解决,就是fast跟slow说,我知道你也不知道这个链表有多长,我就先走给你步量一下。快指针先走n+1步,然后快慢指针一起走,当快指针为null,指到空就没有了,那慢指针这时候停下,距离快指针就是n个值,正好倒数为第n个节点,就可以把慢指针指的给删除了。快指针先走就是为了步量出慢指针所需要的这个n,突然有点子感人。