首页 > 编程语言 >02链表算法/代码随想录

02链表算法/代码随想录

时间:2024-11-01 10:50:09浏览次数:3  
标签:02 head ListNode temp 随想录 next 链表 null 节点

  • 前几天忙比赛,算法停了三天,继续开刷,不能停!!

二、链表

2.1删除链表中的元素

两种方案

  1. 无哨头:要删除节点的前一个结点指向删除节点的指向节点。头节点需要单独定义

  2. 有哨头:头节点不需要单独定义

    • 实战

      力扣203

      外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

      /**
       * Definition for singly-linked list.
       * public class ListNode {
       *     int val;
       *     ListNode next;
       *     ListNode() {}
       *     ListNode(int val) { this.val = val; }
       *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
       * }
       */
      class Solution {
          public ListNode removeElements(ListNode head, int val) {
              ListNode current = new ListNode(0);
              current.next = head;
              ListNode temp = current;
              while (temp.next != null) {
                  if (temp.next.val == val) {
                      temp.next = temp.next.next;
                  }
                  else {
                      temp = temp.next;
                  }
              }
              return current.next;
          }
      }
      
    • 使用哨头,只需定义删除方法要删除节点的前一个结点指向删除节点的指向节点即可。

2.2实现单向链表
  1. 链表的crud

    • 实战

      力扣707

      外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

      class MyLinkedList {
          ListNode vhead;
          int size;
      
          public MyLinkedList() {
              vhead = new ListNode(0);
              size = 0;
          }
          
          public int get(int index) {
              if (index < 0 || index >= size) {
                  return -1;
              }
              ListNode temp = vhead;
              for (int i = 0; i <= index; ++i) {
                  temp = temp.next;
              }
              return temp.val;
          }
          
          public void addAtHead(int val) {
              ListNode temp = new ListNode(val);
              temp.next = vhead.next;
              vhead.next = temp;
              size++;
          }
          
          public void addAtTail(int val) {
              ListNode temp = vhead;
              for (int i = 0; i < size; ++i) {
                  temp = temp.next;
              }
              ListNode t = new ListNode(val);
              temp.next = t;
              size++;
          }
          
          public void addAtIndex(int index, int val) {
              if (index > size || index < 0) {
                  return;
              }
              ListNode temp = vhead;
              for (int i = 0; i < index; ++i) {
                  temp = temp.next;
              }
              ListNode t = new ListNode(val);
              t.next = temp.next;
              temp.next = t;
              size++;
          }
          
          public void deleteAtIndex(int index) {
              ListNode temp = vhead;
              if (index < 0 || index >= size) {
                  return;
              }
              else {
              for (int i = 0; i < index; ++i) {
                  temp = temp.next;
              }
              temp.next = temp.next.next;
              size--;
              }
          }
      }
      
    • 我是用头哨实现的,是一个虚拟节点,注意形参和实际参数的区别,需要做转换,链表内部index:0是虚拟节点不允许访问,外部访问index:0,其实就是访问index:1的节点

