链表的题Java(简单到难6道小题)

简介: 链表的题Java(简单到难6道小题)

1.链表逆置很核心的操作很多地方都会用到)

详细讲讲逆置操作,他的想法:之前看了很多遍都没理解,第一次的逆置(不好理解)他是为了将第一个节点指向空,然后后面才是慢慢的逆置链表

class Solution {
    public ListNode reverseList(ListNode head) {
        if(head==null){return null;
        }
        ListNode cur=new ListNode(0);     //我自己设了一个头,有了头会更方便的逆置链表
        cur.next=head;
        head=cur;
        ListNode p=cur.next;
        cur.next=null;
        ListNode q=null;
    while(p!=null){                     //逆置操作
        q=p.next;
        p.next=cur.next;                 
        cur.next=p;
        p=q;
    }
    return head.next;               //很细节的一个点:从头的下一个节点返回,这样就相当于无头
    }
}

2.寻找链表中的中间节点 (核心操作2号,也很重要)

特别重要的一个问题,他会决定你理不理解中间节点

如果奇数的时候:1  2  3  4  5    这串中间节点是几(当奇数时候,奇数是最中间的点

如果偶数的话:1 2 2 1中间节点是几(当偶数的时候中间节点,应该是能把链表均等分成两份的所以是第二个2。这样前面是1,2后面是2,1

好了最大的问题想清楚了就很好处理了。

 public ListNode middleNode(ListNode head) {
    ListNode fast=head;
    ListNode slow=head;          //利用快慢指针
    while(fast!=null&&fast.next!=null){     //条件一定没有fast.next.next!=null
        fast=fast.next.next;
        slow=slow.next;
    }
    return slow;
    }
//循坏的条件,偶数的情况下就应该是第二个2,自己想一想

3.倒数第k个节点 (可能很重要,练习来玩)

想一个问题:链表:1,2,3,4,5。

5个数,倒数第二个是不是正数第4个,倒数第一个,就是正数第五个,换句话说,他给我的正着数+倒着数=总数+1.

第一个解法严格来说O(2N)

 public ListNode FindKthToTail(ListNode head,int k) {
        if(head==null||k<=0){
            return null;
        }
        ListNode cur=head;     
        int a=0;         //a是用来计数,链表一共有几个节点
        int b=0;         //b是用来构成下面的数学关系,正着数第几个
        while(cur!=null){ 
          a++;     
        cur=cur.next;
      }
        cur=head;
       while(cur!=null){
        b++;
       if(k+b==a+1){          //k是第几个数据节点
        break;             //找到就退出呗
    }
       cur=cur.next;
      }
      return cur;
  }
}
第二种算法,O(N),快慢指针他的核心是倒数第K个节点,距离空指针差K个指针,如倒数第二个节点,距离空指针差了K个指针,那也就是说让fast先走k个节点,然后他俩一起走,这样他俩始终距离k,那么fast到了空指针,slow就是我们要求的
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
      if(head==null||k<=0){
            return null;
        }
      ListNode fast=head;
      ListNode slow=head;
     while(k>0){
        if(fast==null){      //快指针先走K步,但不能走过了,要是倒数第6个节点
            return null;    //一共五个点,这种K不合理情况不行
        }
        fast=fast.next;
        k--;
     }
     while(fast!=null){
        slow=slow.next;    //fast和slow 一起走
        fast=fast.next;
     }
     return slow;
}
}

4.合并两个有序链表

public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
            ListNode cur=list1;
            ListNode curv=list2;
            ListNode m=new ListNode(0);      还是创建一个新节点会更方便的插入和删除
            ListNode newb=m;
            if(cur==null&&curv==null){
                return null;
            }
            if(cur==null){
                return curv;
            }
            if(curv==null){
                return cur;
            }
            while(cur!=null&curv!=null){
              if(cur.val<=curv.val){
                  newb.next=cur;    //这里插入节点很容易出错,小于之后,新链表的头连接cur,
                  cur=cur.next;     //cur连接后,cur指针后移
               }else {
                  newb.next=curv;
                  curv = curv.next;
              }
                  newb=newb.next;   //新链表节点后移
            }
              if(cur==null){
                  newb.next=curv;
            }
              if(curv==null){
                  newb.next=cur;
            }
             return m.next;
        }
 }

5.链表回文(微微难)

1.首先,我们要先找中间节点:1,2,3,2,1。中间节点slow为3(如何找看前面的题)

然后以3作为头,将3后面的节点逆置,变成:1,2,3,1,2这样,slow=slow.next后,然后定义一个指针从头遍历,另一个从slow遍历,当slow为空结束

