链表相关题目

今天又是元气满满的一天,加油

涉及leecode题目

目录

92. 反转链表 II

25.k个一组翻转链表

234.回文链表



1、递归反转整个链表

了解链表的基础知识后再来看这个反转链表,真的很有意思,嗯,数据结构感兴趣有动力就变得容易理解了哦

根据作者的思路,这种递归的题目不能用传统方法,在脑子里debug,一层一层肯定晕掉了,需要有整体的思维。

ListNode reverse(ListNode head){
    if(head.next == null){
        return head;
    }
    
    ListNode last = reverse(head.next);
    
    //很神奇将链表两个节点指向关系翻转
    head.next.next = head;
    head.next = null;
    
    return last;
}

2、实现翻转前N个节点

ListNode successor = null;
ListNode reverseN(LiseNode head, int n){
    if(n==1){
        successor = head.next;
        return head;
    }
    
    ListNode last = reverseN(head.next,n-1);
    
    head.next.next = head;
   //翻转递归最后一步,将第n个节点后面的部分连接到第一个节点以后
     head.next = successor;
    
    return last;
}

3、翻转链表的一部分

这个题真的太难理解了,上一个还好,这个题是基于上一个的,我是这样理解:

ListNode reverseBetwween(ListNode head, int m,int n){
    //这里巧妙的把区间的概念(m,n)转化为上一题前n个翻转的问题,
    //head在这里已经不再是表头
    if(m==1){
        return reverseN(head,n);
    }
    //这里分为两部分理解,等号前面其实相当于不发生反转的部分向后索引
    //等号后面便是递归,找到需要翻转的链表部分的“head”,这里是由n这个数来控制
    head.next = reverseBetween(head.next,m-1,n-1);
    return head;
}

实战练习

92. 反转链表 II

class Solution {

    ListNode tempNode = null;

    public ListNode reverseN(ListNode head, int n){
      if(n==1){
        tempNode = head.next;
        return head;
      }

      ListNode last = reverseN(head.next, n-1);
       
      head.next.next = head;
      head.next = tempNode;

      return last;
    }

    public ListNode reverseBetween(ListNode head, int left, int right) {
        if(left==1){
        return reverseN(head,right);
        }

        head.next = reverseBetween(head.next,left-1,right-1);
        return head;

        }
    }

25.k个一组翻转链表

这道题没做过翻转链表相关题目的话实在不好想

看了题解之后,分解开来理解如下:

首先k个一组翻转,每组内部翻转需要一个方法,参数为链表中两个节点[a,b),返回的是每组b之前的节点;

然后需要构造a和b,通过for循环去做

class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {

        if(head == null){
            return null;
        }

        ListNode a, b;
        a=b = head;
        for(int i=0;i<k;i++){
            if(b==null){
                return head;
            }
            b=b.next;
        }
        ListNode newHead = reverse(a,b);
        a.next=reverseKGroup(b,k);
        return newHead;
    }

    public ListNode reverse(ListNode a,ListNode b){
        ListNode pre, cur,nxt;

        pre = null;
        cur=a;
        nxt = a;

        while(cur!=b){
          nxt = cur.next;
          cur.next = pre;
          pre = cur;
          cur = nxt;
        }

        return pre;
    }
}

234.回文链表

通过双指针的思路可以如以下方法:

它是用递归,然后有别于以前我做递归一层一层处理的思路,用的是每层递归做类似缓存的操作,每层操作拿到对应的递归栈中的数据做对比,真的震到我了,想不到还能这样做题:

class Solution{
    ListNode left;
    public boolean isPalindrome(ListNode head){
        left = head;
        return traverse(head);
    }
    
    boolean traverse(ListNode right){
        if(right ==null){
            return true;
        }
        
        boolean res = traverse(right.next);
        
        res = res&&(right.val==left.val);
        left = left.next;
        return res;
    }
}

这个题是做出来了,但是空间复杂度有点高,回文判断嘛,不需要每个节点都过一遍。

优化空间复杂度

在这里又学到一个新技巧:快慢指针!

ListNode slow,fast;
slow = fast = head;
while(fast!=null&&fast.next!=null){
    slow =slow.next;
    fast = fast.next.next;
    
}

这两个节点就像赛跑一样,通过循环中的条件可以看出结果无非两种,fast指向null与否。

这样子写的作用是判断链表长度是奇数还是偶数。

若是fast没有指向null,说明链表是奇数,这样slow还要再前进一步

 

最后就可以比较回文串了

题解:

class Solution {
    public boolean isPalindrome(ListNode head) {
        ListNode slow,fast;
        slow= fast=head;
        while(fast!=null&&fast.next!=null){
            slow = slow.next;
            fast= fast.next.next;
        }
        if(fast!=null){
            slow=slow.next;
        }

        ListNode left = head;
        ListNode right = reverse(slow);

        while(right !=null){
            if(left.val != right.val){
                return false;
            }
            left = left.next;
            right = right.next;
        }
     
     return true;

    }
        ListNode reverse(ListNode a){
            ListNode pre = null,cur = a;

            while(cur!=null){
                ListNode nxt = cur.next;
                cur.next = pre;
                pre = cur;
                cur = nxt;
            }
            return pre;
        }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿星_Alex

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值