2.3双指针法
  1. 翻转链表

    • 实战

      力扣206

      外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

      迭代法

      class Solution {
          public ListNode reverseList(ListNode head) {
              ListNode prev = null;
              ListNode curr = head;
              while (curr != null) {
                  ListNode next = curr.next;
                  curr.next = prev;
                  prev = curr;
                  curr = next;
              }
              return prev;
          }
      }
      
    • 此解较为常见,链表题最重要的是(我是谁、我下一个节点是谁、我上一个节点是谁),在修改当前节点的next指针的时候,注意存储以防断链

      递归法(递归其实就是后一项依靠前一项,这里依靠的是翻转后头节点)

      此题递归需要传递的点就是反转后的头节点,此解法采用先返回反转后头节点再翻转。要注意递归传递的是翻转头节点,不是当前节点是下一个节点,因为链表本身就具有记忆的能力,把这个当作传递点会很多余。而无法传递的是翻转后头节点,所以传递它

      class Solution {
          public ListNode reverseList(ListNode head) {
              if (head == null || head.next == null) {
                  return head;
              }
              ListNode newNode = reverseList(head.next);
              head.next.next = head;  // 翻转
              head.next = null;       // 将原来的链接置空
              return newNode;
          }
      }
      
      class Solution {
          public ListNode reverseList(ListNode head) {
              return reverse(null, head);
          }
      
          private ListNode reverse(ListNode prev, ListNode cur) {
              if (cur == null) {
                  return prev;
              }
              ListNode temp = null;
              temp = cur.next;// 先保存下一个节点
              cur.next = prev;// 反转
              return reverse(cur, temp);
          }
      }
      
  2. 两两交换链表中的节点

    • 实战

      力扣

      外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

      双指针+虚拟头节点

      class Solution {
          public ListNode swapPairs(ListNode head) {
              ListNode vhead = new ListNode(0);
              vhead.next = head;
              ListNode slow;  // 不提前赋值,防止空链表需要额外判断
              ListNode fast;
              ListNode temp = vhead;
              while(temp.next != null && temp.next.next != null) {
                  slow = temp.next;  // 通过temp赋值,也减少循环判断
                  fast = temp.next.next;
                  slow.next = fast.next;
                  fast.next = slow;
                  temp.next = fast;
                  temp = slow;
              }
              return vhead.next;
          }
      }
      
    • 交换节点需要三步,slow指向fast.next,fast指向slow,temp指向temp,这个时候交换好了,但是需要跳转然后继续交换,这里体现了虚拟头节点的好处,跳转后交换,fast要与前一个交换后的slow相连接,这里就可以通过虚拟头节点代替。

    • 递归(这里递归传递的是后两个节点,因为头节点一开始交换后就可以确定)

      class Solution {
          public ListNode swapPairs(ListNode head) {
              if(head == null || head.next == null) return head;
              // 获取当前节点的下一个节点
              ListNode next = head.next;
              // 进行递归
              ListNode newNode = swapPairs(next.next);
              // 这里进行交换
              next.next = head;
              head.next = newNode;
      
              return next;
          }
      } 
      
  3. 删除链表的第N个节点

    • 实战

      力扣19

      外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

      典型的双指针,让快指针走n步,然后快慢指针同时走,快指针走到最后一个节点,慢指针就到了要删除节点的前一个节点

      class Solution {
          public ListNode removeNthFromEnd(ListNode head, int n) {
              ListNode vhead = new ListNode(0);
              vhead.next = head;
              ListNode fastPtr = vhead;
              ListNode slowPtr = vhead;
              for (; n > 0; --n) {
                  fastPtr = fastPtr.next;
              }
              while (fastPtr.next != null) {
                  fastPtr = fastPtr.next;
                  slowPtr = slowPtr.next;
              }
              slowPtr.next = slowPtr.next.next;
              return vhead.next;
          }
      }
      
  4. 链表相交

    • 实战

      力扣160

      外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

      长的链表的起始部分短的链表一定不包含,第一步就是剪切那一部分,然后进行一一比对,如果节点相等说明相交

      /**
       * Definition for singly-linked list.
       * public class ListNode {
       *     int val;
       *     ListNode next;
       *     ListNode(int x) {
       *         val = x;
       *         next = null;
       *     }
       * }
       */
      public class Solution {
          public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
              int num_A = 0;
              int num_B = 0;
              ListNode skipA = headA;
              ListNode skipB = headB;
              while (headA != null){
                  headA = headA.next;
                  num_A++;
              }
              while (headB != null){
                  headB = headB.next;
                  num_B++;
              }
              if (num_A >= num_B) {
                  int m = num_A - num_B;
                  for (int i = 0; i < m; i++) {
                      skipA = skipA.next;
                  }
                  while (skipA != null) {
                      if (skipA == skipB) {
                          return skipA;
                      }
                      else {
                          skipA = skipA.next;
                          skipB = skipB.next;
                      }
                  }
              }
              else {
                  int m = (num_A - num_B) * -1;
                  for (int i = 0; i < m; i++) {
                      skipB = skipB.next;
                  }
                  while (skipA != null) {
                      if (skipA == skipB) {
                          return skipA;
                      }
                      else {
                          skipA = skipA.next;
                          skipB = skipB.next;
                      }
                  }
              }
              return null;
          }
      }
      
    • 这里直接调HashSet表,去重复,更容易

      public class Solution {
          public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
              Set<ListNode> visited = new HashSet<ListNode>();
              ListNode temp = headA;
              while (temp != null) {
                  visited.add(temp);
                  temp = temp.next;
              }
              temp = headB;
              while (temp != null) {
                  if (visited.contains(temp)) {
                      return temp;
                  }
                  temp = temp.next;
              }
              return null;
          }
      }
      
  5. 环形链表

    • 实战

      力扣142

      外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

      哈希表秒杀

      public class Solution {
          public ListNode detectCycle(ListNode head) {
              ListNode pos = head;
              Set<ListNode> visited = new HashSet<ListNode>();
              while (pos != null) {
                  if  (visited.contains(pos)) {
                      return pos;
                  } else {
                      visited.add(pos);
                  }
                  pos = pos.next;
              }
              return null;
          }
      }
      

      双指针写法,慢指针每次走一步,快指针每次走两步,如果有环,那么一定会相遇,因为当慢指针到环的时候,快制作一定到了,这个时候相当于快指针追慢指针,每次挪一步,一定会追到。而且慢指针一定不会走满一圈。举例,在极限位置再过一点不符合条件,就是当满指针刚进环的时候,两指针就相遇了,这个时候先不算,由于快指针是慢指针的两倍速,所以最多再经历完一圈快指针追上慢指针,而这种实际不可能,快指针会更快一步。

      public class Solution {
          public ListNode detectCycle(ListNode head) {
              ListNode fast = head;
              ListNode slow = head;
              ListNode index1 = head;
              while (fast != null && fast.next != null) {
                  fast = fast.next.next;
                  slow = slow.next;
                  if (slow == fast) {
                      ListNode index2 = slow;
                      while (index2 != index1) {
                          index1 = index1.next;
                          index2 = index2.next;
                      }
                      return index1;
                  }
              }
              return null;
          }
      }
      

