每日一題——Python實現PAT甲級1046 Shortest Distance(舉一反三+思想解讀+逐步優化)


一個認為一切根源都是“自己不夠強”的INTJ

個人主頁:用哲學編程-CSDN博客
專欄:每日一題——舉一反三
Python編程學習
Python內置函數

Python-3.12.0文檔解讀

目錄

我的寫法

專業點評

優點

改進建議

時間復雜度分析

空間復雜度分析

總結

我要更強

方法一:優化空間復雜度(保留前綴和)

方法二:直接使用距離數組進行查詢

代碼優化解釋

時間和空間復雜度分析

總結

哲學和編程思想

編程思想和哲學

總結

舉一反三

1. 空間換時間

2. 時間換空間

3. 貪心思想

4. 分治思想

5. 動態規劃

舉一反三的技巧



https://pintia.cn/problem-sets/994805342720868352/exam/problems/type/7?problemSetProblemId=994805435700199424&page=0


我的寫法

# 從輸入中讀取一行,將其拆分為整數,并存儲在 distances 列表中
distances = list(map(int, input().split()))# 第一個元素是 N,表示接下來行程的數目
N = distances[0]# 剩下的元素是各段行程的距離
distances = distances[1:]# 從輸入中讀取 M,表示要處理的查詢次數
M = int(input())# 創建一個前綴和數組,用于存儲從起點到各位置的累計距離
prefix_sum = [0] * (N + 1)# 計算前綴和數組
for i in range(1, N + 1):# prefix_sum[i] 表示從起點到第 i 段行程結束的累計距離prefix_sum[i] = prefix_sum[i - 1] + distances[i - 1]# 總的環形路徑的距離
total_distance = prefix_sum[N]# 處理每個查詢
for i in range(M):# 讀取查詢的兩個點 a 和 ba, b = map(int, input().split())# 確保 a 小于 b,如果不是則交換 a 和 bif a > b:a, b = b, a# 計算從 a 到 b 的路徑距離distance1 = prefix_sum[b - 1] - prefix_sum[a - 1]# 計算從 b 到 a(繞過環的另一邊)的路徑距離distance2 = total_distance - distance1# 輸出較短的路徑距離print(min(distance1, distance2))

這段代碼的功能是處理一個環形路徑的查詢問題,計算兩個節點之間的最短距離。以下是對這段代碼的點評,以及時間復雜度和空間復雜度的分析。

專業點評

優點
  1. 前綴和的使用:
    • 通過前綴和數組?prefix_sum,可以在常數時間內計算任意兩點之間的路徑距離。這種方法有效地將路徑長度查詢的時間復雜度從線性降到常數。
  2. 處理環形路徑:
    • 計算兩種可能的路徑(順時針和逆時針)并取最小值的方式,確保了找到兩點間的最短路徑。
  3. 輸入處理:
  • 代碼通過?map?和?split?組合高效地讀取并轉換輸入,符合常見的Python代碼風格。
改進建議
  1. 輸入驗證:
    • 沒有對輸入進行驗證假設輸入是正確的。可以增加對輸入數據的合法性檢查,確保輸入值在合理范圍內。
  2. 變量命名:
  • 可以通過更具描述性的變量名(如?distance_clockwise?和?distance_counterclockwise)來提高代碼的可讀性。

時間復雜度分析

  1. 前綴和計算:
    • 構建前綴和數組的時間復雜度為?O(N),因為需要遍歷距離數組一次。
  2. 查詢處理:
    • 每次查詢的時間復雜度為?O(1),因為計算路徑距離和比較最小值的操作都是常數時間內完成的。
  3. 總體時間復雜度:
  • 總體時間復雜度為?O(N+M),其中?N?是距離數組的大小,M?是查詢次數。

空間復雜度分析

  1. 前綴和數組:
    • 需要一個大小為?N+1?的前綴和數組?prefix_sum,空間復雜度為?O(N)。
  2. 輸入存儲:
    • distances?數組存儲每段行程的距離,空間復雜度為?O(N)。
  3. 總體空間復雜度:
  • 總的空間復雜度為?O(N),因為額外使用的主要是?distances?和?prefix_sum?數組。

總結

這段代碼使用前綴和技巧有效地解決了環形路徑的最短距離查詢問題,時間復雜度為 O(N+M),空間復雜度為O(N)。整體實現高效、簡潔,但可以通過增加輸入驗證和更清晰的變量命名進一步提高代碼質量。


