首页 > 其他分享 >LeetCode 链表操作

LeetCode 链表操作

时间:2023-05-02 20:22:58浏览次数:43  
标签:ListNode val next 链表 l2 操作 null LeetCode

21. 合并两个有序链表

/**
 * 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 mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode l1 = list1;
        ListNode l2 = list2;
        // 新链表头指针
        ListNode header = null;
        // 新链表后指针
        ListNode before = null;
        
        // 特别注意示例 [1,5] [1,2,4]
        while(l1 != null || l2 != null) {
            // 两者都没走到末尾,都不为空
            if (l1 != null && l2 != null) {
                // 两链表当前节点相同,加两个一样的到新链表,并同时向前走一步
                if (l1.val == l2.val) {
                    ListNode newNode1 = new ListNode(l1.val);
                    ListNode newNode2 = new ListNode(l2.val);
                    if (before != null) {
                        before.next = newNode1;
                    }
                    newNode1.next = newNode2;
                    before = newNode2;
                    // 两个相等,同时加入新链表,同时向前走一步
                    l1 = l1.next;
                    l2 = l2.next;
                    // 新链表头节点,只在为 null 的时候指定一次
                    if (header == null) {
                        header = newNode1;
                    }
                }
                // 两链表当前节点不同,加小的那个到新链表,并只将小的那个向前走一步
                else {
                    ListNode newNode = null;
                    if (l1.val < l2.val) {
                        newNode = new ListNode(l1.val);
                        // l1 当前比 l2 当前小,只把 l1 加入新链表,也只有 l1 向前走一步
                        l1 = l1.next;
                    }
                    else if (l2.val < l1.val) {
                        newNode = new ListNode(l2.val);
                        // l2 当前比 l1 当前小,只把 l2 加入新链表,也只有 l2 向前走一步
                        l2 = l2.next;
                    }
                    // 将新节点与之前的连上
                    if (before != null) {
                        before.next = newNode;
                    }
                    before = newNode;
                     // 新链表头节点,只在为 null 的时候指定一次
                    if (header == null) {
                        header = newNode;
                    }
                }
            }
            // 两链表有一者走到了末尾,将没走到末尾的那个当前节点加入新链表,并向前走一步
            else {
                ListNode newNode = null;
                if (l1 != null && l2 == null) {
                    // 只走还没走完的这个链表
                    newNode = new ListNode(l1.val);
                    l1 = l1.next;
                }
                else if (l2 != null && l1 == null) {
                    // 只走还没走完的这个链表
                    newNode = new ListNode(l2.val);
                    l2 = l2.next;
                }
                // 将新节点与之前的连上
                if (before != null) {
                    before.next = newNode;
                }
                before = newNode;
                 // 新链表头节点,只在为 null 的时候指定一次
                if (header == null) {
                    header = newNode;
                }
            }
            
        }
        return header;

    }
}

 

 

25. K 个一组翻转链表

写一个反转链表的公共方法 revers(ListNode listHead)

ki 表示走到了 k 组第几个;k 组第一个记为 kStart ; k 组最后一个记为 kEnd;前一个 k 组的尾巴记为 preKTail

每次走到 k 组最后一个的时候

  • ki 清零
  • kEnd 指向 null ,调用反转方法反转 kStart
  • 如果 preKTail 不为空,preKTail指向 kEnd,preKTail 变为 kStart (反转后 start 成了尾)

如果走到了末尾,而 ki >1 说明后面的不够 k 个一组,不用反转。因此 preKTail 直接指向 kStart

/**
 * 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 reverseKGroup(ListNode head, int k) {
        ListNode kStart = null;
        ListNode kCur = head;
        ListNode kEnd = null;

        ListNode preKtail = null;

        ListNode resHead = null;
        int ki = 1;
        while(kCur != null) {
            // 每次先缓存下一个节点,防止后面有变化
            ListNode nextNode = kCur.next;
            if (ki == 1) {
                // k 个一组的起始
                kStart = kCur;
            }
            if (ki == k) {
                kEnd = kCur;
                if (resHead == null) {
                    resHead = kEnd;
                }
                ki=0;
                // 切断与下一个 k 组的联系,使得反转链表的时候有尾指向null
                kEnd.next = null;
                // 上一个链表尾指向这个的最后一个(待翻转)
                if (preKtail != null) {
                    preKtail.next = kEnd;
                }
                // 反转链表
                reverseList(kStart);
                // 链表已经反转过,头成了尾巴
                preKtail = kStart;
            }
            ki++;
            kCur = nextNode;
            if (kCur == null && ki > 1) {
                // 没有任何完整的一组的情况
                if (resHead == null) {
                    resHead = kStart;
                }
                // 这些剩下的不用反转,因此上一个尾指向这一个头
                if (preKtail != null) {
                    preKtail.next = kStart;
                }
                break;
            }
        }
        return resHead;
    }

    private void reverseList(ListNode head) {
        ListNode cur = head;
        ListNode pre = null;
        while(cur != null) {
            // 先缓存下一个节点。注意怎么反转链表,这个 Next 指针要每次循环新生成一个,不能定义一个全局的
            ListNode next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }
    }
}

 

标签:ListNode,val,next,链表,l2,操作,null,LeetCode
From: https://www.cnblogs.com/suBlog/p/17354453.html

相关文章

  • NC20279 [SCOI2010]序列操作
    题目链接题目题目描述lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作:0ab把[a,b]区间内的所有数全变成01ab把[a,b]区间内的所有数全变成12ab把[a,b]区间内的所有数全部取反,也就是说把所有的0变成1,......
  • python excel 操作
    7个库:xlrd库:从excel中读取数据,支持xls、xlsxxlwt库:对excel进行修改操作,不支持对xlsx格式的修改xlutils库:在xlw和xlrd中,对一个已存在的文件进行修改openpyxl:不支持xls,只支持.xlsx、.xlsm、.xltx、.xltm。可以通过TotalExcelConverter软件进行excel格式转换。软件下载连接:TotalE......
  • 加算操作
    【2022重庆市中考A卷数学选择压轴题】加算操作题目背景2022重庆市中考A卷数学选择压轴题。题目描述现定义加算操作为对于长度为$n$的只含减法运算的序列$a_1-a_2-\cdots-a_{n-1}-a_n$,可以随意在其中两项加入一对括号,比如,对于$a_1-a_2-a_3-a_4-a_5$,可以进行加算操作变成......
  • 21 文件六大基本操作
    文件的六大基本操作:新建、打开、关闭、读写、删除文件;辅助操作:操作根目录文件:操作文件,先要找到与该文件对应的rfsdir_t结构;get_rootdirfile_blk函数:获取根目录文件,先调用get_rootdir函数获取根目录的rfsdir_t结构,到一个缓冲区中;del_rootdir函数释放缓冲区;获取文件名:......
  • Halcon XLD 轮廓操作,轮廓交集补集
    8.1获取轨迹的图像数据 获取轮廓坐标get_contour_xld     算子:get_contour_xld(Contour ::: Row, Col)示例:get_contour_xld(Contours4,Row26,Col)Contours4(输入对象):输入轮廓对象Row26(输出控制参数1):输出轮廓的每一个点的行坐标Col(输出控制参数2):输出轮廓的每一个点的......
  • 反转链表
    描述给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。 数据范围: 0≤n≤1000要求:空间复杂度 O(1) ,时间复杂度 O(n) 。 如当输入链表{1,2,3}时,经反转后,原链表变为{3,2,1},所以对应的输出为{3,2,1}。 ......
  • java反转部分链表后记
    由于链表只是一个单向链表所以不能在一次循环之内就直接进行反转操作又因为只需要反转部分链表所以只要将链表遍历到需要反转的最后一位,剩下的不用管了于是我想到了在第一遍循环中用HashMap获取需要反转的链表的部分,键代表下标,值代表原先链表中val之后第二遍遍历时按照将值按......
  • Halcon XLD 轮廓操作,轮廓交集补集
     8.1获取轨迹的图像数据 获取轮廓坐标get_contour_xld     算子:get_contour_xld(Contour ::: Row, Col)示例:get_contour_xld(Contours4,Row26,Col)Contours4(输入对象):输入轮廓对象Row26(输出控制参数1):输出轮廓的每一个点的行坐标Col(输出控制参数2):输出轮廓的......
  • IT工具知识-18: ADB操作笔记(自用)
    Linux下的常用命令(持续更新)终端使用bashshell查询安卓设备当前活动的APP包名和活动窗口名adbshelldumpsyswindowwindows|grep-E'mCurrentFocus|mFocusedApp'启动指定app下的指定窗口app包名和活动窗口名都要提供,否则无法启动adbshellamstart包名/活动窗口......
  • vue学习 第五天 css基础 --- ps操作 / 圆角边框(border-radius) / 阴影(盒子/文字)b
      ps基本操作1、ps的基本操作2、ps快捷操作的位置3、样式书写习惯 4、样式设置的小细节(注意)1、图片设置width:100%这样图片的宽度就不会超过父容器的宽度。2、块元素没有设置宽度,给margin左右是没有效果的。......