1.反转单链表
反转一个点链表呢,就如下所示:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
//反转单链表
public Node reverseList1() {
Node cur = this.head;
Node prev = null;
Node newHead = null;
while (cur != null) {
Node curNext = cur.next;
if (curNext == null) {
newHead = cur;
}
cur.next = prev;
prev = cur;
cur = curNext;
}
return newHead;
}
遇到这个问题呢,首先我们会想到去倒过来操作它,但问题是,这个单链表只有不断向后指,当我们想去将每一个结点都指向前面一个结点时,是没有办法去操作他这个前一个节点的,所以我们还是得从前往后操作。过程中呢,我们首先得想到设置三个变量prev,cur,curNext,功能分别是,反转,和追踪下一个要反转的结点。定义cur指向头节点,判断cur是不是为空,不为空进入循环,定义一个curNext让他指向cur的下一个结点,再判断它是否为空,为空就定义一个新头结点newHead让他指向cur,就是反转后的链表的头节点,否则就开始反转,让cur指向前一个结点prev,然后prev和cur分别向后移,重复上述操作,直到cur为空反转完成退出循环,返回新的头节点newHead。
2.头插法反转单链表
//头插法反转单链表
public Node reverseList2() {
//Node x = head.next;
int num = this.head.data;
Node cur = this.head.next;
while (cur != null) {
addFirst(cur.data);
cur = cur.next;
}
Node s = this.head;
while (s != null) {
if (s.data == num) {
s.next = null;
return head;
}
s = s.next;
}
// x = null;
/* Node u = this.head;
while(u.next != null) {
u = u.next;
}
u.next = null;*/
return head;
}
还有一种方法呢,就是用头插法去反转,这个代码呢是我自己写的,运行结果测试是没有问题的,如果有大佬发现问题,请及时告知小弟改正。步骤的,就是从头节点的下一个结点开始逐渐用头插法插到头节点前面,不过首先需要记下当前头节点的data数据,方便最后将此节点的next置为null,然后到所有结点都反转后,遍历链表使当前的最后一个结点的next置为空,链表就反转完了。
3.返回链表的中间结点
//返回链表的中间节点
public Node middleNode() {
Node fast = this.head;
Node slow = this.head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
这种题呢,其实并不难,主要是看我们解题的思路,一般人们会去遍历一遍获取长度,一次来返回中间结点,而我们呢,可以用两个结点都先指向头节点,一个走一步,一个走两步,当走的快的那个结点为空或者他的下一个结点为空时,我们就返回当前的走慢的结点,那个循环终止条件主要是根据结点数是奇数还是偶数而变得。
4.返回倒数第K个结点
//返回倒数第K个节点
public Node FindKthToTail(int k) {
if (k <= 0 || k > size()) {
return null;
}
Node fast = this.head;
Node slow = this.head;
int i = 0;
while (i < k - 1) {
fast = fast.next;
i++;
}
while (fast.next != null) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
这个呢,思路和上一个题思路一样,就是先让一个结点走k步,然后两个一人一步走,当前面那个结点走到最后一个结点时,返回走的慢的那个结点,此时就是倒数第K个结点。
5.以给定的x为分割线,小于x的排在大于等于x的数之前,原来数的序列保持不变
//以给定的x为分割线,小于x的排在大于等于x的数之前,原来数的序列保持不变
public Node partition(int x) {
Node cur = this.head;
Node bs = null;
Node be = null;
Node as = null;
Node ae = null;
while (cur != null) {
if (cur.data < x) {
if (bs == null) {
be = cur;
bs = be;
} else {
be.next = cur;
be = be.next;
}
}else {
if (cur.data >= x) {
if (as == null) {
ae = cur;
as = ae;
} else {
ae.next = cur;
ae = ae.next;
}
}
}
cur = cur.next;
}
if(bs == null) {
return as;
}else {
be.next = as;
if(as!= null) {
ae.next = null;
}
return bs;
}
}
}
这题的思路,就是先遍历一遍链表,然后与X 作比较,小于x的放在bs-be链表里,大于x的放在as-ae的链表里,放前,分别先判断两个链表是否为空,分别做相应的操作,之后,再判断,如果bs为空则返回第二个链表,即as,若不为空,则把两个链表链接,be指向as,此时在做判断,如果as不为空,则需要把ae的next置为空,最后,再返回**bs,**整个表就返回了。
6.将两个已经排好序的链表从小到大排成一个新的链表
public class TestDemo {
public static Node mergeTwoLists(Node headA, Node headB) {
Node newHead = new Node(-1);
Node 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;
}
}
if(headA != null) {
tmp.next = headA;
}
if(headB != null) {
tmp.next = headB;
}
//1、当两个单链表都不为空的时候
//2、第一步完成后 其中一个单链表不为空 一个为空
return newHead.next;
}
我们可以重新创建一个链表,将两个链表里的值分别做好比较后放入新的链表里,新创建一个头节点,做好标记,然后创建一个结点指向该节点,当两个链表都不为空时,比较两个链表的值,将较小的放入链表中,然后各一步走,继续比较,跳出循环后,我们需要判断是哪个链表遍历完了,哪个完了,就将当前的tmp直接指向另一个链表的当前的头节点就行了,最后需要注意的是,我们需要返回的,是新头节点的下一个结点。
7.判断两个链表是否相交
//判断两个单链表是否相交
public static Node getIntersectionNode(Node headA,Node headB) {
if(headA == null || headB == null) {
return null;
}
int count1 = 0;
int count2 = 0;
Node pL = headA;
Node pS = headB;
while(pL != null) {
pL = pL.next;
count1++;
}
while(pS != null) {
pS = pS.next;
count2++;
}
pL = headA;
pS = headB;
int len = count1-count2;
if(len<0) {
pL = headB;
pS = headA;
len = count2-count1;
}
while(len > 0) {
pL =pL.next;
len--;
}
while(pL!= null && pS != null && pL != pS) {
pL = pL.next;
pS = pS.next;
}
if(pL!= null && pL == pS) {
return pL;
}
return null;
}
判断相交呢,这是个y字形的,就是遇到相同的结点后两个链表就结合成一个了,后面的完全相同,还需要注意的是,这里的判断链表是否相交,是比较的两个节点的地址是否相同,而不是他们的data,如果其中一个链表为空的话,自然是没有相交,之后,我们先让比较长的链表走和短的链表相差的步数,然后一人一步走做比较,出循环后判断,如果是因为pL和pS 为空跳出的话,说明没找到相交点,直接返回null,否则是因为pL==pS的话,则找到相交点,返回这个结点。