我要更強

在這個問題中,由于我們需要進行多次查詢,而每次查詢都需要計算兩點之間的最短距離,前綴和的使用已經是一種非常高效的方案。進一步優化時間復雜度已經較為困難,因為查詢已經是 O(1) 的時間復雜度。

然而,我們可以考慮優化空間復雜度,特別是當 N 非常大時。以下是幾種可能的優化方法:

方法一:優化空間復雜度(保留前綴和)

盡管前綴和數組的空間復雜度是 O(N),但它已經是當前任務的較優解。如果我們希望進一步減少空間消耗,可以考慮在查詢中實時計算部分前綴和,而不是存儲整個前綴和數組。然而,由于查詢次數 M 通常大于路徑段數 N,這種方法可能并不會帶來實際的性能提升。

方法二:直接使用距離數組進行查詢

如果我們不使用前綴和數組,而是直接從距離數組中計算路徑長度,雖然會增加每次查詢的時間復雜度,但可以節省空間。

下面是直接使用距離數組進行查詢的代碼示例:

# 讀取輸入
distances = list(map(int, input().split()))
N = distances[0]
distances = distances[1:]
M = int(input())# 計算總距離
total_distance = sum(distances)# 處理每個查詢
for _ in range(M):a, b = map(int, input().split())if a > b:a, b = b, a# 計算從 a 到 b 的路徑距離distance1 = sum(distances[a-1:b-1])# 計算從 b 到 a(繞過環的另一邊)的路徑距離distance2 = total_distance - distance1# 輸出較短的路徑距離print(min(distance1, distance2))

代碼優化解釋

  1. 輸入讀取和初始化:
    • 讀取并解析輸入,distances?包含各段行程的距離。
  2. 總距離計算:
    • 計算環形路徑的總距離。
  3. 查詢處理:

對每個查詢,計算從?a?到?b?的兩種路徑距離,輸出較小的值。

時間和空間復雜度分析

  1. 時間復雜度:
    • 每次查詢的時間復雜度為?O(N),因為我們需要計算部分路徑的距離。總的時間復雜度為?O(M?N)。
  2. 空間復雜度:
  • 這種方法的空間復雜度為?O(1),除了輸入數據外不需要額外的空間。

總結

直接使用距離數組進行查詢可以顯著減少空間消耗,但會增加查詢的時間復雜度。如果路徑段數 N 較小且查詢次數 M 較多,這種方法可能不如使用前綴和的方案高效。選擇何種方法需要根據具體的輸入規模進行權衡。


哲學和編程思想


在上述解決問題的過程中,運用了多種編程思想和哲學,下面詳細說明:

編程思想和哲學

  1. 空間換時間(前綴和方法):
    • 思想:通過增加額外的空間(前綴和數組)來換取時間上的優化。
    • 具體應用:在前綴和方法中,我們使用一個大小為?�+1N+1?的數組來存儲從起點到各位置的累計距離。這使得每次查詢的時間復雜度從可能的?�(�)O(N)?降至?�(1)O(1)。
    • 哲學:用更多的空間來預處理數據,以便在后續查詢中能夠快速得到結果。這種方法常用于需要多次查詢的大數據集。
  2. 時間換空間(直接計算路徑距離):
    • 思想:減少空間使用,通過增加計算時間來實現同樣的功能。
    • 具體應用:在沒有使用前綴和的情況下,我們直接在每次查詢中計算部分路徑的距離。這樣做雖然節省了空間,但查詢時間復雜度增加到了?�(�)O(N)。
    • 哲學:在空間資源緊張的情況下,可以通過增加計算時間來節省空間。這種方法適用于空間資源比時間資源更寶貴的場景。
  3. 貪心思想:
    • 思想:在每一步選擇中做出局部最優的選擇,希望最終得到全局最優解。
    • 具體應用:在環形路徑的查詢中,我們計算了兩種路徑(順時針和逆時針)的距離,并選擇了最小的那個距離。這個過程實際上是一個貪心選擇的過程。
    • 哲學:通過一系列局部最優的選擇,可以達到全局最優的效果。這種方法適用于問題可以分解成一系列子問題,并且每個子問題的最優解能構成問題的最優解的情況。
  4. 分治思想:
    • 思想:將問題分解成更小的子問題,分別解決這些子問題,然后合并結果。
    • 具體應用:雖然在上述代碼中沒有直接應用分治法,但前綴和的計算過程可以看作是一種分治思想的應用。我們先解決小范圍內的求和問題,再通過累積的方式解決更大范圍的求和問題。
    • 哲學:通過將復雜問題分解成更小、更易解決的子問題,可以有效地降低解決問題的復雜度。這種方法尤其適用于遞歸和動態規劃。
  5. 動態規劃思想:
  • 思想:通過記錄子問題的解,避免重復計算,逐步解決更大的問題。
  • 具體應用:前綴和數組的構建和使用實際上是一種動態規劃思想的體現。我們通過記錄每個位置的累計和,避免了在每次查詢時重復計算相同的子區間和。
  • 哲學:通過存儲和利用子問題的解,可以大大提高解決問題的效率。這種方法適用于具有重疊子問題的場景。

