附1:Stack API
附2:ArrayList API
题一:输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
法一:递归
1 /**
2 * public class ListNode {
3 * int val;
4 * ListNode next = null;
5 *
6 * ListNode(int val) {
7 * this.val = val;
8 * }
9 * }
10 *
11 */
12 import java.util.ArrayList;
13 public class Solution {
14 ArrayList list = new ArrayList();
15 public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
16 if(listNode!=null){
17 printListFromTailToHead(listNode.next);
18 list.add(listNode.val);
19 }
20 return list;
21 }
22 }
法二:Stack
1 import java.util.*;
2 public class Solution {
3 ArrayList list = new ArrayList();
4 public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
5 Stack stack = new Stack();
6 while(listNode!=null){
7 stack.push(listNode.val);
8 listNode = listNode.next;
9 }
10 while(!stack.empty()){
11 list.add(stack.pop());
12 }
13 return list;
14 }
15 }
法三:ArrayList内部方法
1 import java.util.ArrayList;
2 public class Solution {
3 public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
4 ArrayList list = new ArrayList();
5 while(listNode!=null){
6 list.add(0,listNode.val);//相当于insert,在0位置插入元素
7 listNode = listNode.next;
8 }
9 return list;
10 }
11 }
题二:给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
分析:三步走
1.判断是否有环-》设置两个指针lp、rp,lp一次走一步,rp一次走两步。如果rp能够追上lp则说明有环(rp通过环绕了一圈和lp相遇,否则rp直接走到链表尾部),如果rp走到尾部还没有相遇则说明无环;
2.得到环中结点的数目-》第一步结束时,lp和rp会在环内相遇,rp此时停止遍历,lp开始一个节点一个节点遍历,再次相遇时(lp在环内走一圈)即可求出环内节点数目(此处可设置整数n++)。
3.找到环的入口-》通过第二步求出环内节点数n,此时可再设置两个指针,一个指针先走n步(此时指针之间有n-1个节点),两指针同时遍历,相遇时指向的节点即为环的入口。
1 /*
2 public class ListNode {
3 int val;
4 ListNode next = null;
5
6 ListNode(int val) {
7 this.val = val;
8 }
9 }
10 */
11 public class Solution {
12
13 public ListNode EntryNodeOfLoop(ListNode pHead)
14 {
15 ListNode lp=pHead;
16 ListNode rp=pHead;
17 boolean flag = false;//是否有环标志
18 //1.判断是否有环
19 while(rp.next!=null){//rp还没走到末尾
20 lp=lp.next;
21 rp=rp.next.next;
22 if(lp==rp){
23 flag=true;
24 break;//此时两个指针在环内相遇
25 }
26 }
27 if(!flag){//没环
28 return null;
29 }else{
30 //2.得到环中结点的数目
31 int n=1;
32 lp = lp.next;
33 while(lp!=rp){//while循环完,两指针在相同位置再次相遇
34 lp=lp.next;//rp不动,lp一步一步走
35 n++;
36 }
37 //3.找到环的入口
38 lp=pHead;
39 rp=pHead;
40 for(int i=0;i<n;i++){
41 rp=rp.next;//rp先走n步
42 }
43 while(lp!=rp){//两指针同时走
44 lp=lp.next;
45 rp=rp.next;
46 }
47 return lp;
48 }
49
50 }
51 }
题三:在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
分析:
关键点:链表有序,并且重复的节点不保留,全删除。
整体思想:遍历链表,通过比较当前节点和前后节点的值,找出满足条件的节点,添加到自设的头节点之后;
注意:1.自设头节点是为了解决头节点重复问题(自己搞一个头结点,题目中的直接遍历即可)
2.还要注意末尾重复问题-》实行“断尾”手段----head.next=null;每次添加完满足条件的节点之后,将该节点之后的连接去除(干干净净,只 关注该节点)
1 /*
2 public class ListNode {
3 int val;
4 ListNode next = null;
5
6 ListNode(int val) {
7 this.val = val;
8 }
9 }
10 */
11 public class Solution {
12 public ListNode deleteDuplication(ListNode pHead)
13 {
14 //为了解决头节点重复的问题,重新设置一个头结点
15 ListNode head = new ListNode(-1);
16 ListNode tmp=head;//保存返回值
17 ListNode pre = null;//前一个结点
18 ListNode cur = pHead;//当前节点
19 ListNode next = null;//后一个节点
20 while(cur!=null){
21 next = cur.next;
22 if((pre==null||cur.val!=pre.val)&&(next==null||cur.val!=next.val)){//当前节点值和前后节点值都不相同,则将当前节点挂在tmp之后;
23 head.next = cur;
24 head = head.next;//递进
25 head.next=null;//防止链表末尾重复
26 }
27 pre = cur;
28 cur = next;
29 }
30 return tmp.next;//返回自设头结点的下一个节点
31 }
32 }