題目描述
輸入一個鏈表,按鏈表從尾到頭的順序返回一個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;
}
}
}