nowcoder--牛客题霸模板速刷101

目录

BM12 单链表的排序

描述

         算法思想:归并排序(递归)

         解题思路:

 BM13 判断一个链表是否为回文结构

描述

                  方法一

         思路

         具体步骤

                  方法二

          思路

BM14 链表的奇偶重排

描述

 BM15 删除有序链表中重复的元素

描述


BM12 单链表的排序

  • 题目
  • 题解(265)
  • 讨论(245)
  • 排行
  • 面经

    new

中等  通过率:47.96%  时间限制:2秒  空间限制:256M

知识点链表排序

描述

给定一个节点数为n的无序单链表,对其按升序排序。

数据范围:0≤1000000

要求:空间复杂度 O(n),时间复杂度 O(nlogn)

nowcoder--牛客题霸模板速刷101_第1张图片

 主要思想:递归

算法思想:归并排序(递归)

解题思路:

主要通过递归实现链表归并排序,有以下两个环节:

1、分割 cut 环节: 找到当前链表中点,并从中点将链表断开(以便在下次递归 cut 时,链表片段拥有正确边界);

    使用 fast,slow 快慢双指针法,奇数个节点找到中点,偶数个节点找到中心左边的节点。
    找到中点 slow 后,执行 slow.next = None 将链表切断。
    递归分割时,输入当前链表左端点 head 和中心节点 slow 的下一个节点 tmp(因为链表是从 slow 切断的)。
    cut 递归终止条件: 当head.next == None时,说明只有一个节点了,直接返回此节点

2、合并 merge 环节: 将两个排序链表合并,转化为一个排序链表。
    双指针法合并,建立辅助ListNode h 作为头部。
    设置两指针 left, right 分别指向两链表头部,比较两指针处节点值大小,由小到大加入合并链表头部,指针交替前进,直至添加完两个链表。
    返回辅助ListNode h 作为头部的下个节点 h.next。
    时间复杂度 O(l + r),l, r 分别代表两个链表长度。
3、特殊情况,当题目输入的 head == None 时,直接返回None。

图解:

nowcoder--牛客题霸模板速刷101_第2张图片

/**
 * @author Diana
 * @date 2023/6/21 9:37
 */
public class SortInList {
     public ListNode sortInList(ListNode head){
         if(head == null || head.next == null)
             return head;
         ListNode fast = head.next,slow = head;
        while(fast != null && fast.next != null){
            slow = slow.next;
            fast = fast.next.next;
        }
        ListNode tmp =slow.next;
        slow.next = null;
        ListNode left = sortInList(head);
        ListNode right = sortInList(tmp);
        ListNode h = new ListNode(0);
         ListNode res = h;
        while(left != null && right != null) {
        if(left.val < right.val ){
        h.next = left;
        left = left.next;}else{
            h.next = right;
            right = right.next;
        }
        h = h.next;
        }
        h.next = left != null ? left : right;
        return res.next;
     }

}

BM13 判断一个链表是否为回文结构

知识点 链表双指针

描述

给定一个链表,请判断该链表是否为回文结构。

回文是指该字符串正序逆序完全一致。

nowcoder--牛客题霸模板速刷101_第3张图片

方法一

思路

因为需要判断是否为回文结构,所以要比较头尾的数据,而链表无法随机查询数据,所以可以先将链表转换成list。

具体步骤

  • 首先初始化一个list列表;

  • 遍历链表,将链表中的值转移至list中;

  • 在list中通过比较头尾的值来判断链表是否为回文结构。

  • 时间复杂度:,两次遍历;

  • 空间复杂度:O(n),列表存储数据需要的size为n。

import java.util.ArrayList;
import java.util.List;

/**
 * @author Diana
 * @date 2023/6/21 9:57
 */
public class IsPail {
   public boolean isPail(ListNode head){
       if(head.next == null){
           return true;
       }
       List nums = new ArrayList();
       while(head != null){
           nums.add(head.val);
           head=head.next;
       }
       int i = 0;
       int j = nums.size() - 1;
       while(i < j){
           if(!nums.get(i).equals(nums.get(j))){
               return false;
           }
           ++i;
           --j;
       }
       return true;
   }
}

