JAVA数据结构(四)

链表与递归

一、删除链表中的元素
leetCode:删除链表元素

  • 不使用虚拟头节点:需要对第一个元素进行判断
public class ListNode {
	int val;
	ListNode next;
	ListNode(int x) { 
		val = x; 
	}
}
class Solution {
    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 = delNode.next;
        		delNode.next=null;
        	}
        	else {
        		prev = prev.next;
        	}
        }
        return head;
    }
}

  • 使用虚拟头节点:不需要对首元素进行判断
public class ListNode {
	int val;
	ListNode next;
	ListNode(int x) { 
		val = x; 
	}
}

class Solution {
    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) {
        		ListNode delNode = prev.next;
        		prev.next = delNode.next;
        		delNode.next=null;
        	}
        	else {
        		prev = prev.next;
        	}
        }
        return dummyhead.next;
    }
}
  • 创建测试用例
package cn.itcast.day4;

public class ListNode {
	int val;
	ListNode next;
	ListNode(int x) { 
		val = x; 
	}
	//使用arr为参数,创建一个链表,当前的ListNode为链表头节点
	public ListNode(int[] arr) {
		if(arr == null || arr.length ==0) {
			throw new IllegalArgumentException("错误");
		}
		this.val = arr[0];
/*		在一个类的内部,也可以使用this代表自身类的对象,或者换句话说,
		每个类内部都有一个隐含的成员变量,该成员变量的类型是该类的类型,
		该成员变量的名称是this,实际使用this代表自身类的对象的示例代码如下:*/
		ListNode cur = this; // 使用this代表自身类的对象
		for(int i=1;i<arr.length;i++) {
			cur.next = new ListNode(arr[i]);
			cur = cur.next;
		}
	}
	@Override
	public String toString() {
		StringBuilder res = new StringBuilder();
		ListNode cur = this;
		while(cur!=null) {
			res.append(cur.val+"->");
			cur = cur.next;
		}
		res.append("NULL");
		return res.toString();
	}
}

二、递归

  • 将原问题转化为更小的同一问题
    在这里插入图片描述
    在这里插入图片描述
  • 利用递归解决链表中删除元素的问题
    在这里插入图片描述
  • 代码实现:
package cn.itcast.day4;

public class Solution3 {
    public ListNode removeElements(ListNode head, int val) {
        if(head == null) {
        	return null;
        }
        ListNode res = removeElements(head.next,val);
        if(head.val == val) {
        	return res;
        }else {
        	head.next = res;
        	return head;
        }
    }
    public static void main(String[] args) {
		int[] nums = new int[] {1,2,6,3,4,5,6};
		ListNode head = new ListNode(nums);
		System.out.println(head);
		ListNode res = (new Solution()).removeElements(head, 6);
		System.out.println(res);
	}
}

链表删除元素递归操作的逻辑:
在这里插入图片描述

  • 递归函数的微观解读
    在这里插入图片描述
  • 递归算法的调试 — > 打印输出
package cn.itcast.day4;

public class Solution3 {
    public ListNode removeElements(ListNode head, int val,int depth) {
        String depthString = generateDepthString(depth);
        
        System.out.print(depthString);
        System.out.println("Call:remove "+val +" in " + head);
    	if(head == null) {
    		System.out.print(depthString);
    		System.out.println("Return: "+ head);
        	return null;
        }
        ListNode res = removeElements(head.next,val,depth+1);
        System.out.print(depthString);
        System.out.println("After remove "+ val+":" +res);
        
        ListNode ret;
        if(head.val == val) {
        	ret =  res;
        }else {
        	head.next = res;
        	ret = head;
        }
        System.out.print(depthString);
        System.out.println("Return: "+ret);
        return ret;
    }
    private String generateDepthString(int depth) {
    	StringBuilder res = new StringBuilder();
    	for(int i=0;i<depth;i++) {
    		res.append("--");
    	}
    	return res.toString();
    }
    
    public static void main(String[] args) {
		int[] nums = new int[] {1,2,6,3,4,5,6};
		ListNode head = new ListNode(nums);
		System.out.println(head);
		ListNode res = (new Solution3()).removeElements(head, 6,0);
		System.out.println(res);
	}
}
// 输出

1->2->6->3->4->5->6->NULL
Call:remove 6 in 1->2->6->3->4->5->6->NULL
--Call:remove 6 in 2->6->3->4->5->6->NULL
----Call:remove 6 in 6->3->4->5->6->NULL
------Call:remove 6 in 3->4->5->6->NULL
--------Call:remove 6 in 4->5->6->NULL
----------Call:remove 6 in 5->6->NULL
------------Call:remove 6 in 6->NULL
--------------Call:remove 6 in null
--------------Return: null
------------After remove 6:null
------------Return: null
----------After remove 6:null
----------Return: 5->NULL
--------After remove 6:5->NULL
--------Return: 4->5->NULL
------After remove 6:4->5->NULL
------Return: 3->4->5->NULL
----After remove 6:3->4->5->NULL
----Return: 3->4->5->NULL
--After remove 6:3->4->5->NULL
--Return: 2->3->4->5->NULL
After remove 6:2->3->4->5->NULL
Return: 1->2->3->4->5->NULL
1->2->3->4->5->NULL

三、其他关于链表的问题

  • 双链表
    在这里插入图片描述
    同样也可以使用虚拟头节点来解决。
  • 循环链表,同样可以使用虚拟头节点,令尾节点不指向空,而是指向这个虚拟头节点
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值