實踐九 軟體安全攻防--緩衝區溢位和shellcode
阿新 • • 發佈:2022-05-09
方法一:遞迴(推薦使用)
知識點:遞迴
遞迴是一個過程或函式在其定義或說明中有直接或間接呼叫自身的一種方法,它通常把一個大型複雜的問題層層轉化為一個與原問題相似的規模較小的問題來求解。因此遞迴過程,最重要的就是檢視能不能講原本的問題分解為更小的子問題,這是使用遞迴的關鍵。
思路:
我們都知道連結串列無法逆序訪問,那肯定無法直接遍歷連結串列得到從尾到頭的逆序結果。但是我們都知道遞迴是到達底層後才會往上回溯,因此我們可以考慮遞迴遍歷連結串列,因此三段式如下:
- 終止條件: 遞迴進入連結串列尾,即節點為空節點時結束遞迴。
- 返回值: 每次返回子問題之後的全部輸出。
- 本級任務: 每級子任務遞迴地進入下一級,等下一級的子問題輸出陣列返回時,將自己的節點值新增在陣列末尾。
具體做法:
- step 1:從表頭開始往後遞迴進入每一個節點。
- step 2:遇到尾節點後開始返回,每次返回依次新增一個值進入輸出陣列。
- step 3:直到遞迴返回表頭。
Java實現程式碼:
複製程式碼1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import java.util.ArrayList;
public class Solution {
//遞迴函式
public void recursion(ListNode head, ArrayList<Integer> res){
if (head != null ){
//先往連結串列深處遍歷
recursion(head.next, res);
//再填充到陣列就是逆序
res.add(head.val);
}
}
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> res = new ArrayList<Integer>(); //遞迴函式解決
recursion(listNode, res);
return res;
}
|
複雜度分析:
- 時間複雜度:O(n)O(n)O(n),其中nnn為連結串列長度,遞迴遍歷一次連結串列
- 空間複雜度:O(n)O(n)O(n),遞迴棧的最大空間為連結串列長度
方法二:棧(擴充套件思路)
知識點:棧
棧是一種僅支援在表尾進行插入和刪除操作的線性表,這一端被稱為棧頂,另一端被稱為棧底。元素入棧指的是把新元素放到棧頂元素的上面,使之成為新的棧頂元素;元素出棧指的是從一個棧刪除元素又稱作出棧或退棧,它是把棧頂元素刪除掉,使其相鄰的元素成為新的棧頂元素。
思路:
遞迴的思想也可以用棧實現,因為棧是先進後出的,符合逆序的特點,遞迴本質上就是用棧實現的。
具體做法:
- step 1:我們可以順序遍歷連結串列,將連結串列的值push到棧中。
- step 2:然後再依次彈出棧中的元素,加入到陣列中,即可實現連結串列逆序。
圖示:
Java實現程式碼:
複製程式碼1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import java.util.*;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> res = new ArrayList<Integer>();
Stack<Integer> s = new Stack<Integer>();
//正序輸出連結串列到棧中
while (listNode != null ){
s.push(listNode.val);
listNode = listNode.next;
}
//輸出棧中元素到陣列中
while (!s.isEmpty())
res.add(s.pop());
return res;
}
}
|
複雜度分析:
- 時間複雜度:O(n)O(n)O(n),遍歷連結串列是一個O(n)O(n)O(n),彈空一個棧需要O(n)O(n)O(n)
- 空間複雜度:O(n)O(n)O(n),棧空間最大長度是連結串列的長度nnn