题目描述
输入一个链表,按链表从尾到头的顺序返回一个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;
}
}
}