标签:02,head,ListNode,temp,随想录,next,链表,null,节点
From: https://blog.csdn.net/2403_86942375/article/details/143275436

相关文章

  • Autodesk Maya 2025.3 Multilanguage (macOS, Windows) - 三维动画和视觉特效软件
    AutodeskMaya2025.3Multilanguage(macOS,Windows)-三维动画和视觉特效软件三维计算机动画、建模、仿真和渲染软件请访问原文链接:https://sysin.org/blog/autodesk-maya/查看最新版。原创作品,转载请保留出处。作者主页:sysin.org三维计算机动画、建模、仿真和渲染软件......
  • Autodesk AutoCAD 2025.1 (macOS, Windows) - 自动计算机辅助设计软件
    AutodeskAutoCAD2025.1(macOS,Windows)-自动计算机辅助设计软件AutoCAD2024开始原生支持AppleSilicon请访问原文链接:https://sysin.org/blog/autodesk-autocad/查看最新版。原创作品,转载请保留出处。作者主页:sysin.org具有设计自动化以及工具组合、Web和移动应......
  • Adobe Creative Cloud 2025 (macOS, Windows) 下载汇总 - 创意应用程序
    AdobeCreativeCloud2025(macOS,Windows)下载汇总-创意应用程序Acrobat、AfterEffects、Animate、Audition、Bridge、CharacterAnimator、Dimension、Dreamweaver、Illustrator、InCopy、InDesign、LightroomClassic、MediaEncoder、Photoshop、PremierePro、AdobeX......
  • SS02-0B00-00 Broadcom 华创峰业
    SS02-0B00-00是Broadcom公司的PEX88000系列ManagedPCIe4.0Switches中的一个型号。以下是该产品的一些关键参数和特性:PCIe4.0支持:支持PCIe4.0r1.0标准。嵌入式ARMCPU:用于管理的嵌入式ARMCPU。ExpressFabric®PCIe交换架构:支持ExpressFabric®架构......
  • 【2024-10-31】考虑装修
    20:00我们现在走的是一条人迹罕至的路,但是我爱这条路。如果荆棘丛生,就披荆斩棘;如果它寂寞荒凉,我们就结伴前行。                                                 ——王......
  • T533810 [SXZOI 2024 C] 典
    [SXZOI2024C]典题目背景现在我说,这真的是典。你信吗?是吗?是吧。题目描述给定一个整数$n$。你有一个长度为$n$的序列$a_1,a_2,\dots,a_n$,值域为$[1,n]$。从$n^n$个可能的序列$a$中,等概率地随机选出一个。接下来建出一张有向图,对于每个$i$,$i\toa_i$有一条......
  • T533809 [SXZOI 2024 B] 乐
    [SXZOI2024B]乐题目背景有人看乐子,有人照镜子。赶紧做题,不然看的就是你!题目描述给定一个长度为$n$的整数序列$a_1,a_2,\dots,a_n$。定义$f(l,r)=|\sum_{i=l}^ra_i|$。现在有$q$次查询,每次给定$l,r$。询问$\max_{l\leqi\leqj\leqr}f(i,j)$。输入......
  • T533811 [SXZOI 2024 E] 哮
    [SXZOI2024E]哮题目背景是什么在黑夜嚎叫?题目描述有一个$n$个点,$m$条边的有向无环图。每条边上有边权。定义一条路径的权值为路径上所有边权的异或值。现在对于所有从节点$1$出发走到节点$n$的路径,输出这些路径的权值和。答案对$998244353$取模。输入格式第一......
  • T533808 [SXZOI 2024 A] 急
    [SXZOI2024A]急题目背景我们为什么要说“急了”?急了是一种态度,一种张弛有度,一种睚眦必报,一种快意恩仇。遇到羞辱不急于还击,是懦夫,“急了”教我们让他绝不退让、以武服人;遇到挫折羞愤不已,是愚夫,“急了”教我们正面应敌、以武取胜。“急了”体现的是中华法家的杀伐之道,体现的......
  • 第四届电子信息工程与计算机通信国际学术会议(EIECC 2024) 2024 4th International Con
    @目录一、会议详情二、重要信息三、大会介绍四、出席嘉宾五、征稿主题一、会议详情二、重要信息大会官网:https://ais.cn/u/vEbMBz提交检索:EICompendex、IEEEXplore、Scopus会议时间:2024年12月13-15日会议地点:中国·武汉三、大会介绍第四届电子信息工程与计算机通信国......