方法二

思路

方法一的空间复杂度为O(n),较大,可以使用快慢指针,快指针的速度为慢指针的两倍,当快指针到达链表尾部时,慢指针到达中间位置,将慢指针之后的部分进行反转,再与前半部分进行比较。

  • 时间复杂度:O(n),遍历链表

  • 空间复杂度:常数级空间复杂度O(1)

nowcoder--牛客题霸模板速刷101_第4张图片

import java.util.*;

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 *   public ListNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param head ListNode类 the head
     * @return bool布尔型
     */
    public boolean isPail (ListNode head) {
        // write code here
    ListNode q= head, p= head;
  //通过快慢指针找到中点
  while (q != null && q.next != null) {
      q = q.next.next;
      p = p.next;
  }
  //如果q不为空,说明链表的长度是奇数个
  if (q != null) {
      p = p.next;
  }
  //反转后半部分链表
  p = reverse(p);
 
  q = head;
  while (p != null) {
      //然后比较,判断节点值是否相等
      if (q.val != p.val)
          return false;
      q = q.next;
      p = p.next;
  }
  return true;
}
//反转链表
public ListNode reverse(ListNode head) {
  ListNode prev = null;
  while (head != null) {
      ListNode next = head.next;
      head.next = prev;
      prev = head;
      head = next;
  }
  return prev;
}
}

BM14 链表的奇偶重排

知识点链表排序

描述

给定一个单链表,请设定一个函数,将链表的奇数位节点和偶数位节点分别放在一起,重排后输出。注意是节点的编号而非节点的数值。

具体做法:

  • step 1:判断空链表的情况,如果链表为空,不用重排。
  • step 2:使用双指针odd和even分别遍历奇数节点和偶数节点,并给偶数节点链表一个头。
  • step 3:上述过程,每次遍历两个节点,且even在后面,因此每轮循环用even检查后两个元素是否为NULL,如果不为再进入循环进行上述连接过程。
  • step 4:将偶数节点头接在奇数最后一个节点后,再返回头部。

要求:空间复杂度 O(n),时间复杂度 O(n)

nowcoder--牛客题霸模板速刷101_第5张图片

import java.util.*;
public class Solution {
    public ListNode oddEvenList (ListNode head) {
        //如果链表为空,不用重排
        if(head == null) 
            return head;
        //even开头指向第二个节点,可能为空
        ListNode even = head.next; 
        //odd开头指向第一个节点
        ListNode odd = head; 
        //指向even开头
        ListNode evenhead = even; 
        while(even != null && even.next != null){
            //odd连接even的后一个,即奇数位
            odd.next = even.next; 
            //odd进入后一个奇数位
            odd = odd.next; 
            //even连接后一个奇数的后一位,即偶数位
            even.next = odd.next; 
            //even进入后一个偶数位
            even = even.next; 
        } 
        //even整体接在odd后面
        odd.next = evenhead; 
        return head;
    }
}

 BM15 删除有序链表中重复的元素

描述

删除给出链表中的重复元素(链表中元素从小到大有序),使链表中的所有元素都只出现一次
例如:
给出的链表为1→1→21→1→2,返回1→21→2.
给出的链表为1→1→2→3→31→1→2→3→3,返回1→2→31→2→3.

进阶:空间复杂度 O(1),时间复杂度 O(n)

import java.util.*;

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 * }
 */

public class Solution {
    /**
     * 
     * @param head ListNode类 
     * @return ListNode类
     */
    public ListNode deleteDuplicates (ListNode head) {
        // write code here
        if (head == null || head.next == null){
            return head;
        }
        ListNode q = head;
        while(q != null) {
            int cache = q.val;
            ListNode p = q.next;
            while(p != null && p.val == cache) {
                p = p.next;
            }
            q.next = p;
            q = p;
        }
        return head;
    }
}

你可能感兴趣的:(点子的刷题记录,算法,java)