劍指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;
        }
 
    }
 
}
發佈了104 篇原創文章 · 獲贊 34 · 訪問量 6832
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章