附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 }
来源:https://www.cnblogs.com/qmillet/p/11951940.html