剑指offer--从尾到头打印链表

题目描述

输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
示例代码:

/**
*    public class ListNode {
*        int val;
*        ListNode next = null;
*
*        ListNode(int val) {
*            this.val = val;
*        }
*    }
*
*/
import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        
    }
}

思路+代码实现

1 最简单思路

1.1 分析
使用两个ArrayList集合,一个存放顺序遍历的结果,一个存放倒叙遍历的结果
1.2 代码

/**
*    public class ListNode {
*        int val;
*        ListNode next = null;
*
*        ListNode(int val) {
*            this.val = val;
*        }
*    }
*
*/
import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> tempList=new ArrayList<>();
        while(listNode!=null){
            tempList.add(listNode.val);
            listNode=listNode.next;
        }
        ArrayList<Integer> resultList=new ArrayList<>();
        for(int i=tempList.size()-1;i>=0;i--){
            resultList.add(tempList.get(i));
        }
        return resultList;
    }
}

1.3 复杂度
O(n)

2 栈思路

2.1 分析
由于是得到链表的倒叙遍历结果,这样我们联想到栈的“先进后出”特点。将链表先遍历的存放,最后才输出,并且题目指定只能导入ArrayList结合,联想list(index,value)属性可以办到。

2.2 代码

/**
*    public class ListNode {
*        int val;
*        ListNode next = null;
*
*        ListNode(int val) {
*            this.val = val;
*        }
*    }
*
*/
import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> resultList=new ArrayList<>();
       while(listNode!=null){
           resultList.add(0,listNode.val);
           listNode=listNode.next;
       }
        return resultList;
    }
}

2.3 复杂度
O(n²)

3 递归

3.1 分析
运用递归,系统自己的栈完成
3.2 代码

/**
*    public class ListNode {
*        int val;
*        ListNode next = null;
*
*        ListNode(int val) {
*            this.val = val;
*        }
*    }
*
*/
import java.util.ArrayList;
public class Solution {
    ArrayList<Integer> resultList=new ArrayList<>();
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        if(listNode!=null){
           printListFromTailToHead(listNode.next);
           resultList.add(listNode.val);
        }
        return resultList;
    }
}

校招真题

1 找出单向链表中的一个节点,该节点到尾指针的距离为K-小米2019秋招测试开发笔试题(A)

1.1 题目描述
找出单向链表中的一个节点,该节点到尾指针的距离为K。链表的倒数第0个结点为链表的尾指针。要求时间复杂度为O(n)。
链表结点定义如下:

struct ListNode
{
    int m_nKey;
    ListNode* m_pNext;
}

链表节点的值初始化为1,2,3,4,5,6,7

输入描述:
该节点到尾指针的距离K
输出描述
返回该单向链表的倒数第K个节点,输出节点的值

示例1

输入
2
输出
6

备注:

请自觉实现一个链表,将1到7依次加入链表,然后再寻找倒数第K个节点。要求加节点与找节点的操作复杂度均为O(n)。

1.2 思路+代码实现

1.2.1 思路
先运用递归,遍历出倒叙的结果,然后再直接找出需要的值

1.2.2 代码

import java.util.Scanner;
import java.util.ArrayList;

class ListNode{
    int val;
    ListNode next=null;
    ListNode(int val){
        this.val=val;
    }
}
public class Main{
    public static void main(String[] args){
        ListNode node=init();
        Scanner in=new Scanner(System.in);
        int x=in.nextInt();
        ArrayList<Integer> arrList=new ArrayList<>();
        Traverse(node,arrList);
        System.out.println(arrList.get(x-1));
    }
    public static void Traverse(ListNode list,ArrayList<Integer> arrList){
        if(list!=null){
            Traverse(list.next,arrList);
            arrList.add(list.val);
        }
    }
    
    public static ListNode init(){
        ListNode node1=new ListNode(1);
        ListNode node2=new ListNode(2);
        ListNode node3=new ListNode(3);
        ListNode node4=new ListNode(4);
        ListNode node5=new ListNode(5);
        ListNode node6=new ListNode(6);
        ListNode node7=new ListNode(7);

        node1.next=node2;
        node2.next=node3;
        node3.next=node4;
        node4.next=node5;
        node5.next=node6;
        node6.next=node7;
        
        return node1;
    }
}

2 翻转链表-哔哩哔哩2019秋招编程题合集

2.1 题目描述
对于一个链表 L: L0→L1→…→Ln-1→Ln,
将其翻转成 L0→Ln→L1→Ln-1→L2→Ln-2→…
输入是一串数字,请将其转换成单链表格式之后,再进行操作

输入描述
一串数字,用逗号分隔
输出描述
一串数字,用逗号分隔

示例1

输入
1,2,3,4,5
输出
1,5,2,4,3

备注:

数组长度不超过100000
时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M

2.2 思路+代码实现
2.2.1 思路
链表平均拆分,后半部分链表逆转,再合并两条链表
2.2.2 代码


import java.util.Scanner;
 
/*
题目描述:对于一个链表 L: L0→L1→…→Ln-1→Ln,将其翻转成 L0→Ln→L1→Ln-1→L2→Ln-2→…
输入1,2,3,4,5     输出1,5,2,4,3
备注:数组长度不超过100000
 */
public class Main {
    //定义Node节点
    static class ListNode {
        int val;
        ListNode next = null;
 
        ListNode(int val) {
            this.val = val;
        }
    }
 
    public static void main(String[] args) {
        //1.获取控制台输入的信息
        Scanner scanner = new Scanner(System.in);
        String string = scanner.nextLine();
        String[] strings = string.split(",");
        //2.将输入的字符串构成带头节点的2个链表
        ListNode head = creatList(strings);
        reorderList(head.next);
        head = head.next;
        //3.输出
        while(head!=null){
            if(head.next==null){
                System.out.print(head.val);
            }else{
                 System.out.print(head.val+",");
            }
            head=head.next;
        }
 
    }
 
 
 
    /*
     * 将str创建带头结点的单链表
     */
    public static ListNode creatList(String[] strings) {
        ListNode head = new ListNode(0);
        ListNode tail = head;
        for (String str : strings) {
            ListNode newNode = new ListNode(Integer.valueOf(str));
            tail.next = newNode;
            tail = newNode;
        }
        return head;
    }
 
 
    /*
     * 思路:链表平均拆分,后半部分链表反转,在将两个链表合并
     */
    public static void reorderList(ListNode head) {
        if (head == null || head.next == null) return;
 
        ListNode p1 = head;
        ListNode p2 = head;
 
        // 找到链表的一半
        while (p2.next != null && p2.next.next != null) {
            p1 = p1.next;
            p2 = p2.next.next;
        }
 
        // 将链表分为两段
        p2 = p1.next;
        p1.next = null;
        p1 = head;
 
        // 将后半段进行链表的翻转
        ListNode head2 = p2;
        ListNode next2;
        while (p2.next != null) {
            next2 = p2.next;
            p2.next = next2.next;
            next2.next = head2;
            head2 = next2;
        }
        p2 = head2;
 
        // 两条链表进行合并
        ListNode next1;
        while (p2 != null) {
            next1 = p1.next;
            next2 = p2.next;
 
            p1.next = p2;
            p2.next = next1;
 
            p1 = next1;
            p2 = next2;
        }
 
    }
 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值