1)进行反转单链表:节点的值不发生改变,只需要进行修改节点的指向
进行测试的时候要给方法传入一个头结点
输入:1,2,3,4,5;
输出:5,4,3,2,1;
1)我们先写两个变量,front=head,current=front.next;我们设想一下只用这两个变量是否可以进行反转单链表的操作呢;
我让current.next=front,再让front=current;这是我们就发现current已经无法走到下一个节点了,因为此时current.next已经被修改了,所以我们可以让curNext来进行保存每一次反转操作的current.next的值(这个操作再循环中的第一条语句)
2)循环条件为current.next!=null;
public Node resverse()
{
if(head==null)
{
throw new RuntimeException("链表长度为空");
}
Node front=null;
Node current=head;
Node currentNext=head.next;
while(current!=null)
{ currentNext=current.next;
current.next=front;
front=current;
current=currentNext;
}
return front;
}
2.只遍历单链表一遍,找出链表的中间节点,如果有两个中间节点,那么返回第二个中间节点
输入:1,2,3,4,5,返回:3
输入:1,2,3,4,5,6,返回:4,如果一个链表有两个中间节点,那么我们返回第二个节点
先求出链表的长度,再走count/2步
class Solution {
public ListNode middleNode(ListNode head) {
ListNode current=head;
int count=0;
while(current!=null){
current=current.next;
count++;
}
current=head;
for(int i=0;i<count/2;i++){//当我们的current走到count/2的位置的时候
//恰好已经走到了链表的中间节点
current=current.next;
}
return current;
}
}
思路:快指针速度是慢指针速度的2倍,一个到结尾了,那么另一个就是中间位置:
1)进行快慢指针,我们可以定义一个快慢指针,一开始让fast节点和slow节点都指向head,然后我们指向循环,让fast一次走两步,让slow一次走一步;
奇数节点fast走到最后一步的时候fast.next为空
偶树节点fast走到最后一步的时候fast为空
2)最终slow就是中间节点
我们可以自己画图演示一下,链表长度为奇数或者链表长度是偶数的截至条件是不一样的
public ListNode middleNode(ListNode head) {
ListNode fast=head;
ListNode slow=head;
while(fast!=null&&fast.next!=null)
{
fast=fast.next.next;
slow=slow.next;
}
return slow;
public ListNode middleNode(ListNode head) {
if(head==null){
return null;
}
ListNode fast=head;
ListNode slow=head;
while(true){
if(fast==null||fast.next==null){
return slow;
}
fast=fast.next.next;
slow=slow.next;
}
}
此时那一个判断条件if(fast==null||fast.next==null)必须写在让指针进行移动的前面,因为此时如果连表中只有一个元素的时候,否则会发生空指针异常
第三题:找出链表中的倒数第K个节点,能不能遍历单链表一遍
要找到倒数第K个,要从前向后走len-k步(至少要遍历两遍,因为首先要知道链表的长度);?
1)我们进行定义两个快慢指针,fast为快指针,slow是慢指针,我们先让fast走k-1步
2)然后再让fast和slow同时走;等到fast.next为空的时候(或者说fast走到最后一个节点)
3)并返回slow节点,这时的slow才为倒数第K个节点;
从倒数第三个到倒数第一个 走几步?需要走两步
从倒数第四个到倒数第一个 走几步?需要走三步
从倒数第K个到倒数第一个? 走几步?需要走k-1步
2)更简单的方法是先求出链表的长度,让current走len-k步,但是需要进行遍历单链表现要求出但是链表长度
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
if(k<=0||k>size()){
//必须加上,否则下面的循环会出现空指针异常,再循环走k-1步的时候会发生空指针异常
return null;
}
int count=0;
ListNode current=head;
while(current!=null){
count++;
current=current.next;
}
current=head;
for(int i=0;i<count-k;i++){//当走到count-k的位置的时候,循环退出
current=current.next;
}
return current;
}
}
public Node returnLastK(int index)
{
if(index<0)
{
throw new UnsupportedOperationException("此时的链表的倒数第K个节点位置不正确");
}
if(head==null)
{
throw new UnsupportedOperationException("此时链表长度是空");
}
Node fast=head;
Node slow=head;
for(int i=0;i<index-1;i++)
{ fast=fast.next;
if(fast==null)
{
throw new UnsupportedOperationException("当前你输入的index的值已经超过了链表的长度");
}
}
while(fast.next!=null)
{
fast=fast.next;
slow=slow.next;
}
return slow;
}
4.合并两个有序链表
思路:
1)我们首先定义一个虚拟节点是newHead作为要合并在一起的总链表的新节点,注意它是一个虚拟节点,里面的值是任意的
2)我们再合并headA和headB这两个链表的时候,保存两个链表的右节点是没有什么用处的,如果发现headA.data>headB.data,我们就把HeadA指向的这个头结点放到先开辟的链表后面,同时让headA进行向后移动
? ?if(headA.data>headB.data)
? ? ? {
? ? ? ?}else if(HeadA.data<HeadB.data){
? ?}else{
? ?}
3)再进行合并的过程中,两个链表所走的过程中都不可以是空的,所以循环条件是HeadA!=null&&HeadB!=null
4)在循环出来之后,会出现一种情况,HeadA过长或者HeadB过长,此时我们还要进行特殊处理
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode HeadA=list1;
ListNode HeadB=list2;
ListNode newHead=new ListNode(-1);
ListNode temp=newHead;
while(HeadA!=null&&HeadB!=null)
{
if(HeadA.val<HeadB.val)
{
temp.next=HeadA;
HeadA=HeadA.next;
temp=temp.next;
}else
{
temp.next=HeadB;
HeadB=HeadB.next;
temp=temp.next;
}
}
if(HeadA!=null)
{
temp.next=HeadA;
}
if(HeadB!=null)
{
temp.next=HeadB;
}
return newHead.next;
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode head1=list1;
ListNode head2=list2;
ListNode newHead=new ListNode(-1);
ListNode current=newHead;
while(head1!=null&&head2!=null){
if(head1.val>head2.val){
current.next=head2;
head2=head2.next;
current=current.next;
}else{
current.next=head1;
head1=head1.next;
current=current.next;
}
}
while(head1!=null){
current.next=head1;
head1=head1.next;
current=current.next;
}
while(head2!=null){
current.next=head2;
head2=head2.next;
current=current.next;
}
current.next=null;
return newHead.next;
}
}
下一种写法更推荐
|