總結

通過分析和解釋,可以看到編程思想和哲學在解決實際問題中的應用。這些思想幫助我們在不同的約束條件下(如時間復雜度和空間復雜度)找到適合的解決方案。理解并靈活應用這些思想,可以使我們在編程中更加從容地應對各種挑戰。


舉一反三


理解和靈活應用編程思想和哲學是提升編程能力的關鍵。下面是一些技巧,結合這些思想,能更好地舉一反三,解決類似的問題:

1. 空間換時間

  • 技巧:預處理和緩存
    • 應用:當你需要頻繁查詢某些數據時,考慮是否可以通過預處理將結果存儲在數組或表中,從而減少每次查詢的計算量。
    • 示例:前綴和、動態規劃中的狀態轉移表、緩存最近查詢結果的LRU緩存。
  • 延伸:存儲中間結果
  • 應用:在遞歸問題中,存儲已經計算過的結果,避免重復計算。
  • 示例:斐波那契數列的動態規劃實現。

2. 時間換空間

  • 技巧:實時計算
    • 應用:當空間有限時,考慮是否可以在每次需要時實時計算所需的數據,而不是提前存儲所有可能的結果。
    • 示例:對每次查詢實時計算路徑距離,而不是使用前綴和數組。
  • 延伸:按需加載
  • 應用:在處理大數據時,可以考慮按需加載需要的數據,而不是一次性加載所有數據。
  • 示例:分頁加載數據、流式處理大文件。

3. 貪心思想

  • 技巧:每次選擇局部最優解
    • 應用:當問題可以分解成一系列子問題,并且每個子問題的最優解能構成問題的最優解時,考慮使用貪心算法。
    • 示例:找零錢問題、活動選擇問題、最小生成樹(Prim和Kruskal算法)。
  • 延伸:構建貪心策略
  • 應用:在實際問題中,嘗試構建一個簡單的貪心策略,驗證其是否能得到全局最優解。
  • 示例:為旅行商問題構建最近鄰居貪心策略。

4. 分治思想

  • 技巧:將問題分解成更小的子問題
    • 應用:當問題可以遞歸地分解成更小的問題,并且這些子問題獨立求解后可以合并成最終結果時,考慮使用分治算法。
    • 示例:二分搜索、歸并排序、快速排序。
  • 延伸:尋找合適的分解點
  • 應用:在實際問題中,嘗試找到合適的分解點,以便將問題分解成更小的、易于解決的子問題。
  • 示例:在圖算法中,將圖分解成子圖進行處理。

5. 動態規劃

  • 技巧:記錄子問題的解
    • 應用:當問題具有重疊子問題結構時,通過記錄子問題的解,避免重復計算。
    • 示例:背包問題、最長公共子序列、最長遞增子序列。
  • 延伸:自底向上和自頂向下
  • 應用:理解動態規劃的兩種實現方式:自頂向下的記憶化搜索和自底向上的遞推。
  • 示例:斐波那契數列的兩種動態規劃實現。

舉一反三的技巧

  1. 類比法:將當前問題與已知問題進行類比,尋找相似之處,應用相同或類似的解決方法。
    • 實踐:在面對新問題時,問自己:“這是否類似于我之前解決過的某個問題?”
  2. 分解法:將復雜問題分解成更小的子問題,分別解決這些子問題,再將其組合成最終解決方案。
    • 實踐:在解決復雜問題時,嘗試運用分治思想,將問題逐步細化。
  3. 驗證法:假設某種策略是可行的,先嘗試解決子問題,驗證其可行性,再逐步擴展到更大的問題。
    • 實踐:在嘗試貪心算法或其他策略時,先在小規模問題上驗證,再擴展到全局。
  4. 優化法:在已有解決方案的基礎上,思考是否有可以優化的部分,特別是時間復雜度和空間復雜度。
  • 實踐:在已有的解決方案上,問自己:“是否有更快(時間)或更省空間的方法?”

