《剑指offer》– 链表中倒数第k个节点、反转链表、合并两个排序的链表

《剑指offer》– 链表中倒数第k个节点、反转链表、合并两个排序的链表

一、链表中倒数时第k个节点:

1、题目:

输入一个链表,输出该链表中倒数第k个结点。

2、解题思路:单链表具有单向移动的特性。

(1)第一种:先遍历链表,算出链表节点数count,第二次直接遍历到第count-k个节点。但是要注意,可能链表节点数count小于k,此时要返回NULL,所以要先判断这个条件。(这一种就不贴代码出来了)

(2)第二种:

可以用两个指针,一个指针遍历到第k个结点的时候,第二个指针再走到第一个节点,然后两个指针的距离始终保持k-1,这样,当第一个指针的next==NULL,也就是走到最后一个节点的时候,第二个指针对应的位置,就是倒数第k个结点。

这样的好处是能够节省一个循环,时间复杂度会相应降低。从Q(2N) 到Q(N)

注意,但是需要一个小循环让第一个指针先走到第k个指针。同时也存在结点总数小于k的问题,如果循环还没有进行到k次,而第一个指针的已经是NULL,即走到头了,那么,函数返回NULL。

3、代码实现:

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

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {

        if(head ==null || k<=0){
            return null;
        }
        ListNode last=head;
        
        //第一个指针先移动k-1个节点
        for(int i=0;i<k-1;i++){
            if(head.next!=null){
                head=head.next;
            }else{
                return null;
            }
        }
        //同时移动两个指针,当第一个指针指向null的时候,last就是所求的结点
        while(head.next!=null){
            head=head.next;
            last=last.next;
        }
        
        return last;
    }
}

 

 

二、反转链表:

参考博客:https://www.jianshu.com/p/e385d9c06672

1、题目:

输入一个链表,反转链表后,输出新链表的表头。

2、解题思路:

2-1:第一种:使用递归方式:

(1)解题思路:

假设链表为[1,2,3,4,5]先迭代到链表末尾5,然后从5开始依次反转整个链表。
如下图所示,先迭代待最后一位5,并且设置一个新的节点newList作为反转后链表的头结点,由于整个链表反转后的头就是最后一个数,所以newList存放的一直是反转后的头结点的地址,将head指向的地址赋值给head->next->next指针,并且一定要记得让head->next =NULL,也就是断开现在指针的链接,否则新的链表形成了环,下一层head->next->next赋值的时候会覆盖后续的值。依次反转。。

《剑指offer》-- 链表中倒数第k个节点、反转链表、合并两个排序的链表

(2)代码实现:

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

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode ReverseList(ListNode head) {
        //递归方式
        if(head==null || head.next==null){
            return head;
        }
        ListNode newList=ReverseList(head.next);
        head.next.next=head;
        head.next=null;
        
        return newList;
    }
}

 

2-2第二种:使用迭代方式:

(1)解题思路:

先给定一个空的链表newList,然后判断传入的链表head是不是空链表或者链表元素只有一个,如果是,直接返回就可以。如果不是,则对链表进行迭代,然后给一个临时变量temp存储head.next,然后改变head.next的指向newList,然后把head赋值给newList,接着让head等于临时变量temp,就这样一直迭代完整个链表,返回newList就可以。如下图所示:

《剑指offer》-- 链表中倒数第k个节点、反转链表、合并两个排序的链表

(2)代码实现:

 public ListNode ReverseList(ListNode head) {
        
        //非递归方式:
        ListNode newList=null;
        if(head==null || head.next==null){
            return head;
        }
        
        while(head!=null){
            ListNode temp=head.next;
            head.next=newList;
            newList=head;
            head=temp;
        }
        return newList;
    }

 

 

三、合并两个排序的链表:

参考博客:https://blog.csdn.net/qq_23217629/article/details/51730312

1、题目:

输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

2、解题思路:

比较两个链表的第一个节点,取出最小值的节点,接着再按照相同的方式重复比较剩余链表的节点。

3、代码实现:


public class Solution {
    public ListNode Merge1(ListNode list1, ListNode list2) {
            //递归版本
			ListNode head;
			if (list1 == null) {
				return list2;
			}
			if (list2 == null) {
				return list1;
			}
			if (list1.val < list2.val) {
				head = list1;
				head.next = Merge(list1.next, list2);
			} else {
				head = list2;
				head.next = Merge(list1, list2.next);
			}
			return head;
		}

    public ListNode Merge(ListNode list1,ListNode list2) {
		//非递归版本:
		ListNode head = new ListNode(-1);//头节点,用来存储合并的链表
		head.next = null;
		ListNode root = head;//root暂存我新建的头节点,合并之后返回root.next,就是题目给的头节点
		
		while(list1!=null && list2!=null){
			if(list1.val <=list2.val){
				head.next=list1;
				head = list1;
				list1 = list1.next;
			}else{
				head.next=list2;
				head=list2;
				list2=list2.next;
			}
		}
		
		//把未结束的链表连接到合并后的链表尾部
		if(list1 !=null){
			head.next=list1;
		}
		if(list2 !=null){
			head.next=list2;
		}
		
		return root.next;
    }
}

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/114699.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • C# FindWindowEx用法

    C# FindWindowEx用法2010-11-2809:51:18|  分类: 程序编程|字号 订阅 函数功能:该函数获得一个窗口的句柄,该窗口的类名和窗口名与给定的字符串相匹配。这个函数查找子窗口,从排在给定的子窗口后面的下一个子窗口开始。在查找时不区分大小写。   函数原型:HWNDFindWindowEx(HWNDhwndParent,HWNDhwndChildAfter

    2022年5月31日
    261
  • python运行pyc文件_Python pyc文件[通俗易懂]

    python运行pyc文件_Python pyc文件[通俗易懂]什么是pyc文件pyc是由py文件经过编译后二进制文件,py文件变成pyc文件后,加载的速度有所提高,而且pyc是一种跨平台的字节码,是由python的虚拟机来执行的。pyc的内容,是跟python的版本相关的,不同版本编译后的pyc文件是不同的,2.5编译的pyc文件,2.4版本的python是无法执行的。pyc文件也是可以反编译的,不同版本编译后的pyc文件是不同。为什么需要pyc文件…

    2022年6月16日
    35
  • JDK安装包和Mysql安装包整理

    肯定有许多许多小伙伴在找jdk和MySQL这些东西的安装包,去官网下载有特别慢,所以想在网上找一下,来吧,看完总有一款是你喜欢的。。。。JDK安装包jdk-7u80-windows-x64.exe(jdk1.7win64位)jdk-7u80-windows-x86.exe(jdk1.7win32位)jdk-7u80-linux-i586.tar.gz(jdk1.7Li…

    2022年4月8日
    394
  • 在报关的过程中会不会出现两个商检

    在报关的过程中会不会出现两个商检问题:1、我刚接触报关,我想知道在报检后如果检验检疫局要商检,那么在接下来的报关过程中我们还会再要商检吗?2、还有我想知道法检是指哪些检验,三检和法检有什么区别,我知道三检包括商检那么法检报不包括呢?回答:1.只有报检手续都办好了,出具通关单后,凭通关单才可以报关。报关过程和商检已经没有关系了。报关中不存在两个商检。但是商检整个流程会分别在报关前后完成。所以,可能让你混淆以为是两个商检。

    2025年12月3日
    4
  • PyCharm激活码永久有效PyCharm2017.1.8激活码教程-持续更新,一步到位

    PyCharm激活码永久有效PyCharm2017.1.8激活码教程-持续更新,一步到位PyCharm激活码永久有效2017.1.8激活码教程-Windows版永久激活-持续更新,Idea激活码2017.1.8成功激活

    2022年6月19日
    36
  • JsonPath使用

    JsonPath使用JSONPath-是xpath在json的应用。xml最大的优点就有大量的工具可以分析,转换,和选择性的提取文档中的数据。XPath是这些最强大的工具之一。如果可以使用xpath来解析json,以下的问题可以被解决: 1,数据不使用特殊的脚本,可以在客户端交互的发现并取并获取。2,客户机请求的JSON数据可以减少到服务器上的相关部分,这样可以最大限度地减少服务器响应的带宽使用…

    2022年6月18日
    31

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号