【算法与数据结构复习】| 链表类

        今天跟着左程云算法课007-012,07和08讲了【时空复杂度】和【算法与数据结构的概念】,简单复习了一下。重点在于009-012课程链表类题目的学习。总结记录一下,以下是单链表结点的通用代码:

	//单链表节点
	public static class ListNode{
		public int val;
		public ListNode nextListNode;
		
		public ListNode(int n) {
			this.val=n;
		}
		public ListNode(int n,ListNode next) {
			this.val=n;
			this.nextListNode=next;
		}
	}

一、单链表和双链表的逆置

(1)单链表逆置

        链表逆置是链表类最基础的算法。head头结点要移动,除了head指向当前结点之外,要另外设置两个变量pre和next分别指向当前结点的前一个结点和后一个结点。

	public static ListNode ListReverse(ListNode head) {
		ListNode pre=null;
		ListNode next=null;
		
		while(head!=null) {
			next=head.nextListNode;
			head.nextListNode=pre;
			pre=head;
			head=next;
		}
		
		return pre;
	}

(2)双链表的逆置

        双链表的逆置和单链表逆置思路一样,只是在当年节点的next变动时要pre和next一起变动,思路和上述的单链表逆置一模一样。

	//双链表节点
	public static class DoubleListNode{
		public int val;
		public DoubleListNode pre;
		public DoubleListNode next;
		
		public DoubleListNode(int n) {
			this.val=n;
		}
		
		public DoubleListNode(int n, DoubleListNode pre, DoubleListNode next) {
			this.val=n;
			this.pre=pre;
			this.next=next;
		}
	}
	
	//逆置双链表
	public static DoubleListNode reverDoubleListNode(DoubleListNode head) {
		DoubleListNode pre=null;
		DoubleListNode next=null;
		while(head!=null) {
			next=head.next;
			head.next=pre;
			head.pre=next;
			pre=head;
			head=next;
		}
		return pre;
	}

二、有序链表的合并

        对于有序链表的合并,进行边缘条件判定之后,比较两个链表头结点大小,然后将返回的head指向小头,这里的head之后不变,用于返回合并链表的头。之后设置一个cur指向合并链表的最后一个结点(也就是说只要有一个结点兜进来,就用cur指向这个结点),分别用cur1和cur2在两个链表上移动。比较cur1和cur2的大小,哪个小哪个链到cur后面,直到其中一个链表走完。走完后接着把没链上的链进来,然后返回最开的head结点。

        代码测试链接:. - 力扣(LeetCode)

	public static ListNode MergeList(ListNode h1,ListNode h2) {
		
		if(h1==null||h2==null) {
			return h1==null?h2:h1;
		}
		ListNode head=h1.val>h2.val?h2:h1;
		ListNode cur=head;
		ListNode cur1=h1.val>h2.val?h1:h1.next;
		ListNode cur2=h1.val>h2.val?h2.next:h2;
		
		while(cur1!=null && cur2!=null) {
			if(cur1.val<cur2.val) {
				cur.next=cur1;
				cur1=cur1.next;
				
			}
			else {
				cur.next=cur2;
				cur2=cur2.next;
			}
			
			cur=cur.next;
		}
		
		if(cur1!=null || cur2!=null) {
			cur.next= cur1==null?cur2:cur1;
		}
		
		return head;
		
	}

三、两个链表相加

        对于两个链表相加,要返回的数据类型也是NodeList,所以要重开一个链表来存储相加结果,用ans返回结果链表头,用cur来指向结果链表尾。写一个循环开始加,循环条件是h1或h2不为空即可。相加得到sum的时候要把h1、h2和carry都考虑上,加出来的结果处理后往结果链表放。代码如下。

        代码测试链接:. - 力扣(LeetCode)

	public static ListNode AddTwoNumbers(ListNode h1,ListNode h2) {
		ListNode ans=null,cur=null;
		int carry=0;
		for(int sum,val;
				h1!=null||h2!=null;
				h1= h1==null?null:h1.next,
				h2= h2==null?null:h2.next) {
			sum=(h1==null?0:h1.val)+(h2==null?0:h2.val)+carry;
			val=sum%10;
			carry=sum/10;
			
			if(ans==null) {
				ans=new ListNode(val);
				cur=ans;
			}
			else {
				cur.next=new ListNode(val);
				cur=cur.next;
			}
			
		}
		
		if(carry==1) {
			cur.next=new ListNode(1);
		}
		return ans;
		
	}

四、链表划分

        这个题目要以x为分界点,分成左右两个区域。那么我们就设置4个变量,分别是smallHead,smallTail,表示小头和小尾。bigHead和bigTail,表示大头和大尾。然后设置一个cur,我们在对于当下节点head的时候,用cur指向head.next,然后后面发货的时候把head.next断开,方便当前head发货完还能接着原来的顺序往后遍历继续走。思路很简单,head拿到一个数,判断然后发货,发往大区或者小区。最后要注意判断一下小区里面是否有元素存在,如果没有直接返回大头,如果有元素的话,把小尾和大头连接起来然后返回小头。代码如下:

        代码测试链接:. - 力扣(LeetCode)

	public static ListNode PartList(ListNode head,int x) {
		
		ListNode smallHead=null,smallTaiListNode=null;
		ListNode bigHead=null,bigTaiListNode=null;
		ListNode cur=null;
		
		if(head==null) {
			return null;
		}
		
		while(head!=null) {
			cur=head.next;
			head.next=null;
			//发货
			if(head.val<x) {
				//发货给小区
				if(smallHead==null) {
					smallHead=head;
				}
				else {
					smallTaiListNode.next=head;
					
				}
				smallTaiListNode=head;
			}
			else {
				//发货给大区
				if(bigHead==null) {
					bigHead=head;
				}
				else{
					bigTaiListNode.next=head;
				}
				
				bigTaiListNode=head;
				
			}
			
			head=cur;
		}
		
		if(smallHead==null) {
			return bigHead;
		}
		else {
			smallTaiListNode.next=bigHead;
			return smallHead;
		}
		
		
	}
  • 18
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值