链表和递归
1、LeetCode—203
删除链表元素
不使用虚拟头结点:
public class Solution203 {
public ListNode removeElements(ListNode head, int val) {
while(head!=null&&head.val==val) {
ListNode delNode=head;
head=head.next;
delNode.next=null;
}
if(head==null)
return null;
//中间
ListNode prev=head;
while(prev.next!=null) {
if(prev.next.val==val) {
ListNode delNode=prev.next;
prev.next=prev.next.next;
delNode.next=null;
}else {
prev=prev.next;
}
}
return head;
}
}
使用虚拟头结点:(对用户屏蔽)
public class Solution203_2 {
public ListNode removeElements(ListNode head, int val) {
ListNode dummyHead=new ListNode(-1);
dummyHead.next=head;
ListNode prev=dummyHead;
while(prev.next!=null) {
if(prev.next.val==val) {
prev.next=prev.next.next;
}else {
prev=prev.next;
}
}
return dummyHead.next;
}
}
2、测试LeetCode代码
把数组转成链表:
public ListNode(int[] arr) {
if(arr==null||arr.length==0)
throw new IllegalArgumentException("arr can not be empty");
this.val=arr[0];
ListNode cur=this;
for(int i=1;i<arr.length;i++) {
cur.next=new ListNode(arr[i]);
cur=cur.next;
}
}
#main
int[] nums= {1,2,6,3,4,5,6};
ListNode head=new ListNode(nums);
#测试LeetCode代码
ListNode res=(new Solution203()).removeElements(head, 6);
3、递归
将原来的问题,转化为更小的同一问题。
递归函数也是函数
数组求和:
public static int sum(int[] arr,int l){
if(l==arr.length)
return 0;//求解最基本问题
return arr[l]+sum(arr,l+1);//把原问题转化成更小的问题
}
#最终调用sum(arr,0)
4、链表的天然递归结构性质
解决leetcode203问题:移除链表中等于给定值val的所有节点
public ListNode removeElements(ListNode head,int val) {
if(head==null)
return null;
ListNode res=removeElements(head.next,val);
if(head.val==val)//处理head节点
return res;
else {
head.next=res;
return head;
}
//head.next=removeElements(head.next,val);
//return head.val==val?head.next:head;
}
5、递归函数的微观解读
递归函数的调用本质上仍然是函数的调用,只不过调用的是它本身。
调试递归:用一个很小的数据集模拟递归的调用过程。
递归代价:函数调用+系统栈空间。
6、如何调试递归程序
1)打印输出
2)跟踪
7、更多关于链表
近乎所有链表的问题都可以用递归解决。
LeetCode上关于链表的问题
双链表
循环链表
数组链表