通過運用這些技巧和思想,可以更好地理解和解決問題,提升編程能力。理解背后的哲學和原理,能夠在面對新的或復雜的問題時,迅速找到有效的解決方案。


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/21024.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/21024.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/21024.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python模塊導入的寫法

關于Python模塊導入的寫法有 相對路徑導入 和 絕對路徑導入 兩種不同的導入路徑的寫法。 文章目錄 相對路徑導入絕對路徑導入總結 相對路徑導入 from .utils import upblock2d, crossattn_upblock2d使用了相對導入,以(“.”)開頭這種導入方…

HCIP-Datacom-ARST自選題庫__MAC【14道題】

一、單選題 1.缺省情況下,以下哪種安全MAC地址類型在設備重啟后表項會丟失? 黑洞MAC地址 Sticky MAC地址 安全動態MAC地址 安全靜態MAC地址 2.華為交換機MAC地址表中的動態sticky MAC地址的默認老化時間是多少秒? 300 不會老化 400 500 3.華為交換機MA…

【BeyondCompare官方免費版下載鏈接】

提示:文章寫完后,目錄可以自動生成,如何生成可參考右邊的幫助文檔 文章目錄 前言一、BeyondCompare官方免費版下載鏈接 前言 該軟件用于比較兩個文本或文件夾之間的不同之處,查看代碼修改時非常好用。 一、BeyondCompare官方免費…

Polar Web【簡單】login

Polar Web【簡單】login 本文旨在記錄此題的探索和解決過程。 Contents Polar Web【簡單】login探索&思路EXP (python)結果&總結 探索&思路 查看源碼,發現存在用戶信息泄露。嘗試用獲取信息登錄,顯示成功,但其后沒有可做的操作。…

有損線、上升邊退化與材料特性(七)

有損線的不良影響 當信號沿著實際有損線傳輸時,高頻分量的幅度減小,而低頻分量的幅度保持不變。由于這個種選擇性的衰減,信號的帶寬降低,信號的上升邊會增長。如果上升邊的退化與單位間隔比很小,同位模式將比較穩定與…

Django視圖與路由:打造你的網絡帝國

Hello,我是阿佑,上期給大家講了 Django ORM魔法:用Python代碼召喚數據庫之靈! 今天將帶大家深入探討了視圖的工作原理、如何編寫高效的函數視圖和類視圖,以及如何巧妙地利用URL路由來提升應用的用戶體驗和可維護性。通…

最新h5st(4.7.2)參數分析與純算法還原(含算法源碼)

文章目錄 1. 寫在前面2. 加密分析3. 算法還原 【🏠作者主頁】:吳秋霖 【💼作者介紹】:擅長爬蟲與JS加密逆向分析!Python領域優質創作者、CSDN博客專家、阿里云博客專家、華為云享專家。一路走來長期堅守并致力于Python…

操作系統 實驗29 同步與互斥

1、并發線程同步與互斥 源程序&#xff1a; #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <unistd.h> #include <string.h> int num30,count10; pthread_mutex_t mylockPTHREAD_MUTEX_INITIALIZER; void *sub1(voi…

圖解 Python 編程(10) | 錯誤與異常處理

&#x1f31e;歡迎來到Python的世界 &#x1f308;博客主頁&#xff1a;卿云閣 &#x1f48c;歡迎關注&#x1f389;點贊&#x1f44d;收藏??留言&#x1f4dd; &#x1f31f;本文由卿云閣原創&#xff01; &#x1f4c6;首發時間&#xff1a;&#x1f339;2024年6月2日&…

LangChain學習之prompt格式化與解析器使用

1. 學習背景 在LangChain for LLM應用程序開發中課程中&#xff0c;學習了LangChain框架擴展應用程序開發中語言模型的用例和功能的基本技能&#xff0c;遂做整理為后面的應用做準備。視頻地址&#xff1a;基于LangChain的大語言模型應用開發構建和評估高 2. 先準備嘗試調用O…

