链表算法题小结

一 打印两个有序链表的公共部分

给定两个有序链表的头指针head1和head2,打印两个链表的公共部分。

package 打印链表公共部分;//有序链表
public class Node {
      public int info;
      public Node link;
      public Node(int data){
    	  this.info=data;
      }
      public void printNode(Node head1,Node head2){
    	  while(head1!=null&&head2!=null){
    		  //如果head1的值小于head2,则head1往下移动
    		  if(head1.info<head2.info){
    			  head1=head1.link;
    		  }
    		  //如果head2的值小于head1,则head2往下移动
    		  else if(head1.info>head2.info){
    			  head2=head2.link;
    		  }
    		  //若二者的值相等,则打印出来,并将head1和head2都往下移动
    		  else{
    			  System.out.println(head1.info);
    			  head1=head1.link;
    			  head2=head2.link;
    		  }
    	  }
      }
}

二 删除单链表中倒数第K个节点

实现一个函数,可以删除单链表中倒数第K个节点

package 删除倒数第K个节点;
public class Node {
	public int value;
	   public Node next;
	   public Node cur;
	   public Node(int data){
		   this.value=data;
	   }
	   public void printNode(Node head,int k){
		   cur=head;
		   //while循环结束时,若k大于0,则说明不存在倒数第k个数
		   while(cur!=null){
			   cur=cur.next;
			   k--;
		   }
		   if(k<=0){
			   //k=0说明k等于链表的节点数
			   if(k==0){head=head.next;}
			   else{
				   cur=head;
				   //++k=0时,cur恰好代表要删除的节点的前一个节点
				   while(++k!=0){
					   cur=cur.next;
				   }
				   cur.next=cur.next.next;
			   }
		   }
	   }
	  
}

三 删除链表的中间节点

实现一个函数,删除链表中间节点,例如

1 不删除任何节点

1→ 2删除节点1

1→ 2→ 3删除节点2

1→ 2→ 3→ 4删除节点2

1→2→3→4→ 5删除节点3

package 删除链表中间节点;
public class Node {
      public int value;
      public Node next;
      public Node(int data){
    	  this.value=data;
      }
      //head为首节点,num为节点数
      public void removeMid(Node head,int num){
    	  Node cur=head;
    	  //找到中心节点的位置
    	  if(num==1)return;
    	  else if(num==2)head=null;
    	  else if(num%2==1)num=(num+1)/2;
    	  else num=num/2;
    	  while(num>2){
    		  cur=cur.next;
    		  num--;
          }
    	  cur.next=cur.next.next;
    	  
      }
}<strong>
</strong>

四 反转单向链表

实现反转单向链表的函数

package 反转单向链表;
public class Node {
     public int value;
     public Node link;
     public Node(int data){
    	 this.value=data;
     }
     public void reverseList(Node head){
    	 Node p1=head;
    	 Node p2=head.link;
    	 Node p3=null;
    	 while(p2!=null){
    		 p3=p2.link;//保留p2.link以便下次循环用
    		 p2.link=p1;//将p1赋给p2.link,链表反转,p2.link将指向p1
    		 /*
    		  * p2赋给p1
    		  * p3赋给p2
    		  * 循环后移一位
    		  */
    		 p1=p2;
    		 p2=p3;
    	}
    	 //重新定义头节点
    	 head=p1;
     }
}

五 环形单链表的约瑟夫问题

约瑟夫环的相关问题,可参照我的另一篇博客约瑟夫环问题详述

输入:一个环形单链表头节点head和报数的值num

返回:最后生存下来的节点,且这个节点自己组成环形单链表,其他节点都删掉

package 环形单链表的约瑟夫问题;
/*
 * 没删除一个节点,都要遍历m次,一共需要删除的节点数为n-1,
 * 故该解法的时间复杂度为O(n×m)
 */
public class Node {
      public int value;
      public Node next;
      public Node(int data){
    	  this.value=data;
      }
      public Node killOne(Node head,int num){
    	  if(head==null||head.next==head||num<1){
    		  return head;
    	  }
    	  Node last=head;
    	  //while语句将last引用指向head节点的前一个节点
    	  while(last.next!=head){
    		  last=last.next;
    	  }
    	  int count=0;
    	  while(last!=head){
    		  if(++count==num){
    			  last.next=head.next;//head.next此时相当于last.next.next,起到删除节点的作用
    			  count=0;
    		  }else{
    			  last=last.next;//last引用的指向向后移动
    		  }
    		  head=last.next;//head引用始终指向last节点的下一个节点
    		  
    	  }
		  return head;
      }
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值