1, equal to a given value to delete the list ** val ** all nodes.
Analysis of ideas:
Define two auxiliary pointers prev and cur, can be deleted when prev.next.data = val
Mainly do not forget to deal with the first node
public void removeAllKey(int key) {
ListNode prev = this.head;
ListNode cur = this.head.next;
while(cur != null) {
if (prev.next.data == key) {
prev.next = cur.next;
cur = cur.next;
} else {
prev = cur;
cur = cur.next;
}
}
//处理第一个节点--最后处理
if (this.head.data == key) {
this.head = this.head.next;
}
}
prev = cur
public ListNode reverseList() {
if(this.head == null) {
return null;
}
ListNode cur = this.head;
ListNode prev = null;
ListNode newHead = null;
while (cur != null) {
ListNode curNext = cur.next;
if (curNext == null) {
newHead = cur;
}
cur.next = prev;
prev = cur;
cur = curNext;
}
return newHead;
}
public ListNode middleNode() {
// ListNode cur = this.head;
// int length = getlength()/2;
// for (int i = 0; i < length; i++) {
// cur = cur.next;
// }
// return cur;
ListNode fast = this.head;
ListNode slow = this.head;
while(fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
Note: first determining whether a valid k , most efficient way is to take the step up to the number of nodes -1, so fast while the pointer is determined to be walking, fast.next = null; k illegal instructions to return null.
public ListNode FindKthToTail(int k) {
if (k <= 0 || this.head == null) {
return null;
}
ListNode fast = this.head;
ListNode slow = this.head;
for (int i = 0; i < k-1; i++) {
if (fast.next == null) {
return null;
}
fast = fast.next;
}
while(fast.next != null) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
public static ListNode mergeTwoLists1(ListNode headA, ListNode headB){
ListNode newHead = new ListNode(-1);
ListNode tmp = newHead;
while (headA != null && headB != null) {
if (headA.data < headB.data) {
tmp.next = headA;
headA = headA.next;
tmp = tmp.next;
} else {
tmp.next = headB;
headB = headB.next;
tmp = tmp.next;
}
}
//如果a为空
if (headA == null) {
tmp.next = headB;
} else {
tmp.next = headA;
}
return newHead.next;
}
6, write code to the given value x is divided into two parts for the reference will list all smaller than the x node is greater than or equal to the row x previous node.
Thinking Analysis:
① First, there must be two references beginStart and beginEnd, afterStart and afterEnd
② when the data list node k h ratio, beginStart into the node pointed to by the linked list node when the data is larger than k, into afterStart points to the node.
Put the time to pay attention to whether the first release.
③ to link the beginEnd and afterStart
Looks like the end, in fact, missed two questions:
. If the A list, in all less than k, then return bs no problem. . However, if all the elements in the list is greater than k, bs description is empty, as can be directly returned, plus a determination.
b. When we return bs time, you will find printed lists termination condition is null, but when the list is done and, ae.next not necessarily empty, so we want ae.next last set is empty. So be feasible Hey ~
public ListNode partition(int x){
ListNode bs = null;
ListNode be = null;
ListNode as = null;
ListNode ae = null;
ListNode cur = this.head;
while (cur != null) {
if (cur.data < x) {
//判断是否为第一次加入
if (bs == null) {
bs = cur;
be = cur;
} else {
be.next = cur;
be = be.next;
}
} else {
//判断是否为第一次加入
if (as == null) {
as = cur;
ae = cur;
} else {
ae.next = cur;
ae = ae.next;
}
}
cur = cur.next;
}
//连在一起
if (be.next != null) {
be.next = as;
}
//判断是否k是否小于所以节点
if (bs == null) {
return as;
}
if (as != null) {
ae.next = null;
}
return bs;
}
7. In a sorted linked list nodes duplicate, delete the duplicate node list, the node does not retain repeated, returns the head pointer list.
Thinking Analysis:
① find duplicate nodes, define a single auxiliary variable cur traversal list, if the node cur.data = DESCRIPTION cur.next.data have duplicate data. However, note repeated more than one node, so use cycle is determined.
② remove duplicate node
Note:
. A judge must determine when each judge cur.data == cur.next.data cur.next is null. Otherwise it will cause a null pointer exception.
. b If the last repeating node is also a node, then to tmp.next = null;
public ListNode deleteDuplication(){
ListNode cur = this.head;
ListNode newHead = new ListNode(-1);
ListNode tmp = newHead;
while (cur != null) {
//重复的节点
if(cur.next != null && cur.data == cur.next.data) {
//每一次都需要判断cur.next
while (cur.next != null && cur.data == cur.next.data) {
cur = cur.next;
}
cur = cur.next;
} else {
tmp.next = cur;
tmp = tmp.next;
cur = cur.next;
}
}
//最后一个节点如果也是重复的,需要将tmp.next置为空
tmp.next = null;
return newHead.next;
}
8. palindrome list.
How to determine the palindrome list it?
② reverse list
③fast / slow forward head next to go
//单链表判断回文数
public boolean chkPalindrome() {
//为空
if (this.head == null) {
return false;
}
//一个数
if (head.next == null) {
return true;
}
//1、找到单链表的中间节点
ListNode fast = this.head;
ListNode slow = this.head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
//2、反转单链表
ListNode cur = slow.next;
while (cur != null) {
ListNode curNext = cur.next;
cur.next = slow;
slow = cur;
cur = curNext;
}
//3、fast/slow往前 head往后走
while (this.head != slow) {
if (this.head.data != slow.data) {
return false;
}
//偶数个数
if (this.head.next == slow) {
return true;
}
this.head = this.head.next;
slow = slow.next;
}
return true;
}
9. Enter the two lists, find their first common node.
思路分析:
①将pL指向长链表,pL指向短的链表
②让长链表先走差值步
③分别一步一步走,如果节点相同就为相交
注意:
注意计算完长度后pS、pL重新赋值,还有最后循环退出的条件
public static ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA == null || headB == null) {
return null;
}
ListNode pL = headA;//永远指向长的单链表
ListNode pS = headB;//永远指向短的单链表
int lenA = 0;
int lenB = 0;
//求的lenA lenB
while (pL != null) {
lenA++;
pL = pL.next;
}
while (pS != null) {
lenB++;
pS = pS.next;
}
//pl、ps为空了
pL = headA;
pS = headB;
//差值-》最长的单链表先走len步
int len = lenA-lenB;
if(len < 0) {
pL = headB;
pS = headA;
len = lenB-lenA;
}
//让pL先走len步
for (int i = 0; i < len; i++) {
pL = pL.next;
}
//开始一起走 (pL != pS ) {一人一步走}
while (pL != pS) {
pL = pL.next;
pS = pS.next;
}
// if (pL == null) {
// return null;
// }
// return pL;
return pL;
}
判断链表是否有环可以使用快慢指针法,快的每次走两步,慢的每次走一步。若快的和慢的相遇则有环。
//判断链表是否有环
public boolean hasCycle() {
ListNode fast = this.head;
ListNode slow = this.head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if (fast == slow) {
break;
}
}
if (fast == null || fast.next ==null) {
return false;
}
return true;
}
//创造一个环
public void creteLoop() {
ListNode cur = this.head;
while (cur.next != null) {
cur = cur.next;
}
cur.next = this.head.next;
}
11. 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
当slow=fast时,将slow指向头节点。slow和fast同时往后走,当slow和fast相等时的节点就是链表开始入环的第一个节点。
public ListNode detectCycle() {
ListNode fast = this.head;
ListNode slow = this.head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if (fast == slow) {
break;
}
}
if (fast == null || fast.next ==null) {
return null;
}
slow = this.head;
while (slow != fast) {
slow = slow.next;
fast = fast.next;
}
return slow;
}
证明:画图
12、给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。
要求返回这个链表的深拷贝。
思路分析:
①老新进行进行交替链接
②修改random
③将老新节点打开
public Node copyRandomList(Node head) {
if(head == null) {
return null;
}
Node cur = head;
//1、老新进行进行交替链接
while(cur != null) {
Node node = new Node(cur.val, cur.next, null);
Node tmp = cur.next;
cur.next = node;
cur = tmp;
}
//2、修改random
cur = head;
while(cur != null) {
if(cur.random != null) {
cur.next.random = cur.random.next;
cur = cur.next.next;
} else {
cur = cur.next.next;
}
}
//3、将老新节点打开
cur = head;
Node newHead = cur.next;
while(cur.next != null) {
Node tmp = cur.next;
cur.next = tmp.next;
cur = tmp;
}
return newHead;
}
最近做了挺多单链表的题,感觉虽然有的题目思路并不是特别难,但是一不小心就会造成空指针异常,因此做单链表的题要考虑全面,包括单链表的头、尾以及单链表是否为空,next是否为空。。。。