數據結構(C):從初識堆到堆排序的實現

目錄 &#x1f31e;0.前言 &#x1f688; 1.堆的概念 &#x1f688; 2.堆的實現 &#x1f69d;2.1堆向下調整算法 &#x1f69d;2.2堆的創建&#xff08;堆向下調整算法&#xff09; ??2.2.1 向下調整建堆時間復雜度 &#x1f69d;2.3堆向上調整算法 &#x1f69d;2.…

testcontainer

在我們的項目中&#xff0c;單元測試是保證我們代碼質量非常重要的一環&#xff0c;但是我們的業務代碼不可避免的需要依賴外部的系統或服務如DB&#xff0c;redis&#xff0c;其他外部服務等。如何保證我們的測試代碼不受外部依賴的影響&#xff0c;能夠穩定的運行成為了一件比…

c++------類和對象(下)包含了this指針、構造函數、析構函數、拷貝構造等

文章目錄 前言一、this指針1.1、this指針的引出1.2、 this指針的特性 二、類的默認的六個構造函數2.1、構造函數簡述2.2構造函數 三、析構函數3.1、析構函數引出3.2、特點&#xff1a; 四、拷貝構造4.1、引入4.2、特征&#xff1a;4.3、默認拷貝構造函數 總結 前言 在本節中&a…

中國的歷史看中國的經濟發展

從中國的歷史看中國的經濟發展&#xff0c;可以發現其經歷了幾個顯著的階段&#xff0c;每個階段都有其獨特的特點和成就&#xff1a; 古代經濟&#xff1a;中國古代經濟以農業為主&#xff0c;實行井田制&#xff0c;重視水利工程的建設&#xff0c;如都江堰、靈渠等。 商業發…

Compose Multiplatform 1.6.10 發布,解釋一些小問題, Jake 大佬的 Hack

雖然一直比較關注跨平臺開發&#xff0c;但其實我很少寫 Compose Multiplatform 的內容&#xff0c;因為關于 Compose Multiplatform 的使用&#xff0c;其實我并沒在實際生產環境上發布過&#xff0c;但是這個版本確實值得一提&#xff0c;因為該版本包含&#xff1a; iOS Bet…

數據庫(15)——DQL分頁查詢

DQL分頁查詢語法 SELECT 字段列表 FROM 表名 LIMIT 起始索引&#xff0c;查詢記錄數; 注&#xff1a;起始索引從0開始&#xff0c;起始索引&#xff08;查詢頁碼-1&#xff09;*每頁顯示記錄數。 如果查詢的是第一頁&#xff0c;可以省略起始索引。 示例&#xff1a;查詢第一頁…

【考研數學】概率論如何復習?跟誰好?

概率論一定要跟對老師&#xff0c;如果跟對老師&#xff0c;考研基本上能拿滿分 概率論在考研試卷中占比并不大&#xff0c;其中&#xff1a; 高等數學&#xff0c;90分&#xff0c;約占比60%; 線性代數&#xff0c;30分&#xff0c;約占比20%; 概率論與數理統計&#xff0…

hive中的join操作及其數據傾斜

hive中的join操作及其數據傾斜 join操作是一個大數據領域一個常見的話題。歸根結底是由于在數據量超大的情況下&#xff0c;join操作會使內存占用飆升。運算的復雜度也隨之上升。在進行join操作時&#xff0c;也會更容易發生數據傾斜。這些都是需要考慮的問題。 過去了解到很…

每日5題Day15 - LeetCode 71 - 75

每一步向前都是向自己的夢想更近一步&#xff0c;堅持不懈&#xff0c;勇往直前&#xff01; 第一題&#xff1a;71. 簡化路徑 - 力扣&#xff08;LeetCode&#xff09; class Solution {public String simplifyPath(String path) {Deque<String> stack new LinkedList…

mysql的增刪查改(進階)

目錄 一. 更復雜的新增 二. 查詢 2.1 聚合查詢 COUNT SUM AVG MAX MIN 2.1.2 分組查詢 group by 子句 2.1.3 HAVING 2.2 聯合查詢/多表查詢 2.2.1 內連接 2.2.2 外連接 2.2.3 全外連接 2.2.4 自連接 2.2.5 子查詢 2.2.6 合并查詢 一. 更復雜的新增 將從表名查詢到…