public class PalindromeList {
    public boolean chkPalindrome(ListNode A) {
        if(A==null||A.next==null){
            return true;
        }
        // write code here
        ListNode fast=A;
        ListNode slow=A;
        ListNode now=A;
    while(fast!=null&&fast.next!=null){    //找中间节点
          fast=fast.next.next;
          slow=slow.next;
    }
        ListNode cur=slow;
        ListNode p,q;
        p=cur.next;
        cur.next=null;
    while(p!=null){                  //逆置
          q=p.next;
          p.next=cur.next;
          cur.next=p;
          p=q;
    }
       cur=cur.next;
    while(cur!=null){
      if(now.val!=cur.val){           //重新遍历,是否为回文
          return false; 
    }
         cur=cur.next;
         now=now.next;
    }
       return true;
    }
}

6.链表分割(微微难)   首先我们思路,把整个链表分成两个部分

一个比x小,一个比x大于或者等于,并且如果不改变原来顺序,尾插是最优的选择,

小的要求比大的在前面,然后再将小的表尾连大的链表表头,这也就是为什么要分出四个,表头尾了。

public class Partition {
  public ListNode partition(ListNode pHead, int x) {
        // write code here
     ListNode cur=pHead;
     ListNode sb=null;              //smallbegin小的头
     ListNode bb=null;              //bigbegin大的头
     ListNode be=null;
     ListNode se=null;
     while(cur!=null){
        if(cur.val<x){
           if(sb==null){           //小的部分没有节点,那么需要连上cur
                sb=cur; 
                se=cur;
            }
            else{
                se.next=cur;       //尾插
                se=se.next;
            }
         }else{                    //相等的情况放到大的里面
           if(bb==null){
                 bb=cur;
                 be=cur;
                }
         else{
                 be.next=cur;
                 be=be.next;
          }
            }
        cur=cur.next;
            }
          if(sb==null){           //如果小的那段没有,则直接返回大的那块
             return bb;
            }
        se.next=bb;
          if(bb==null){          //如果大的那段没有,则直接返回小的那部分
             return sb;
            }
        be.next=null;         //这个也很关键最后需要让他指向空
        return sb;           //最后小的那部分是要连接大的那部分
        }
    }

如果最后的be.next=null 不写会导致链表指针指向最后一个节点,这样链表就会有可能变成环,从而对链表的访问结果出现问题


相关文章
|
2月前
|
Java
java数据结构,双向链表的实现
文章介绍了双向链表的实现,包括数据结构定义、插入和删除操作的代码实现,以及双向链表的其他操作方法,并提供了完整的Java代码实现。
java数据结构,双向链表的实现
|
1月前
|
存储 安全 Java
【用Java学习数据结构系列】探索顺序表和链表的无尽秘密(附带练习唔)pro
【用Java学习数据结构系列】探索顺序表和链表的无尽秘密(附带练习唔)pro
23 3
|
5月前
|
Java
环形数组链表(java)
环形数组链表(java)
|
3月前
|
存储 Java
|
3月前
|
存储 Java
java实现单链表的创建、增、删、改、查
这篇文章详细介绍了Java中如何实现单链表的创建以及对单链表进行增加、删除、修改、查询等操作的方法,并提供了相应的代码示例。
java实现单链表的创建、增、删、改、查
|
3月前
|
存储 Java 开发者
揭秘!HashMap底层结构大起底:从数组到链表,再到红黑树,Java性能优化的秘密武器!
【8月更文挑战第24天】HashMap是Java集合框架中的核心组件,以其高效的键值对存储和快速访问能力广受开发者欢迎。在JDK 1.8及以后版本中,HashMap采用了数组+链表+红黑树的混合结构,实现了高性能的同时解决了哈希冲突问题。数组作为基石确保了快速定位;链表则用于处理哈希冲突;而当链表长度达到一定阈值时,通过转换为红黑树进一步提升性能。此外,HashMap还具备动态扩容机制,当负载因子超过预设值时自动扩大容量并重新哈希,确保整体性能。通过对HashMap底层结构的深入了解,我们可以更好地利用其优势解决实际开发中的问题。
101 0
|
3月前
|
存储 Java
【Java集合类面试十】、HashMap中的循环链表是如何产生的?
在多线程环境下,HashMap在扩容时如果发生条件竞争,元素的插入顺序可能形成循环链表,导致死循环。
|
3月前
|
存储 Java
java实现双向链表的增删改查
这篇文章展示了如何在Java中实现双向链表的增加、删除、修改和查询操作,并通过代码示例演示了在双向链表中存储和操作学生信息的过程。
|
3月前
|
算法 Java
LeetCode初级算法题:环形链表+排列硬币+合并两个有序数组java解法
LeetCode初级算法题:环形链表+排列硬币+合并两个有序数组java解法
54 0
|
3月前
|
存储 算法 Java
LeetCode初级算法题:反转链表+统计N以内的素数+删除排序数组中的重复项Java详解
LeetCode初级算法题:反转链表+统计N以内的素数+删除排序数组中的重复项Java详解
44 0