[{"data":1,"prerenderedAt":6026},["ShallowReactive",2],{"blog-/blog/leetcode-contest/leetcode-biweekly-191":3,"related-/blog/leetcode-contest/leetcode-biweekly-191":1754},{"id":4,"title":5,"author":6,"body":7,"category":1738,"date":1739,"description":1740,"extension":1741,"image":33,"language":1742,"meta":1743,"navigation":162,"path":1744,"seo":1745,"stem":1746,"tags":1747,"updatedAt":1752,"__hash__":1753},"blog/blog/Leetcode Contest/leetcode-biweekly-191.md","LeetCode Biweekly Contest 191 紀錄","Ting Zhang",{"type":8,"value":9,"toc":1736},"minimark",[10,21,27,261,269,272,277,581,589,592,597,973,981,986,991,994,997,1021,1732],[11,12,13,14],"p",{},"Q1\n",[15,16,20],"a",{"href":17,"rel":18},"https://leetcode.com/problems/count-values-with-equally-spaced-occurrences-i/",[19],"nofollow","Count Values With Equally Spaced Occurrences I",[22,23,24],"blockquote",{},[11,25,26],{},"原本思路：把題目定義的條件刻出來，沒什麼特別的",[28,29,34],"pre",{"className":30,"code":31,"language":32,"meta":33,"style":33},"language-python shiki shiki-themes github-light github-dark","class Solution:\n    def countSpecialIntegers(self, nums: list[int]) -> int:\n        seen = {}\n        res = 0\n        for i, num in enumerate(nums):\n            if num in seen:\n                seen[num].append(i)\n            else:\n                seen[num] = [i]\n\n        # print(seen)\n        for key in seen:\n            if len(seen[key]) == 3 and seen[key][2] - seen[key][1] == seen[key][1] - seen[key][0]:\n                res += 1\n        return res\n","python","",[35,36,37,54,77,89,100,118,132,138,146,157,164,171,183,240,252],"code",{"__ignoreMap":33},[38,39,42,46,50],"span",{"class":40,"line":41},"line",1,[38,43,45],{"class":44},"szBVR","class",[38,47,49],{"class":48},"sScJk"," Solution",[38,51,53],{"class":52},"sVt8B",":\n",[38,55,57,60,63,66,70,73,75],{"class":40,"line":56},2,[38,58,59],{"class":44},"    def",[38,61,62],{"class":48}," countSpecialIntegers",[38,64,65],{"class":52},"(self, nums: list[",[38,67,69],{"class":68},"sj4cs","int",[38,71,72],{"class":52},"]) -> ",[38,74,69],{"class":68},[38,76,53],{"class":52},[38,78,80,83,86],{"class":40,"line":79},3,[38,81,82],{"class":52},"        seen ",[38,84,85],{"class":44},"=",[38,87,88],{"class":52}," {}\n",[38,90,92,95,97],{"class":40,"line":91},4,[38,93,94],{"class":52},"        res ",[38,96,85],{"class":44},[38,98,99],{"class":68}," 0\n",[38,101,103,106,109,112,115],{"class":40,"line":102},5,[38,104,105],{"class":44},"        for",[38,107,108],{"class":52}," i, num ",[38,110,111],{"class":44},"in",[38,113,114],{"class":68}," enumerate",[38,116,117],{"class":52},"(nums):\n",[38,119,121,124,127,129],{"class":40,"line":120},6,[38,122,123],{"class":44},"            if",[38,125,126],{"class":52}," num ",[38,128,111],{"class":44},[38,130,131],{"class":52}," seen:\n",[38,133,135],{"class":40,"line":134},7,[38,136,137],{"class":52},"                seen[num].append(i)\n",[38,139,141,144],{"class":40,"line":140},8,[38,142,143],{"class":44},"            else",[38,145,53],{"class":52},[38,147,149,152,154],{"class":40,"line":148},9,[38,150,151],{"class":52},"                seen[num] ",[38,153,85],{"class":44},[38,155,156],{"class":52}," [i]\n",[38,158,160],{"class":40,"line":159},10,[38,161,163],{"emptyLinePlaceholder":162},true,"\n",[38,165,167],{"class":40,"line":166},11,[38,168,170],{"class":169},"sJ8bj","        # print(seen)\n",[38,172,174,176,179,181],{"class":40,"line":173},12,[38,175,105],{"class":44},[38,177,178],{"class":52}," key ",[38,180,111],{"class":44},[38,182,131],{"class":52},[38,184,186,188,191,194,197,200,203,206,209,212,215,217,220,222,224,226,228,230,232,234,237],{"class":40,"line":185},13,[38,187,123],{"class":44},[38,189,190],{"class":68}," len",[38,192,193],{"class":52},"(seen[key]) ",[38,195,196],{"class":44},"==",[38,198,199],{"class":68}," 3",[38,201,202],{"class":44}," and",[38,204,205],{"class":52}," seen[key][",[38,207,208],{"class":68},"2",[38,210,211],{"class":52},"] ",[38,213,214],{"class":44},"-",[38,216,205],{"class":52},[38,218,219],{"class":68},"1",[38,221,211],{"class":52},[38,223,196],{"class":44},[38,225,205],{"class":52},[38,227,219],{"class":68},[38,229,211],{"class":52},[38,231,214],{"class":44},[38,233,205],{"class":52},[38,235,236],{"class":68},"0",[38,238,239],{"class":52},"]:\n",[38,241,243,246,249],{"class":40,"line":242},14,[38,244,245],{"class":52},"                res ",[38,247,248],{"class":44},"+=",[38,250,251],{"class":68}," 1\n",[38,253,255,258],{"class":40,"line":254},15,[38,256,257],{"class":44},"        return",[38,259,260],{"class":52}," res\n",[11,262,263,264],{},"Q2\n",[15,265,268],{"href":266,"rel":267},"https://leetcode.com/problems/count-values-with-equally-spaced-occurrences-ii/",[19],"Count Values With Equally Spaced Occurrences II",[11,270,271],{},"上一題的進階版，判定條件從 3 個變成 n 個",[22,273,274],{},[11,275,276],{},"原始思路：改成透過 for 迴圈處理判定",[28,278,280],{"className":30,"code":279,"language":32,"meta":33,"style":33},"class Solution:\n    def countSpecialIntegers(self, nums: list[int]) -> int:\n        seen = {}\n        res = 0\n        for i, num in enumerate(nums):\n            if num in seen:\n                seen[num].append(i)\n            else:\n                seen[num] = [i]\n\n        # print(seen)\n        for key in seen:\n            if len(seen[key]) \u003C 3:\n                continue\n\n            first = seen[key][0]\n            second = seen[key][1]\n            gap = first - second\n            fail = False\n            # print(seen[key][2:])\n            for num in seen[key][2:]:\n                # print(second, num, gap)\n                if gap != second - num:\n                    fail = True\n                    break\n                else:\n                    second = num\n            if fail:\n                continue\n            else:\n                res += 1\n        return res\n",[35,281,282,290,306,314,322,334,344,348,354,362,366,370,380,395,400,404,419,433,449,460,466,483,489,509,520,526,534,545,553,558,565,574],{"__ignoreMap":33},[38,283,284,286,288],{"class":40,"line":41},[38,285,45],{"class":44},[38,287,49],{"class":48},[38,289,53],{"class":52},[38,291,292,294,296,298,300,302,304],{"class":40,"line":56},[38,293,59],{"class":44},[38,295,62],{"class":48},[38,297,65],{"class":52},[38,299,69],{"class":68},[38,301,72],{"class":52},[38,303,69],{"class":68},[38,305,53],{"class":52},[38,307,308,310,312],{"class":40,"line":79},[38,309,82],{"class":52},[38,311,85],{"class":44},[38,313,88],{"class":52},[38,315,316,318,320],{"class":40,"line":91},[38,317,94],{"class":52},[38,319,85],{"class":44},[38,321,99],{"class":68},[38,323,324,326,328,330,332],{"class":40,"line":102},[38,325,105],{"class":44},[38,327,108],{"class":52},[38,329,111],{"class":44},[38,331,114],{"class":68},[38,333,117],{"class":52},[38,335,336,338,340,342],{"class":40,"line":120},[38,337,123],{"class":44},[38,339,126],{"class":52},[38,341,111],{"class":44},[38,343,131],{"class":52},[38,345,346],{"class":40,"line":134},[38,347,137],{"class":52},[38,349,350,352],{"class":40,"line":140},[38,351,143],{"class":44},[38,353,53],{"class":52},[38,355,356,358,360],{"class":40,"line":148},[38,357,151],{"class":52},[38,359,85],{"class":44},[38,361,156],{"class":52},[38,363,364],{"class":40,"line":159},[38,365,163],{"emptyLinePlaceholder":162},[38,367,368],{"class":40,"line":166},[38,369,170],{"class":169},[38,371,372,374,376,378],{"class":40,"line":173},[38,373,105],{"class":44},[38,375,178],{"class":52},[38,377,111],{"class":44},[38,379,131],{"class":52},[38,381,382,384,386,388,391,393],{"class":40,"line":185},[38,383,123],{"class":44},[38,385,190],{"class":68},[38,387,193],{"class":52},[38,389,390],{"class":44},"\u003C",[38,392,199],{"class":68},[38,394,53],{"class":52},[38,396,397],{"class":40,"line":242},[38,398,399],{"class":44},"                continue\n",[38,401,402],{"class":40,"line":254},[38,403,163],{"emptyLinePlaceholder":162},[38,405,407,410,412,414,416],{"class":40,"line":406},16,[38,408,409],{"class":52},"            first ",[38,411,85],{"class":44},[38,413,205],{"class":52},[38,415,236],{"class":68},[38,417,418],{"class":52},"]\n",[38,420,422,425,427,429,431],{"class":40,"line":421},17,[38,423,424],{"class":52},"            second ",[38,426,85],{"class":44},[38,428,205],{"class":52},[38,430,219],{"class":68},[38,432,418],{"class":52},[38,434,436,439,441,444,446],{"class":40,"line":435},18,[38,437,438],{"class":52},"            gap ",[38,440,85],{"class":44},[38,442,443],{"class":52}," first ",[38,445,214],{"class":44},[38,447,448],{"class":52}," second\n",[38,450,452,455,457],{"class":40,"line":451},19,[38,453,454],{"class":52},"            fail ",[38,456,85],{"class":44},[38,458,459],{"class":68}," False\n",[38,461,463],{"class":40,"line":462},20,[38,464,465],{"class":169},"            # print(seen[key][2:])\n",[38,467,469,472,474,476,478,480],{"class":40,"line":468},21,[38,470,471],{"class":44},"            for",[38,473,126],{"class":52},[38,475,111],{"class":44},[38,477,205],{"class":52},[38,479,208],{"class":68},[38,481,482],{"class":52},":]:\n",[38,484,486],{"class":40,"line":485},22,[38,487,488],{"class":169},"                # print(second, num, gap)\n",[38,490,492,495,498,501,504,506],{"class":40,"line":491},23,[38,493,494],{"class":44},"                if",[38,496,497],{"class":52}," gap ",[38,499,500],{"class":44},"!=",[38,502,503],{"class":52}," second ",[38,505,214],{"class":44},[38,507,508],{"class":52}," num:\n",[38,510,512,515,517],{"class":40,"line":511},24,[38,513,514],{"class":52},"                    fail ",[38,516,85],{"class":44},[38,518,519],{"class":68}," True\n",[38,521,523],{"class":40,"line":522},25,[38,524,525],{"class":44},"                    break\n",[38,527,529,532],{"class":40,"line":528},26,[38,530,531],{"class":44},"                else",[38,533,53],{"class":52},[38,535,537,540,542],{"class":40,"line":536},27,[38,538,539],{"class":52},"                    second ",[38,541,85],{"class":44},[38,543,544],{"class":52}," num\n",[38,546,548,550],{"class":40,"line":547},28,[38,549,123],{"class":44},[38,551,552],{"class":52}," fail:\n",[38,554,556],{"class":40,"line":555},29,[38,557,399],{"class":44},[38,559,561,563],{"class":40,"line":560},30,[38,562,143],{"class":44},[38,564,53],{"class":52},[38,566,568,570,572],{"class":40,"line":567},31,[38,569,245],{"class":52},[38,571,248],{"class":44},[38,573,251],{"class":68},[38,575,577,579],{"class":40,"line":576},32,[38,578,257],{"class":44},[38,580,260],{"class":52},[11,582,583,584],{},"Q3\n",[15,585,588],{"href":586,"rel":587},"https://leetcode.com/problems/minimum-days-to-score-exactly-n-points/",[19],"Minimum Days to Score Exactly N Points",[11,590,591],{},"題目定義每天可以選擇累加或是休息，來湊出 target number",[22,593,594],{},[11,595,596],{},"原始思路：是先把可以用的選項算出來，然後透過 DP Array 求出達到target number 所需最少的天數",[28,598,600],{"className":30,"code":599,"language":32,"meta":33,"style":33},"class Solution:\n    def minDays(self, n: int) -> int:\n        options = []\n        cal = 0\n        i = 0\n        while cal \u003C= n:\n            i += 1\n            cal = (1 + i) * i // 2\n            if cal > n:\n                break\n            options.append(cal)\n\n        dp = [float(\"inf\")] * (n+1)\n        dp[0] = 0\n\n        for i in range(1, n + 1):\n            for j in range(len(options)):\n                if i - options[j] >= 0:\n                    if i - options[j] != 0 and dp[i - options[j]] != float(\"inf\"):\n                        dp[i] = min(dp[i], dp[i - options[j]] + j + 1 + 1)\n                    else:\n                        dp[i] = min(dp[i], dp[i - options[j]] + j + 1)\n                else:\n                    break\n        return dp[-1]\n",[35,601,602,610,629,639,648,657,671,680,710,721,726,731,735,771,784,788,814,833,852,888,919,926,950,956,960],{"__ignoreMap":33},[38,603,604,606,608],{"class":40,"line":41},[38,605,45],{"class":44},[38,607,49],{"class":48},[38,609,53],{"class":52},[38,611,612,614,617,620,622,625,627],{"class":40,"line":56},[38,613,59],{"class":44},[38,615,616],{"class":48}," minDays",[38,618,619],{"class":52},"(self, n: ",[38,621,69],{"class":68},[38,623,624],{"class":52},") -> ",[38,626,69],{"class":68},[38,628,53],{"class":52},[38,630,631,634,636],{"class":40,"line":79},[38,632,633],{"class":52},"        options ",[38,635,85],{"class":44},[38,637,638],{"class":52}," []\n",[38,640,641,644,646],{"class":40,"line":91},[38,642,643],{"class":52},"        cal ",[38,645,85],{"class":44},[38,647,99],{"class":68},[38,649,650,653,655],{"class":40,"line":102},[38,651,652],{"class":52},"        i ",[38,654,85],{"class":44},[38,656,99],{"class":68},[38,658,659,662,665,668],{"class":40,"line":120},[38,660,661],{"class":44},"        while",[38,663,664],{"class":52}," cal ",[38,666,667],{"class":44},"\u003C=",[38,669,670],{"class":52}," n:\n",[38,672,673,676,678],{"class":40,"line":134},[38,674,675],{"class":52},"            i ",[38,677,248],{"class":44},[38,679,251],{"class":68},[38,681,682,685,687,690,692,695,698,701,704,707],{"class":40,"line":140},[38,683,684],{"class":52},"            cal ",[38,686,85],{"class":44},[38,688,689],{"class":52}," (",[38,691,219],{"class":68},[38,693,694],{"class":44}," +",[38,696,697],{"class":52}," i) ",[38,699,700],{"class":44},"*",[38,702,703],{"class":52}," i ",[38,705,706],{"class":44},"//",[38,708,709],{"class":68}," 2\n",[38,711,712,714,716,719],{"class":40,"line":148},[38,713,123],{"class":44},[38,715,664],{"class":52},[38,717,718],{"class":44},">",[38,720,670],{"class":52},[38,722,723],{"class":40,"line":159},[38,724,725],{"class":44},"                break\n",[38,727,728],{"class":40,"line":166},[38,729,730],{"class":52},"            options.append(cal)\n",[38,732,733],{"class":40,"line":173},[38,734,163],{"emptyLinePlaceholder":162},[38,736,737,740,742,745,748,751,755,758,760,763,766,768],{"class":40,"line":185},[38,738,739],{"class":52},"        dp ",[38,741,85],{"class":44},[38,743,744],{"class":52}," [",[38,746,747],{"class":68},"float",[38,749,750],{"class":52},"(",[38,752,754],{"class":753},"sZZnC","\"inf\"",[38,756,757],{"class":52},")] ",[38,759,700],{"class":44},[38,761,762],{"class":52}," (n",[38,764,765],{"class":44},"+",[38,767,219],{"class":68},[38,769,770],{"class":52},")\n",[38,772,773,776,778,780,782],{"class":40,"line":242},[38,774,775],{"class":52},"        dp[",[38,777,236],{"class":68},[38,779,211],{"class":52},[38,781,85],{"class":44},[38,783,99],{"class":68},[38,785,786],{"class":40,"line":254},[38,787,163],{"emptyLinePlaceholder":162},[38,789,790,792,794,796,799,801,803,806,808,811],{"class":40,"line":406},[38,791,105],{"class":44},[38,793,703],{"class":52},[38,795,111],{"class":44},[38,797,798],{"class":68}," range",[38,800,750],{"class":52},[38,802,219],{"class":68},[38,804,805],{"class":52},", n ",[38,807,765],{"class":44},[38,809,810],{"class":68}," 1",[38,812,813],{"class":52},"):\n",[38,815,816,818,821,823,825,827,830],{"class":40,"line":421},[38,817,471],{"class":44},[38,819,820],{"class":52}," j ",[38,822,111],{"class":44},[38,824,798],{"class":68},[38,826,750],{"class":52},[38,828,829],{"class":68},"len",[38,831,832],{"class":52},"(options)):\n",[38,834,835,837,839,841,844,847,850],{"class":40,"line":435},[38,836,494],{"class":44},[38,838,703],{"class":52},[38,840,214],{"class":44},[38,842,843],{"class":52}," options[j] ",[38,845,846],{"class":44},">=",[38,848,849],{"class":68}," 0",[38,851,53],{"class":52},[38,853,854,857,859,861,863,865,867,869,872,874,877,879,882,884,886],{"class":40,"line":451},[38,855,856],{"class":44},"                    if",[38,858,703],{"class":52},[38,860,214],{"class":44},[38,862,843],{"class":52},[38,864,500],{"class":44},[38,866,849],{"class":68},[38,868,202],{"class":44},[38,870,871],{"class":52}," dp[i ",[38,873,214],{"class":44},[38,875,876],{"class":52}," options[j]] ",[38,878,500],{"class":44},[38,880,881],{"class":68}," float",[38,883,750],{"class":52},[38,885,754],{"class":753},[38,887,813],{"class":52},[38,889,890,893,895,898,901,903,905,907,909,911,913,915,917],{"class":40,"line":462},[38,891,892],{"class":52},"                        dp[i] ",[38,894,85],{"class":44},[38,896,897],{"class":68}," min",[38,899,900],{"class":52},"(dp[i], dp[i ",[38,902,214],{"class":44},[38,904,876],{"class":52},[38,906,765],{"class":44},[38,908,820],{"class":52},[38,910,765],{"class":44},[38,912,810],{"class":68},[38,914,694],{"class":44},[38,916,810],{"class":68},[38,918,770],{"class":52},[38,920,921,924],{"class":40,"line":468},[38,922,923],{"class":44},"                    else",[38,925,53],{"class":52},[38,927,928,930,932,934,936,938,940,942,944,946,948],{"class":40,"line":485},[38,929,892],{"class":52},[38,931,85],{"class":44},[38,933,897],{"class":68},[38,935,900],{"class":52},[38,937,214],{"class":44},[38,939,876],{"class":52},[38,941,765],{"class":44},[38,943,820],{"class":52},[38,945,765],{"class":44},[38,947,810],{"class":68},[38,949,770],{"class":52},[38,951,952,954],{"class":40,"line":491},[38,953,531],{"class":44},[38,955,53],{"class":52},[38,957,958],{"class":40,"line":511},[38,959,525],{"class":44},[38,961,962,964,967,969,971],{"class":40,"line":522},[38,963,257],{"class":44},[38,965,966],{"class":52}," dp[",[38,968,214],{"class":44},[38,970,219],{"class":68},[38,972,418],{"class":52},[11,974,975,976],{},"Q4\n沒寫出來\n",[15,977,980],{"href":978,"rel":979},"https://leetcode.com/problems/count-subarrays-with-distant-sums/",[19],"Count Subarrays with Distant Sums",[22,982,983],{},[11,984,985],{},"原始思路：一頭霧水，大概知道要用 prefix sum 去節省每次計算 sum 的時間，但完全不知道如何具體實作",[22,987,988],{},[11,989,990],{},"最佳解：比想像中還複雜：",[11,992,993],{},"題目要求計算哪些 subarray 滿足總和超過 goal 至少 k",[11,995,996],{},"直接數「distant」不好算。反過來數「non-distant」比較簡單，我們可以透過以下方法來知道 non-distant 的條件",[998,999,1000,1007,1018],"ul",{},[1001,1002,1003,1004],"li",{},"Distant 條件： ",[35,1005,1006],{},"|sum - goal| >= k",[1001,1008,1009,1010,1013,1014,1017],{},"Non-distant 條件： ",[35,1011,1012],{},"goal-k \u003C sum \u003C goal+k","（整數就是 ",[35,1015,1016],{},"[goal-k+1, goal+k-1]","）",[1001,1019,1020],{},"答案 = 全部子陣列數 − non-distant 數量",[28,1022,1024],{"className":30,"code":1023,"language":32,"meta":33,"style":33},"class Solution:\n    def countSubarrays(self, nums: list[int], goal: int, k: int) -> int:\n        size = len(nums)\n        total_subarrays = size * (size + 1) // 2\n        if k == 0:\n            return total_subarrays\n\n        prefix_sum = [0] * (size + 1)\n        for idx in range(size):\n            prefix_sum[idx + 1] = prefix_sum[idx] + nums[idx]\n\n        def count_pairs_with_diff_at_most(threshold: int) -> int:\n            \"\"\"Count pairs (earlier, later) where prefix_sum[later] - prefix_sum[earlier] \u003C= threshold.\"\"\"\n            sorted_copy = list(prefix_sum)\n            merge_buffer = [0] * (size + 1)\n\n            def merge_and_count(left_start: int, right_end: int) -> int:\n                if right_end - left_start \u003C= 1:\n                    return 0\n                mid = (left_start + right_end) // 2\n                count = merge_and_count(left_start, mid) + merge_and_count(mid, right_end)\n\n                scan = left_start\n                for right_idx in range(mid, right_end):\n                    while scan \u003C mid and sorted_copy[scan] \u003C sorted_copy[right_idx] - threshold:\n                        scan += 1\n                    count += mid - scan\n\n                write_pos = left_start\n                left_idx, right_idx = left_start, mid\n                while left_idx \u003C mid and right_idx \u003C right_end:\n                    if sorted_copy[left_idx] \u003C= sorted_copy[right_idx]:\n                        merge_buffer[write_pos] = sorted_copy[left_idx]\n                        left_idx += 1\n                    else:\n                        merge_buffer[write_pos] = sorted_copy[right_idx]\n                        right_idx += 1\n                    write_pos += 1\n                while left_idx \u003C mid:\n                    merge_buffer[write_pos] = sorted_copy[left_idx]\n                    left_idx += 1; write_pos += 1\n                while right_idx \u003C right_end:\n                    merge_buffer[write_pos] = sorted_copy[right_idx]\n                    right_idx += 1; write_pos += 1\n                sorted_copy[left_start:right_end] = merge_buffer[left_start:right_end]\n                return count\n\n            return merge_and_count(0, size + 1)\n\n        upper = goal + k - 1\n        lower = goal - k\n        non_distant_count = (\n            count_pairs_with_diff_at_most(upper)\n            - count_pairs_with_diff_at_most(lower)\n        )\n        return total_subarrays - non_distant_count\n",[35,1025,1026,1034,1061,1073,1099,1113,1121,1125,1148,1162,1183,1187,1206,1211,1224,1247,1251,1275,1293,1300,1319,1334,1338,1348,1363,1392,1401,1415,1419,1428,1438,1459,1471,1482,1492,1499,1509,1519,1529,1541,1551,1568,1579,1588,1604,1615,1624,1629,1648,1653,1672,1687,1698,1704,1713,1719],{"__ignoreMap":33},[38,1027,1028,1030,1032],{"class":40,"line":41},[38,1029,45],{"class":44},[38,1031,49],{"class":48},[38,1033,53],{"class":52},[38,1035,1036,1038,1041,1043,1045,1048,1050,1053,1055,1057,1059],{"class":40,"line":56},[38,1037,59],{"class":44},[38,1039,1040],{"class":48}," countSubarrays",[38,1042,65],{"class":52},[38,1044,69],{"class":68},[38,1046,1047],{"class":52},"], goal: ",[38,1049,69],{"class":68},[38,1051,1052],{"class":52},", k: ",[38,1054,69],{"class":68},[38,1056,624],{"class":52},[38,1058,69],{"class":68},[38,1060,53],{"class":52},[38,1062,1063,1066,1068,1070],{"class":40,"line":79},[38,1064,1065],{"class":52},"        size ",[38,1067,85],{"class":44},[38,1069,190],{"class":68},[38,1071,1072],{"class":52},"(nums)\n",[38,1074,1075,1078,1080,1083,1085,1088,1090,1092,1095,1097],{"class":40,"line":91},[38,1076,1077],{"class":52},"        total_subarrays ",[38,1079,85],{"class":44},[38,1081,1082],{"class":52}," size ",[38,1084,700],{"class":44},[38,1086,1087],{"class":52}," (size ",[38,1089,765],{"class":44},[38,1091,810],{"class":68},[38,1093,1094],{"class":52},") ",[38,1096,706],{"class":44},[38,1098,709],{"class":68},[38,1100,1101,1104,1107,1109,1111],{"class":40,"line":102},[38,1102,1103],{"class":44},"        if",[38,1105,1106],{"class":52}," k ",[38,1108,196],{"class":44},[38,1110,849],{"class":68},[38,1112,53],{"class":52},[38,1114,1115,1118],{"class":40,"line":120},[38,1116,1117],{"class":44},"            return",[38,1119,1120],{"class":52}," total_subarrays\n",[38,1122,1123],{"class":40,"line":134},[38,1124,163],{"emptyLinePlaceholder":162},[38,1126,1127,1130,1132,1134,1136,1138,1140,1142,1144,1146],{"class":40,"line":140},[38,1128,1129],{"class":52},"        prefix_sum ",[38,1131,85],{"class":44},[38,1133,744],{"class":52},[38,1135,236],{"class":68},[38,1137,211],{"class":52},[38,1139,700],{"class":44},[38,1141,1087],{"class":52},[38,1143,765],{"class":44},[38,1145,810],{"class":68},[38,1147,770],{"class":52},[38,1149,1150,1152,1155,1157,1159],{"class":40,"line":148},[38,1151,105],{"class":44},[38,1153,1154],{"class":52}," idx ",[38,1156,111],{"class":44},[38,1158,798],{"class":68},[38,1160,1161],{"class":52},"(size):\n",[38,1163,1164,1167,1169,1171,1173,1175,1178,1180],{"class":40,"line":159},[38,1165,1166],{"class":52},"            prefix_sum[idx ",[38,1168,765],{"class":44},[38,1170,810],{"class":68},[38,1172,211],{"class":52},[38,1174,85],{"class":44},[38,1176,1177],{"class":52}," prefix_sum[idx] ",[38,1179,765],{"class":44},[38,1181,1182],{"class":52}," nums[idx]\n",[38,1184,1185],{"class":40,"line":166},[38,1186,163],{"emptyLinePlaceholder":162},[38,1188,1189,1192,1195,1198,1200,1202,1204],{"class":40,"line":173},[38,1190,1191],{"class":44},"        def",[38,1193,1194],{"class":48}," count_pairs_with_diff_at_most",[38,1196,1197],{"class":52},"(threshold: ",[38,1199,69],{"class":68},[38,1201,624],{"class":52},[38,1203,69],{"class":68},[38,1205,53],{"class":52},[38,1207,1208],{"class":40,"line":185},[38,1209,1210],{"class":753},"            \"\"\"Count pairs (earlier, later) where prefix_sum[later] - prefix_sum[earlier] \u003C= threshold.\"\"\"\n",[38,1212,1213,1216,1218,1221],{"class":40,"line":242},[38,1214,1215],{"class":52},"            sorted_copy ",[38,1217,85],{"class":44},[38,1219,1220],{"class":68}," list",[38,1222,1223],{"class":52},"(prefix_sum)\n",[38,1225,1226,1229,1231,1233,1235,1237,1239,1241,1243,1245],{"class":40,"line":254},[38,1227,1228],{"class":52},"            merge_buffer ",[38,1230,85],{"class":44},[38,1232,744],{"class":52},[38,1234,236],{"class":68},[38,1236,211],{"class":52},[38,1238,700],{"class":44},[38,1240,1087],{"class":52},[38,1242,765],{"class":44},[38,1244,810],{"class":68},[38,1246,770],{"class":52},[38,1248,1249],{"class":40,"line":406},[38,1250,163],{"emptyLinePlaceholder":162},[38,1252,1253,1256,1259,1262,1264,1267,1269,1271,1273],{"class":40,"line":421},[38,1254,1255],{"class":44},"            def",[38,1257,1258],{"class":48}," merge_and_count",[38,1260,1261],{"class":52},"(left_start: ",[38,1263,69],{"class":68},[38,1265,1266],{"class":52},", right_end: ",[38,1268,69],{"class":68},[38,1270,624],{"class":52},[38,1272,69],{"class":68},[38,1274,53],{"class":52},[38,1276,1277,1279,1282,1284,1287,1289,1291],{"class":40,"line":435},[38,1278,494],{"class":44},[38,1280,1281],{"class":52}," right_end ",[38,1283,214],{"class":44},[38,1285,1286],{"class":52}," left_start ",[38,1288,667],{"class":44},[38,1290,810],{"class":68},[38,1292,53],{"class":52},[38,1294,1295,1298],{"class":40,"line":451},[38,1296,1297],{"class":44},"                    return",[38,1299,99],{"class":68},[38,1301,1302,1305,1307,1310,1312,1315,1317],{"class":40,"line":462},[38,1303,1304],{"class":52},"                mid ",[38,1306,85],{"class":44},[38,1308,1309],{"class":52}," (left_start ",[38,1311,765],{"class":44},[38,1313,1314],{"class":52}," right_end) ",[38,1316,706],{"class":44},[38,1318,709],{"class":68},[38,1320,1321,1324,1326,1329,1331],{"class":40,"line":468},[38,1322,1323],{"class":52},"                count ",[38,1325,85],{"class":44},[38,1327,1328],{"class":52}," merge_and_count(left_start, mid) ",[38,1330,765],{"class":44},[38,1332,1333],{"class":52}," merge_and_count(mid, right_end)\n",[38,1335,1336],{"class":40,"line":485},[38,1337,163],{"emptyLinePlaceholder":162},[38,1339,1340,1343,1345],{"class":40,"line":491},[38,1341,1342],{"class":52},"                scan ",[38,1344,85],{"class":44},[38,1346,1347],{"class":52}," left_start\n",[38,1349,1350,1353,1356,1358,1360],{"class":40,"line":511},[38,1351,1352],{"class":44},"                for",[38,1354,1355],{"class":52}," right_idx ",[38,1357,111],{"class":44},[38,1359,798],{"class":68},[38,1361,1362],{"class":52},"(mid, right_end):\n",[38,1364,1365,1368,1371,1373,1376,1379,1382,1384,1387,1389],{"class":40,"line":522},[38,1366,1367],{"class":44},"                    while",[38,1369,1370],{"class":52}," scan ",[38,1372,390],{"class":44},[38,1374,1375],{"class":52}," mid ",[38,1377,1378],{"class":44},"and",[38,1380,1381],{"class":52}," sorted_copy[scan] ",[38,1383,390],{"class":44},[38,1385,1386],{"class":52}," sorted_copy[right_idx] ",[38,1388,214],{"class":44},[38,1390,1391],{"class":52}," threshold:\n",[38,1393,1394,1397,1399],{"class":40,"line":528},[38,1395,1396],{"class":52},"                        scan ",[38,1398,248],{"class":44},[38,1400,251],{"class":68},[38,1402,1403,1406,1408,1410,1412],{"class":40,"line":536},[38,1404,1405],{"class":52},"                    count ",[38,1407,248],{"class":44},[38,1409,1375],{"class":52},[38,1411,214],{"class":44},[38,1413,1414],{"class":52}," scan\n",[38,1416,1417],{"class":40,"line":547},[38,1418,163],{"emptyLinePlaceholder":162},[38,1420,1421,1424,1426],{"class":40,"line":555},[38,1422,1423],{"class":52},"                write_pos ",[38,1425,85],{"class":44},[38,1427,1347],{"class":52},[38,1429,1430,1433,1435],{"class":40,"line":560},[38,1431,1432],{"class":52},"                left_idx, right_idx ",[38,1434,85],{"class":44},[38,1436,1437],{"class":52}," left_start, mid\n",[38,1439,1440,1443,1446,1448,1450,1452,1454,1456],{"class":40,"line":567},[38,1441,1442],{"class":44},"                while",[38,1444,1445],{"class":52}," left_idx ",[38,1447,390],{"class":44},[38,1449,1375],{"class":52},[38,1451,1378],{"class":44},[38,1453,1355],{"class":52},[38,1455,390],{"class":44},[38,1457,1458],{"class":52}," right_end:\n",[38,1460,1461,1463,1466,1468],{"class":40,"line":576},[38,1462,856],{"class":44},[38,1464,1465],{"class":52}," sorted_copy[left_idx] ",[38,1467,667],{"class":44},[38,1469,1470],{"class":52}," sorted_copy[right_idx]:\n",[38,1472,1474,1477,1479],{"class":40,"line":1473},33,[38,1475,1476],{"class":52},"                        merge_buffer[write_pos] ",[38,1478,85],{"class":44},[38,1480,1481],{"class":52}," sorted_copy[left_idx]\n",[38,1483,1485,1488,1490],{"class":40,"line":1484},34,[38,1486,1487],{"class":52},"                        left_idx ",[38,1489,248],{"class":44},[38,1491,251],{"class":68},[38,1493,1495,1497],{"class":40,"line":1494},35,[38,1496,923],{"class":44},[38,1498,53],{"class":52},[38,1500,1502,1504,1506],{"class":40,"line":1501},36,[38,1503,1476],{"class":52},[38,1505,85],{"class":44},[38,1507,1508],{"class":52}," sorted_copy[right_idx]\n",[38,1510,1512,1515,1517],{"class":40,"line":1511},37,[38,1513,1514],{"class":52},"                        right_idx ",[38,1516,248],{"class":44},[38,1518,251],{"class":68},[38,1520,1522,1525,1527],{"class":40,"line":1521},38,[38,1523,1524],{"class":52},"                    write_pos ",[38,1526,248],{"class":44},[38,1528,251],{"class":68},[38,1530,1532,1534,1536,1538],{"class":40,"line":1531},39,[38,1533,1442],{"class":44},[38,1535,1445],{"class":52},[38,1537,390],{"class":44},[38,1539,1540],{"class":52}," mid:\n",[38,1542,1544,1547,1549],{"class":40,"line":1543},40,[38,1545,1546],{"class":52},"                    merge_buffer[write_pos] ",[38,1548,85],{"class":44},[38,1550,1481],{"class":52},[38,1552,1554,1557,1559,1561,1564,1566],{"class":40,"line":1553},41,[38,1555,1556],{"class":52},"                    left_idx ",[38,1558,248],{"class":44},[38,1560,810],{"class":68},[38,1562,1563],{"class":52},"; write_pos ",[38,1565,248],{"class":44},[38,1567,251],{"class":68},[38,1569,1571,1573,1575,1577],{"class":40,"line":1570},42,[38,1572,1442],{"class":44},[38,1574,1355],{"class":52},[38,1576,390],{"class":44},[38,1578,1458],{"class":52},[38,1580,1582,1584,1586],{"class":40,"line":1581},43,[38,1583,1546],{"class":52},[38,1585,85],{"class":44},[38,1587,1508],{"class":52},[38,1589,1591,1594,1596,1598,1600,1602],{"class":40,"line":1590},44,[38,1592,1593],{"class":52},"                    right_idx ",[38,1595,248],{"class":44},[38,1597,810],{"class":68},[38,1599,1563],{"class":52},[38,1601,248],{"class":44},[38,1603,251],{"class":68},[38,1605,1607,1610,1612],{"class":40,"line":1606},45,[38,1608,1609],{"class":52},"                sorted_copy[left_start:right_end] ",[38,1611,85],{"class":44},[38,1613,1614],{"class":52}," merge_buffer[left_start:right_end]\n",[38,1616,1618,1621],{"class":40,"line":1617},46,[38,1619,1620],{"class":44},"                return",[38,1622,1623],{"class":52}," count\n",[38,1625,1627],{"class":40,"line":1626},47,[38,1628,163],{"emptyLinePlaceholder":162},[38,1630,1632,1634,1637,1639,1642,1644,1646],{"class":40,"line":1631},48,[38,1633,1117],{"class":44},[38,1635,1636],{"class":52}," merge_and_count(",[38,1638,236],{"class":68},[38,1640,1641],{"class":52},", size ",[38,1643,765],{"class":44},[38,1645,810],{"class":68},[38,1647,770],{"class":52},[38,1649,1651],{"class":40,"line":1650},49,[38,1652,163],{"emptyLinePlaceholder":162},[38,1654,1656,1659,1661,1664,1666,1668,1670],{"class":40,"line":1655},50,[38,1657,1658],{"class":52},"        upper ",[38,1660,85],{"class":44},[38,1662,1663],{"class":52}," goal ",[38,1665,765],{"class":44},[38,1667,1106],{"class":52},[38,1669,214],{"class":44},[38,1671,251],{"class":68},[38,1673,1675,1678,1680,1682,1684],{"class":40,"line":1674},51,[38,1676,1677],{"class":52},"        lower ",[38,1679,85],{"class":44},[38,1681,1663],{"class":52},[38,1683,214],{"class":44},[38,1685,1686],{"class":52}," k\n",[38,1688,1690,1693,1695],{"class":40,"line":1689},52,[38,1691,1692],{"class":52},"        non_distant_count ",[38,1694,85],{"class":44},[38,1696,1697],{"class":52}," (\n",[38,1699,1701],{"class":40,"line":1700},53,[38,1702,1703],{"class":52},"            count_pairs_with_diff_at_most(upper)\n",[38,1705,1707,1710],{"class":40,"line":1706},54,[38,1708,1709],{"class":44},"            -",[38,1711,1712],{"class":52}," count_pairs_with_diff_at_most(lower)\n",[38,1714,1716],{"class":40,"line":1715},55,[38,1717,1718],{"class":52},"        )\n",[38,1720,1722,1724,1727,1729],{"class":40,"line":1721},56,[38,1723,257],{"class":44},[38,1725,1726],{"class":52}," total_subarrays ",[38,1728,214],{"class":44},[38,1730,1731],{"class":52}," non_distant_count\n",[1733,1734,1735],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":33,"searchDepth":56,"depth":56,"links":1737},[],"技術","2026-09-19","Biweekly Contest 191 過程思路與心得","md","zh-TW",{},"/blog/leetcode-contest/leetcode-biweekly-191",{"title":5,"description":1740},"blog/Leetcode Contest/leetcode-biweekly-191",[1748,1749,1750,1751],"LeetCode","Contest","Algorithm","Python",null,"SKR-x3lJV2WMUITpWbZ2MVMWQefxCIhMhEh_NBoQI0g",[1755,3527,5632],{"id":1756,"title":1757,"author":6,"body":1758,"category":1738,"date":1739,"description":3520,"extension":1741,"image":33,"language":1742,"meta":3521,"navigation":162,"path":3522,"seo":3523,"stem":3524,"tags":3525,"updatedAt":1752,"__hash__":3526},"blog/blog/Leetcode Contest/leetcode-weekly-591.md","LeetCode Weekly Contest 591 解錄",{"type":8,"value":1759,"toc":3518},[1760,1767,1772,2014,2019,2182,2189,2200,2205,2221,2643,2650,2653,2674,2683,2688,2826,2830,3131,3139,3142,3162,3176,3180,3340,3344,3515],[11,1761,13,1762],{},[15,1763,1766],{"href":1764,"rel":1765},"https://leetcode.com/problems/cyclically-shift-rows-and-columns/",[19],"Cyclically Shift Rows and Columns",[22,1768,1769],{},[11,1770,1771],{},"原始思路：直接把題義內容刻出來\n依照 rowShift / colShift 去對 grid 做 inplace 替換",[28,1773,1775],{"className":30,"code":1774,"language":32,"meta":33,"style":33},"# Space: O(n)\n# Time: O(n^3)\nclass Solution:\n    def cyclicShift(self, n: int, grid: list[list[int]], rowShift: list[int], colShift: list[int]) -> list[list[int]]:\n        for i in range(n):\n            # grid[i] left shift rowShift[i] times\n            for _ in range(rowShift[i]):\n                grid[i] = grid[i][1:] + grid[i][:1]\n\n        # print(grid)\n        for j in range(n):\n            # grid[i][j] upward shift rowShift[i] times\n            for _ in range(colShift[j]):\n                tmp = grid[0][j]\n                for i in range(n):\n                    if i \u003C n - 1:\n                        grid[i][j] = grid[i + 1][j]\n                    else:\n                        grid[i][j] = tmp\n\n        # print(grid)\n        return grid\n",[35,1776,1777,1782,1787,1795,1829,1842,1847,1861,1885,1889,1894,1906,1911,1924,1939,1951,1968,1984,1990,1999,2003,2007],{"__ignoreMap":33},[38,1778,1779],{"class":40,"line":41},[38,1780,1781],{"class":169},"# Space: O(n)\n",[38,1783,1784],{"class":40,"line":56},[38,1785,1786],{"class":169},"# Time: O(n^3)\n",[38,1788,1789,1791,1793],{"class":40,"line":79},[38,1790,45],{"class":44},[38,1792,49],{"class":48},[38,1794,53],{"class":52},[38,1796,1797,1799,1802,1804,1806,1809,1811,1814,1816,1819,1821,1824,1826],{"class":40,"line":91},[38,1798,59],{"class":44},[38,1800,1801],{"class":48}," cyclicShift",[38,1803,619],{"class":52},[38,1805,69],{"class":68},[38,1807,1808],{"class":52},", grid: list[list[",[38,1810,69],{"class":68},[38,1812,1813],{"class":52},"]], rowShift: list[",[38,1815,69],{"class":68},[38,1817,1818],{"class":52},"], colShift: list[",[38,1820,69],{"class":68},[38,1822,1823],{"class":52},"]) -> list[list[",[38,1825,69],{"class":68},[38,1827,1828],{"class":52},"]]:\n",[38,1830,1831,1833,1835,1837,1839],{"class":40,"line":102},[38,1832,105],{"class":44},[38,1834,703],{"class":52},[38,1836,111],{"class":44},[38,1838,798],{"class":68},[38,1840,1841],{"class":52},"(n):\n",[38,1843,1844],{"class":40,"line":120},[38,1845,1846],{"class":169},"            # grid[i] left shift rowShift[i] times\n",[38,1848,1849,1851,1854,1856,1858],{"class":40,"line":134},[38,1850,471],{"class":44},[38,1852,1853],{"class":52}," _ ",[38,1855,111],{"class":44},[38,1857,798],{"class":68},[38,1859,1860],{"class":52},"(rowShift[i]):\n",[38,1862,1863,1866,1868,1871,1873,1876,1878,1881,1883],{"class":40,"line":140},[38,1864,1865],{"class":52},"                grid[i] ",[38,1867,85],{"class":44},[38,1869,1870],{"class":52}," grid[i][",[38,1872,219],{"class":68},[38,1874,1875],{"class":52},":] ",[38,1877,765],{"class":44},[38,1879,1880],{"class":52}," grid[i][:",[38,1882,219],{"class":68},[38,1884,418],{"class":52},[38,1886,1887],{"class":40,"line":148},[38,1888,163],{"emptyLinePlaceholder":162},[38,1890,1891],{"class":40,"line":159},[38,1892,1893],{"class":169},"        # print(grid)\n",[38,1895,1896,1898,1900,1902,1904],{"class":40,"line":166},[38,1897,105],{"class":44},[38,1899,820],{"class":52},[38,1901,111],{"class":44},[38,1903,798],{"class":68},[38,1905,1841],{"class":52},[38,1907,1908],{"class":40,"line":173},[38,1909,1910],{"class":169},"            # grid[i][j] upward shift rowShift[i] times\n",[38,1912,1913,1915,1917,1919,1921],{"class":40,"line":185},[38,1914,471],{"class":44},[38,1916,1853],{"class":52},[38,1918,111],{"class":44},[38,1920,798],{"class":68},[38,1922,1923],{"class":52},"(colShift[j]):\n",[38,1925,1926,1929,1931,1934,1936],{"class":40,"line":242},[38,1927,1928],{"class":52},"                tmp ",[38,1930,85],{"class":44},[38,1932,1933],{"class":52}," grid[",[38,1935,236],{"class":68},[38,1937,1938],{"class":52},"][j]\n",[38,1940,1941,1943,1945,1947,1949],{"class":40,"line":254},[38,1942,1352],{"class":44},[38,1944,703],{"class":52},[38,1946,111],{"class":44},[38,1948,798],{"class":68},[38,1950,1841],{"class":52},[38,1952,1953,1955,1957,1959,1962,1964,1966],{"class":40,"line":406},[38,1954,856],{"class":44},[38,1956,703],{"class":52},[38,1958,390],{"class":44},[38,1960,1961],{"class":52}," n ",[38,1963,214],{"class":44},[38,1965,810],{"class":68},[38,1967,53],{"class":52},[38,1969,1970,1973,1975,1978,1980,1982],{"class":40,"line":421},[38,1971,1972],{"class":52},"                        grid[i][j] ",[38,1974,85],{"class":44},[38,1976,1977],{"class":52}," grid[i ",[38,1979,765],{"class":44},[38,1981,810],{"class":68},[38,1983,1938],{"class":52},[38,1985,1986,1988],{"class":40,"line":435},[38,1987,923],{"class":44},[38,1989,53],{"class":52},[38,1991,1992,1994,1996],{"class":40,"line":451},[38,1993,1972],{"class":52},[38,1995,85],{"class":44},[38,1997,1998],{"class":52}," tmp\n",[38,2000,2001],{"class":40,"line":462},[38,2002,163],{"emptyLinePlaceholder":162},[38,2004,2005],{"class":40,"line":468},[38,2006,1893],{"class":169},[38,2008,2009,2011],{"class":40,"line":485},[38,2010,257],{"class":44},[38,2012,2013],{"class":52}," grid\n",[22,2015,2016],{},[11,2017,2018],{},"最佳解：用空間複雜度換時間複雜度，建立 result grid\n透過 mod 來取餘數，這樣就可以直接知道當前位置 (i,j) at result 的來源位置  (i,j) at grid",[28,2020,2022],{"className":30,"code":2021,"language":32,"meta":33,"style":33},"# Space: O(n^2)\n# Time: O(n^2)\nclass Solution:\n    def shiftGrid(self, n: int, grid: list[list[int]], rowShift: list[int], colShift: list[int]) -> list[list[int]]:\n        result = [[0] * n for _ in range(n)]\n        for i in range(n):\n            for j in range(n):\n                si = (i + colShift[j]) % n\n                sj = (j + rowShift[si]) % n\n                result[i][j] = grid[si][sj]\n        return result\n",[35,2023,2024,2029,2034,2042,2071,2101,2113,2125,2146,2165,2175],{"__ignoreMap":33},[38,2025,2026],{"class":40,"line":41},[38,2027,2028],{"class":169},"# Space: O(n^2)\n",[38,2030,2031],{"class":40,"line":56},[38,2032,2033],{"class":169},"# Time: O(n^2)\n",[38,2035,2036,2038,2040],{"class":40,"line":79},[38,2037,45],{"class":44},[38,2039,49],{"class":48},[38,2041,53],{"class":52},[38,2043,2044,2046,2049,2051,2053,2055,2057,2059,2061,2063,2065,2067,2069],{"class":40,"line":91},[38,2045,59],{"class":44},[38,2047,2048],{"class":48}," shiftGrid",[38,2050,619],{"class":52},[38,2052,69],{"class":68},[38,2054,1808],{"class":52},[38,2056,69],{"class":68},[38,2058,1813],{"class":52},[38,2060,69],{"class":68},[38,2062,1818],{"class":52},[38,2064,69],{"class":68},[38,2066,1823],{"class":52},[38,2068,69],{"class":68},[38,2070,1828],{"class":52},[38,2072,2073,2076,2078,2081,2083,2085,2087,2089,2092,2094,2096,2098],{"class":40,"line":102},[38,2074,2075],{"class":52},"        result ",[38,2077,85],{"class":44},[38,2079,2080],{"class":52}," [[",[38,2082,236],{"class":68},[38,2084,211],{"class":52},[38,2086,700],{"class":44},[38,2088,1961],{"class":52},[38,2090,2091],{"class":44},"for",[38,2093,1853],{"class":52},[38,2095,111],{"class":44},[38,2097,798],{"class":68},[38,2099,2100],{"class":52},"(n)]\n",[38,2102,2103,2105,2107,2109,2111],{"class":40,"line":120},[38,2104,105],{"class":44},[38,2106,703],{"class":52},[38,2108,111],{"class":44},[38,2110,798],{"class":68},[38,2112,1841],{"class":52},[38,2114,2115,2117,2119,2121,2123],{"class":40,"line":134},[38,2116,471],{"class":44},[38,2118,820],{"class":52},[38,2120,111],{"class":44},[38,2122,798],{"class":68},[38,2124,1841],{"class":52},[38,2126,2127,2130,2132,2135,2137,2140,2143],{"class":40,"line":140},[38,2128,2129],{"class":52},"                si ",[38,2131,85],{"class":44},[38,2133,2134],{"class":52}," (i ",[38,2136,765],{"class":44},[38,2138,2139],{"class":52}," colShift[j]) ",[38,2141,2142],{"class":44},"%",[38,2144,2145],{"class":52}," n\n",[38,2147,2148,2151,2153,2156,2158,2161,2163],{"class":40,"line":148},[38,2149,2150],{"class":52},"                sj ",[38,2152,85],{"class":44},[38,2154,2155],{"class":52}," (j ",[38,2157,765],{"class":44},[38,2159,2160],{"class":52}," rowShift[si]) ",[38,2162,2142],{"class":44},[38,2164,2145],{"class":52},[38,2166,2167,2170,2172],{"class":40,"line":159},[38,2168,2169],{"class":52},"                result[i][j] ",[38,2171,85],{"class":44},[38,2173,2174],{"class":52}," grid[si][sj]\n",[38,2176,2177,2179],{"class":40,"line":166},[38,2178,257],{"class":44},[38,2180,2181],{"class":52}," result\n",[11,2183,263,2184],{},[15,2185,2188],{"href":2186,"rel":2187},"https://leetcode.com/problems/minimum-operations-to-make-every-element-palindromic/",[19],"Minimum Operations to Make Every Element Palindromic",[998,2190,2191,2194,2197],{},[1001,2192,2193],{},"目標：nums 內每個元素都變成正的回文數（如 8、11、121、1221）",[1001,2195,2196],{},"每次操作：選一個元素，只能+2 或 -2",[1001,2198,2199],{},"求最少操作次數",[22,2201,2202],{},[11,2203,2204],{},"原始思路：思考回文數字應該要怎麼判斷，但沒有想到僅有窮舉這招",[22,2206,2207,2210],{},[11,2208,2209],{},"最佳解：",[998,2211,2212,2215,2218],{},[1001,2213,2214],{},"先找出 constraint 內所有回文數字，依照奇偶分組 (因為操作只能 +-2, 所以奇偶不會改變)",[1001,2216,2217],{},"透過 Binary Search 找最近 id 對應的回文數字",[1001,2219,2220],{},"求該 num 所需步數",[28,2222,2224],{"className":30,"code":2223,"language":32,"meta":33,"style":33},"from bisect import bisect_left\n\nMAX_VALUE = 10 ** 9\npalindromes_by_parity = [[], []]\n\nfor prefix_num in range(1, 100_000):\n    prefix = str(prefix_num)\n    odd_length = prefix[:-1] + prefix[::-1]\n    even_length = prefix + prefix[::-1]\n\n    odd_palindrome = int(odd_length)\n    even_palindrome = int(even_length)\n\n    if odd_palindrome \u003C MAX_VALUE:\n        palindromes_by_parity[odd_palindrome & 1].append(odd_palindrome)\n    if even_palindrome \u003C MAX_VALUE:\n        palindromes_by_parity[even_palindrome & 1].append(even_palindrome)\n\npalindromes_by_parity[0].sort()\npalindromes_by_parity[1].sort()\n\n\nclass Solution:\n    def minOperations(self, nums: list[int]) -> int:\n        total_ops = 0\n        for num in nums:\n            candidates = palindromes_by_parity[num & 1]\n            idx = bisect_left(candidates, num)\n            if idx >= len(candidates):\n                idx = len(candidates) - 1\n            closest_dist = min(\n                abs(num - candidates[idx]),\n                abs(num - candidates[idx - 1]),\n            )\n            total_ops += closest_dist // 2\n        return total_ops\n",[35,2225,2226,2240,2244,2261,2271,2275,2298,2311,2338,2358,2362,2375,2387,2391,2406,2419,2432,2444,2448,2458,2466,2470,2474,2482,2499,2508,2519,2535,2545,2558,2574,2586,2599,2617,2622,2636],{"__ignoreMap":33},[38,2227,2228,2231,2234,2237],{"class":40,"line":41},[38,2229,2230],{"class":44},"from",[38,2232,2233],{"class":52}," bisect ",[38,2235,2236],{"class":44},"import",[38,2238,2239],{"class":52}," bisect_left\n",[38,2241,2242],{"class":40,"line":56},[38,2243,163],{"emptyLinePlaceholder":162},[38,2245,2246,2249,2252,2255,2258],{"class":40,"line":79},[38,2247,2248],{"class":68},"MAX_VALUE",[38,2250,2251],{"class":44}," =",[38,2253,2254],{"class":68}," 10",[38,2256,2257],{"class":44}," **",[38,2259,2260],{"class":68}," 9\n",[38,2262,2263,2266,2268],{"class":40,"line":91},[38,2264,2265],{"class":52},"palindromes_by_parity ",[38,2267,85],{"class":44},[38,2269,2270],{"class":52}," [[], []]\n",[38,2272,2273],{"class":40,"line":102},[38,2274,163],{"emptyLinePlaceholder":162},[38,2276,2277,2279,2282,2284,2286,2288,2290,2293,2296],{"class":40,"line":120},[38,2278,2091],{"class":44},[38,2280,2281],{"class":52}," prefix_num ",[38,2283,111],{"class":44},[38,2285,798],{"class":68},[38,2287,750],{"class":52},[38,2289,219],{"class":68},[38,2291,2292],{"class":52},", ",[38,2294,2295],{"class":68},"100_000",[38,2297,813],{"class":52},[38,2299,2300,2303,2305,2308],{"class":40,"line":134},[38,2301,2302],{"class":52},"    prefix ",[38,2304,85],{"class":44},[38,2306,2307],{"class":68}," str",[38,2309,2310],{"class":52},"(prefix_num)\n",[38,2312,2313,2316,2318,2321,2323,2325,2327,2329,2332,2334,2336],{"class":40,"line":140},[38,2314,2315],{"class":52},"    odd_length ",[38,2317,85],{"class":44},[38,2319,2320],{"class":52}," prefix[:",[38,2322,214],{"class":44},[38,2324,219],{"class":68},[38,2326,211],{"class":52},[38,2328,765],{"class":44},[38,2330,2331],{"class":52}," prefix[::",[38,2333,214],{"class":44},[38,2335,219],{"class":68},[38,2337,418],{"class":52},[38,2339,2340,2343,2345,2348,2350,2352,2354,2356],{"class":40,"line":148},[38,2341,2342],{"class":52},"    even_length ",[38,2344,85],{"class":44},[38,2346,2347],{"class":52}," prefix ",[38,2349,765],{"class":44},[38,2351,2331],{"class":52},[38,2353,214],{"class":44},[38,2355,219],{"class":68},[38,2357,418],{"class":52},[38,2359,2360],{"class":40,"line":159},[38,2361,163],{"emptyLinePlaceholder":162},[38,2363,2364,2367,2369,2372],{"class":40,"line":166},[38,2365,2366],{"class":52},"    odd_palindrome ",[38,2368,85],{"class":44},[38,2370,2371],{"class":68}," int",[38,2373,2374],{"class":52},"(odd_length)\n",[38,2376,2377,2380,2382,2384],{"class":40,"line":173},[38,2378,2379],{"class":52},"    even_palindrome ",[38,2381,85],{"class":44},[38,2383,2371],{"class":68},[38,2385,2386],{"class":52},"(even_length)\n",[38,2388,2389],{"class":40,"line":185},[38,2390,163],{"emptyLinePlaceholder":162},[38,2392,2393,2396,2399,2401,2404],{"class":40,"line":242},[38,2394,2395],{"class":44},"    if",[38,2397,2398],{"class":52}," odd_palindrome ",[38,2400,390],{"class":44},[38,2402,2403],{"class":68}," MAX_VALUE",[38,2405,53],{"class":52},[38,2407,2408,2411,2414,2416],{"class":40,"line":254},[38,2409,2410],{"class":52},"        palindromes_by_parity[odd_palindrome ",[38,2412,2413],{"class":44},"&",[38,2415,810],{"class":68},[38,2417,2418],{"class":52},"].append(odd_palindrome)\n",[38,2420,2421,2423,2426,2428,2430],{"class":40,"line":406},[38,2422,2395],{"class":44},[38,2424,2425],{"class":52}," even_palindrome ",[38,2427,390],{"class":44},[38,2429,2403],{"class":68},[38,2431,53],{"class":52},[38,2433,2434,2437,2439,2441],{"class":40,"line":421},[38,2435,2436],{"class":52},"        palindromes_by_parity[even_palindrome ",[38,2438,2413],{"class":44},[38,2440,810],{"class":68},[38,2442,2443],{"class":52},"].append(even_palindrome)\n",[38,2445,2446],{"class":40,"line":435},[38,2447,163],{"emptyLinePlaceholder":162},[38,2449,2450,2453,2455],{"class":40,"line":451},[38,2451,2452],{"class":52},"palindromes_by_parity[",[38,2454,236],{"class":68},[38,2456,2457],{"class":52},"].sort()\n",[38,2459,2460,2462,2464],{"class":40,"line":462},[38,2461,2452],{"class":52},[38,2463,219],{"class":68},[38,2465,2457],{"class":52},[38,2467,2468],{"class":40,"line":468},[38,2469,163],{"emptyLinePlaceholder":162},[38,2471,2472],{"class":40,"line":485},[38,2473,163],{"emptyLinePlaceholder":162},[38,2475,2476,2478,2480],{"class":40,"line":491},[38,2477,45],{"class":44},[38,2479,49],{"class":48},[38,2481,53],{"class":52},[38,2483,2484,2486,2489,2491,2493,2495,2497],{"class":40,"line":511},[38,2485,59],{"class":44},[38,2487,2488],{"class":48}," minOperations",[38,2490,65],{"class":52},[38,2492,69],{"class":68},[38,2494,72],{"class":52},[38,2496,69],{"class":68},[38,2498,53],{"class":52},[38,2500,2501,2504,2506],{"class":40,"line":522},[38,2502,2503],{"class":52},"        total_ops ",[38,2505,85],{"class":44},[38,2507,99],{"class":68},[38,2509,2510,2512,2514,2516],{"class":40,"line":528},[38,2511,105],{"class":44},[38,2513,126],{"class":52},[38,2515,111],{"class":44},[38,2517,2518],{"class":52}," nums:\n",[38,2520,2521,2524,2526,2529,2531,2533],{"class":40,"line":536},[38,2522,2523],{"class":52},"            candidates ",[38,2525,85],{"class":44},[38,2527,2528],{"class":52}," palindromes_by_parity[num ",[38,2530,2413],{"class":44},[38,2532,810],{"class":68},[38,2534,418],{"class":52},[38,2536,2537,2540,2542],{"class":40,"line":547},[38,2538,2539],{"class":52},"            idx ",[38,2541,85],{"class":44},[38,2543,2544],{"class":52}," bisect_left(candidates, num)\n",[38,2546,2547,2549,2551,2553,2555],{"class":40,"line":555},[38,2548,123],{"class":44},[38,2550,1154],{"class":52},[38,2552,846],{"class":44},[38,2554,190],{"class":68},[38,2556,2557],{"class":52},"(candidates):\n",[38,2559,2560,2563,2565,2567,2570,2572],{"class":40,"line":560},[38,2561,2562],{"class":52},"                idx ",[38,2564,85],{"class":44},[38,2566,190],{"class":68},[38,2568,2569],{"class":52},"(candidates) ",[38,2571,214],{"class":44},[38,2573,251],{"class":68},[38,2575,2576,2579,2581,2583],{"class":40,"line":567},[38,2577,2578],{"class":52},"            closest_dist ",[38,2580,85],{"class":44},[38,2582,897],{"class":68},[38,2584,2585],{"class":52},"(\n",[38,2587,2588,2591,2594,2596],{"class":40,"line":576},[38,2589,2590],{"class":68},"                abs",[38,2592,2593],{"class":52},"(num ",[38,2595,214],{"class":44},[38,2597,2598],{"class":52}," candidates[idx]),\n",[38,2600,2601,2603,2605,2607,2610,2612,2614],{"class":40,"line":1473},[38,2602,2590],{"class":68},[38,2604,2593],{"class":52},[38,2606,214],{"class":44},[38,2608,2609],{"class":52}," candidates[idx ",[38,2611,214],{"class":44},[38,2613,810],{"class":68},[38,2615,2616],{"class":52},"]),\n",[38,2618,2619],{"class":40,"line":1484},[38,2620,2621],{"class":52},"            )\n",[38,2623,2624,2627,2629,2632,2634],{"class":40,"line":1494},[38,2625,2626],{"class":52},"            total_ops ",[38,2628,248],{"class":44},[38,2630,2631],{"class":52}," closest_dist ",[38,2633,706],{"class":44},[38,2635,709],{"class":68},[38,2637,2638,2640],{"class":40,"line":1501},[38,2639,257],{"class":44},[38,2641,2642],{"class":52}," total_ops\n",[11,2644,583,2645],{},[15,2646,2649],{"href":2647,"rel":2648},"https://leetcode.com/problems/count-shadow-pairs-i/",[19],"Count Shadow Pairs I",[11,2651,2652],{},"題目敘述我覺得蠻容易把自己繞昏的，總之我們在找一個 index pair，符合以下條件",[2654,2655,2656,2661,2667],"ol",{},[1001,2657,2658],{},[35,2659,2660],{},"i \u003C j",[1001,2662,2663,2666],{},[35,2664,2665],{},"nums[i] \u003C nums[j]","（左邊比右邊小）",[1001,2668,2669,2670,2673],{},"i 和 j 之間沒有任何元素比 ",[35,2671,2672],{},"nums[i]"," 更小",[11,2675,2676,2677,2679,2680,2682],{},"我們可以做一次 for 迴圈並維護一個 Stack，檢查 ",[35,2678,2672],{}," 右邊是否有比 ",[35,2681,2672],{}," 更小的值\n也就是説一個 x 進來以後，我們用 for 迴圈檢查 top of stack 是否 > x, 如果是的話我們就把 top of stack pop 掉\n完成以後我們可以說 stack 內 \"去除 = x 的\" 所有元素都是一個合法的 i, 當前的 x index 為合法的 j，這時候的 i, j 都是合法的 pair",[22,2684,2685],{},[11,2686,2687],{},"原本思路：沒想到什麼特別的，依照題目內容刻了一個 time n^2 會 TLE 的解",[28,2689,2691],{"className":30,"code":2690,"language":32,"meta":33,"style":33},"# TLE\nclass Solution:\n    def shadowPairs(self, nums: list[int]) -> int:\n        n = len(nums)\n        res = 0\n        for i in range(n):\n            for j in range(n):\n                if j \u003C= i:\n                    continue\n                if nums[j] \u003C nums[i]:\n                    break\n                if nums[j] \u003C= nums[i]:\n                    continue\n                res += 1\n        return res\n\n",[35,2692,2693,2698,2706,2723,2734,2742,2754,2766,2777,2782,2794,2798,2808,2812,2820],{"__ignoreMap":33},[38,2694,2695],{"class":40,"line":41},[38,2696,2697],{"class":169},"# TLE\n",[38,2699,2700,2702,2704],{"class":40,"line":56},[38,2701,45],{"class":44},[38,2703,49],{"class":48},[38,2705,53],{"class":52},[38,2707,2708,2710,2713,2715,2717,2719,2721],{"class":40,"line":79},[38,2709,59],{"class":44},[38,2711,2712],{"class":48}," shadowPairs",[38,2714,65],{"class":52},[38,2716,69],{"class":68},[38,2718,72],{"class":52},[38,2720,69],{"class":68},[38,2722,53],{"class":52},[38,2724,2725,2728,2730,2732],{"class":40,"line":91},[38,2726,2727],{"class":52},"        n ",[38,2729,85],{"class":44},[38,2731,190],{"class":68},[38,2733,1072],{"class":52},[38,2735,2736,2738,2740],{"class":40,"line":102},[38,2737,94],{"class":52},[38,2739,85],{"class":44},[38,2741,99],{"class":68},[38,2743,2744,2746,2748,2750,2752],{"class":40,"line":120},[38,2745,105],{"class":44},[38,2747,703],{"class":52},[38,2749,111],{"class":44},[38,2751,798],{"class":68},[38,2753,1841],{"class":52},[38,2755,2756,2758,2760,2762,2764],{"class":40,"line":134},[38,2757,471],{"class":44},[38,2759,820],{"class":52},[38,2761,111],{"class":44},[38,2763,798],{"class":68},[38,2765,1841],{"class":52},[38,2767,2768,2770,2772,2774],{"class":40,"line":140},[38,2769,494],{"class":44},[38,2771,820],{"class":52},[38,2773,667],{"class":44},[38,2775,2776],{"class":52}," i:\n",[38,2778,2779],{"class":40,"line":148},[38,2780,2781],{"class":44},"                    continue\n",[38,2783,2784,2786,2789,2791],{"class":40,"line":159},[38,2785,494],{"class":44},[38,2787,2788],{"class":52}," nums[j] ",[38,2790,390],{"class":44},[38,2792,2793],{"class":52}," nums[i]:\n",[38,2795,2796],{"class":40,"line":166},[38,2797,525],{"class":44},[38,2799,2800,2802,2804,2806],{"class":40,"line":173},[38,2801,494],{"class":44},[38,2803,2788],{"class":52},[38,2805,667],{"class":44},[38,2807,2793],{"class":52},[38,2809,2810],{"class":40,"line":185},[38,2811,2781],{"class":44},[38,2813,2814,2816,2818],{"class":40,"line":242},[38,2815,245],{"class":52},[38,2817,248],{"class":44},[38,2819,251],{"class":68},[38,2821,2822,2824],{"class":40,"line":254},[38,2823,257],{"class":44},[38,2825,260],{"class":52},[22,2827,2828],{},[11,2829,2209],{},[28,2831,2833],{"className":30,"code":2832,"language":32,"meta":33,"style":33},"class Solution:\n    def countShadowPairs(self, nums: list[int]) -> int:\n        stack = []          # (value, count), non-decreasing\n        total_in_stack = 0  # sum of all counts in the stack\n        ans = 0\n\n        for x in nums:\n            # Pop elements > x — they can never pair again\n            while stack and stack[-1][0] > x:\n                total_in_stack -= stack.pop()[1]\n\n            # Count elements strictly \u003C x\n            if stack and stack[-1][0] == x:\n                ans += total_in_stack - stack[-1][1]\n            else:\n                ans += total_in_stack\n\n            # Push x (merge if top has same value)\n            if stack and stack[-1][0] == x:\n                stack[-1] = (x, stack[-1][1] + 1)\n            else:\n                stack.append((x, 1))\n            total_in_stack += 1\n\n        return ans\n",[35,2834,2835,2843,2860,2873,2885,2894,2898,2909,2914,2943,2958,2962,2967,2991,3015,3021,3030,3034,3039,3063,3095,3101,3111,3120,3124],{"__ignoreMap":33},[38,2836,2837,2839,2841],{"class":40,"line":41},[38,2838,45],{"class":44},[38,2840,49],{"class":48},[38,2842,53],{"class":52},[38,2844,2845,2847,2850,2852,2854,2856,2858],{"class":40,"line":56},[38,2846,59],{"class":44},[38,2848,2849],{"class":48}," countShadowPairs",[38,2851,65],{"class":52},[38,2853,69],{"class":68},[38,2855,72],{"class":52},[38,2857,69],{"class":68},[38,2859,53],{"class":52},[38,2861,2862,2865,2867,2870],{"class":40,"line":79},[38,2863,2864],{"class":52},"        stack ",[38,2866,85],{"class":44},[38,2868,2869],{"class":52}," []          ",[38,2871,2872],{"class":169},"# (value, count), non-decreasing\n",[38,2874,2875,2878,2880,2882],{"class":40,"line":91},[38,2876,2877],{"class":52},"        total_in_stack ",[38,2879,85],{"class":44},[38,2881,849],{"class":68},[38,2883,2884],{"class":169},"  # sum of all counts in the stack\n",[38,2886,2887,2890,2892],{"class":40,"line":102},[38,2888,2889],{"class":52},"        ans ",[38,2891,85],{"class":44},[38,2893,99],{"class":68},[38,2895,2896],{"class":40,"line":120},[38,2897,163],{"emptyLinePlaceholder":162},[38,2899,2900,2902,2905,2907],{"class":40,"line":134},[38,2901,105],{"class":44},[38,2903,2904],{"class":52}," x ",[38,2906,111],{"class":44},[38,2908,2518],{"class":52},[38,2910,2911],{"class":40,"line":140},[38,2912,2913],{"class":169},"            # Pop elements > x — they can never pair again\n",[38,2915,2916,2919,2922,2924,2927,2929,2931,2934,2936,2938,2940],{"class":40,"line":148},[38,2917,2918],{"class":44},"            while",[38,2920,2921],{"class":52}," stack ",[38,2923,1378],{"class":44},[38,2925,2926],{"class":52}," stack[",[38,2928,214],{"class":44},[38,2930,219],{"class":68},[38,2932,2933],{"class":52},"][",[38,2935,236],{"class":68},[38,2937,211],{"class":52},[38,2939,718],{"class":44},[38,2941,2942],{"class":52}," x:\n",[38,2944,2945,2948,2951,2954,2956],{"class":40,"line":159},[38,2946,2947],{"class":52},"                total_in_stack ",[38,2949,2950],{"class":44},"-=",[38,2952,2953],{"class":52}," stack.pop()[",[38,2955,219],{"class":68},[38,2957,418],{"class":52},[38,2959,2960],{"class":40,"line":166},[38,2961,163],{"emptyLinePlaceholder":162},[38,2963,2964],{"class":40,"line":173},[38,2965,2966],{"class":169},"            # Count elements strictly \u003C x\n",[38,2968,2969,2971,2973,2975,2977,2979,2981,2983,2985,2987,2989],{"class":40,"line":185},[38,2970,123],{"class":44},[38,2972,2921],{"class":52},[38,2974,1378],{"class":44},[38,2976,2926],{"class":52},[38,2978,214],{"class":44},[38,2980,219],{"class":68},[38,2982,2933],{"class":52},[38,2984,236],{"class":68},[38,2986,211],{"class":52},[38,2988,196],{"class":44},[38,2990,2942],{"class":52},[38,2992,2993,2996,2998,3001,3003,3005,3007,3009,3011,3013],{"class":40,"line":242},[38,2994,2995],{"class":52},"                ans ",[38,2997,248],{"class":44},[38,2999,3000],{"class":52}," total_in_stack ",[38,3002,214],{"class":44},[38,3004,2926],{"class":52},[38,3006,214],{"class":44},[38,3008,219],{"class":68},[38,3010,2933],{"class":52},[38,3012,219],{"class":68},[38,3014,418],{"class":52},[38,3016,3017,3019],{"class":40,"line":254},[38,3018,143],{"class":44},[38,3020,53],{"class":52},[38,3022,3023,3025,3027],{"class":40,"line":406},[38,3024,2995],{"class":52},[38,3026,248],{"class":44},[38,3028,3029],{"class":52}," total_in_stack\n",[38,3031,3032],{"class":40,"line":421},[38,3033,163],{"emptyLinePlaceholder":162},[38,3035,3036],{"class":40,"line":435},[38,3037,3038],{"class":169},"            # Push x (merge if top has same value)\n",[38,3040,3041,3043,3045,3047,3049,3051,3053,3055,3057,3059,3061],{"class":40,"line":451},[38,3042,123],{"class":44},[38,3044,2921],{"class":52},[38,3046,1378],{"class":44},[38,3048,2926],{"class":52},[38,3050,214],{"class":44},[38,3052,219],{"class":68},[38,3054,2933],{"class":52},[38,3056,236],{"class":68},[38,3058,211],{"class":52},[38,3060,196],{"class":44},[38,3062,2942],{"class":52},[38,3064,3065,3068,3070,3072,3074,3076,3079,3081,3083,3085,3087,3089,3091,3093],{"class":40,"line":462},[38,3066,3067],{"class":52},"                stack[",[38,3069,214],{"class":44},[38,3071,219],{"class":68},[38,3073,211],{"class":52},[38,3075,85],{"class":44},[38,3077,3078],{"class":52}," (x, stack[",[38,3080,214],{"class":44},[38,3082,219],{"class":68},[38,3084,2933],{"class":52},[38,3086,219],{"class":68},[38,3088,211],{"class":52},[38,3090,765],{"class":44},[38,3092,810],{"class":68},[38,3094,770],{"class":52},[38,3096,3097,3099],{"class":40,"line":468},[38,3098,143],{"class":44},[38,3100,53],{"class":52},[38,3102,3103,3106,3108],{"class":40,"line":485},[38,3104,3105],{"class":52},"                stack.append((x, ",[38,3107,219],{"class":68},[38,3109,3110],{"class":52},"))\n",[38,3112,3113,3116,3118],{"class":40,"line":491},[38,3114,3115],{"class":52},"            total_in_stack ",[38,3117,248],{"class":44},[38,3119,251],{"class":68},[38,3121,3122],{"class":40,"line":511},[38,3123,163],{"emptyLinePlaceholder":162},[38,3125,3126,3128],{"class":40,"line":522},[38,3127,257],{"class":44},[38,3129,3130],{"class":52}," ans\n",[11,3132,3133,3134],{},"Q4\n",[15,3135,3138],{"href":3136,"rel":3137},"https://leetcode.com/problems/count-shadow-pairs-ii/",[19],"Count Shadow Pairs II",[11,3140,3141],{},"跟上一題幾乎一樣，條件為",[2654,3143,3144,3148,3152],{},[1001,3145,3146],{},[35,3147,2660],{},[1001,3149,3150],{},[35,3151,2665],{},[1001,3153,3154,3155,3158,3159],{},"i 和 j 之間不存在 k，使得 ",[35,3156,3157],{},"nums[i] \u003C nums[k] \u003C nums[j]","，這邊上一題是不存在 ",[35,3160,3161],{},"nums[k] \u003C nums[i] \u003C nums[j]",[11,3163,3164,3165,3168,3169,3171,3172,3175],{},"維護的 stack 改成 ",[35,3166,3167],{},"比 nums[j] 小的元素會被 pop 出來","\n每個被 pop 的元素 ",[35,3170,2672],{}," 和 ",[35,3173,3174],{},"nums[j]"," 形成一對 shadow pair",[22,3177,3178],{},[11,3179,2687],{},[28,3181,3183],{"className":30,"code":3182,"language":32,"meta":33,"style":33},"# TLE\nclass Solution:\n    def shadowPairs(self, nums: list[int]) -> int:\n        n = len(nums)\n        res = 0\n        for i in range(n):\n            tmp_min = float('inf')\n            for j in range(n):\n                if j \u003C= i:\n                    continue\n                if nums[j] \u003C= nums[i]:\n                    continue\n                if nums[j] > tmp_min:\n                    continue\n                tmp_min = min(tmp_min, nums[j])\n                res += 1\n        return res\n",[35,3184,3185,3189,3197,3213,3223,3231,3243,3259,3271,3281,3285,3295,3299,3310,3314,3326,3334],{"__ignoreMap":33},[38,3186,3187],{"class":40,"line":41},[38,3188,2697],{"class":169},[38,3190,3191,3193,3195],{"class":40,"line":56},[38,3192,45],{"class":44},[38,3194,49],{"class":48},[38,3196,53],{"class":52},[38,3198,3199,3201,3203,3205,3207,3209,3211],{"class":40,"line":79},[38,3200,59],{"class":44},[38,3202,2712],{"class":48},[38,3204,65],{"class":52},[38,3206,69],{"class":68},[38,3208,72],{"class":52},[38,3210,69],{"class":68},[38,3212,53],{"class":52},[38,3214,3215,3217,3219,3221],{"class":40,"line":91},[38,3216,2727],{"class":52},[38,3218,85],{"class":44},[38,3220,190],{"class":68},[38,3222,1072],{"class":52},[38,3224,3225,3227,3229],{"class":40,"line":102},[38,3226,94],{"class":52},[38,3228,85],{"class":44},[38,3230,99],{"class":68},[38,3232,3233,3235,3237,3239,3241],{"class":40,"line":120},[38,3234,105],{"class":44},[38,3236,703],{"class":52},[38,3238,111],{"class":44},[38,3240,798],{"class":68},[38,3242,1841],{"class":52},[38,3244,3245,3248,3250,3252,3254,3257],{"class":40,"line":134},[38,3246,3247],{"class":52},"            tmp_min ",[38,3249,85],{"class":44},[38,3251,881],{"class":68},[38,3253,750],{"class":52},[38,3255,3256],{"class":753},"'inf'",[38,3258,770],{"class":52},[38,3260,3261,3263,3265,3267,3269],{"class":40,"line":140},[38,3262,471],{"class":44},[38,3264,820],{"class":52},[38,3266,111],{"class":44},[38,3268,798],{"class":68},[38,3270,1841],{"class":52},[38,3272,3273,3275,3277,3279],{"class":40,"line":148},[38,3274,494],{"class":44},[38,3276,820],{"class":52},[38,3278,667],{"class":44},[38,3280,2776],{"class":52},[38,3282,3283],{"class":40,"line":159},[38,3284,2781],{"class":44},[38,3286,3287,3289,3291,3293],{"class":40,"line":166},[38,3288,494],{"class":44},[38,3290,2788],{"class":52},[38,3292,667],{"class":44},[38,3294,2793],{"class":52},[38,3296,3297],{"class":40,"line":173},[38,3298,2781],{"class":44},[38,3300,3301,3303,3305,3307],{"class":40,"line":185},[38,3302,494],{"class":44},[38,3304,2788],{"class":52},[38,3306,718],{"class":44},[38,3308,3309],{"class":52}," tmp_min:\n",[38,3311,3312],{"class":40,"line":242},[38,3313,2781],{"class":44},[38,3315,3316,3319,3321,3323],{"class":40,"line":254},[38,3317,3318],{"class":52},"                tmp_min ",[38,3320,85],{"class":44},[38,3322,897],{"class":68},[38,3324,3325],{"class":52},"(tmp_min, nums[j])\n",[38,3327,3328,3330,3332],{"class":40,"line":406},[38,3329,245],{"class":52},[38,3331,248],{"class":44},[38,3333,251],{"class":68},[38,3335,3336,3338],{"class":40,"line":421},[38,3337,257],{"class":44},[38,3339,260],{"class":52},[22,3341,3342],{},[11,3343,2209],{},[28,3345,3347],{"className":30,"code":3346,"language":32,"meta":33,"style":33},"class Solution:\n    def countShadowPairs(self, nums: list[int]) -> int:\n        stack = []  # (value, count), monotonically decreasing\n        result = 0\n\n        for x in nums:\n            count = 1\n            while stack and stack[-1][0] \u003C x:\n                val, cnt = stack.pop()\n                result += cnt\n            if stack and stack[-1][0] == x:\n                val, cnt = stack.pop()\n                count += cnt\n            stack.append((x, count))\n\n        return result\n",[35,3348,3349,3357,3373,3385,3393,3397,3407,3416,3440,3450,3460,3484,3492,3500,3505,3509],{"__ignoreMap":33},[38,3350,3351,3353,3355],{"class":40,"line":41},[38,3352,45],{"class":44},[38,3354,49],{"class":48},[38,3356,53],{"class":52},[38,3358,3359,3361,3363,3365,3367,3369,3371],{"class":40,"line":56},[38,3360,59],{"class":44},[38,3362,2849],{"class":48},[38,3364,65],{"class":52},[38,3366,69],{"class":68},[38,3368,72],{"class":52},[38,3370,69],{"class":68},[38,3372,53],{"class":52},[38,3374,3375,3377,3379,3382],{"class":40,"line":79},[38,3376,2864],{"class":52},[38,3378,85],{"class":44},[38,3380,3381],{"class":52}," []  ",[38,3383,3384],{"class":169},"# (value, count), monotonically decreasing\n",[38,3386,3387,3389,3391],{"class":40,"line":91},[38,3388,2075],{"class":52},[38,3390,85],{"class":44},[38,3392,99],{"class":68},[38,3394,3395],{"class":40,"line":102},[38,3396,163],{"emptyLinePlaceholder":162},[38,3398,3399,3401,3403,3405],{"class":40,"line":120},[38,3400,105],{"class":44},[38,3402,2904],{"class":52},[38,3404,111],{"class":44},[38,3406,2518],{"class":52},[38,3408,3409,3412,3414],{"class":40,"line":134},[38,3410,3411],{"class":52},"            count ",[38,3413,85],{"class":44},[38,3415,251],{"class":68},[38,3417,3418,3420,3422,3424,3426,3428,3430,3432,3434,3436,3438],{"class":40,"line":140},[38,3419,2918],{"class":44},[38,3421,2921],{"class":52},[38,3423,1378],{"class":44},[38,3425,2926],{"class":52},[38,3427,214],{"class":44},[38,3429,219],{"class":68},[38,3431,2933],{"class":52},[38,3433,236],{"class":68},[38,3435,211],{"class":52},[38,3437,390],{"class":44},[38,3439,2942],{"class":52},[38,3441,3442,3445,3447],{"class":40,"line":148},[38,3443,3444],{"class":52},"                val, cnt ",[38,3446,85],{"class":44},[38,3448,3449],{"class":52}," stack.pop()\n",[38,3451,3452,3455,3457],{"class":40,"line":159},[38,3453,3454],{"class":52},"                result ",[38,3456,248],{"class":44},[38,3458,3459],{"class":52}," cnt\n",[38,3461,3462,3464,3466,3468,3470,3472,3474,3476,3478,3480,3482],{"class":40,"line":166},[38,3463,123],{"class":44},[38,3465,2921],{"class":52},[38,3467,1378],{"class":44},[38,3469,2926],{"class":52},[38,3471,214],{"class":44},[38,3473,219],{"class":68},[38,3475,2933],{"class":52},[38,3477,236],{"class":68},[38,3479,211],{"class":52},[38,3481,196],{"class":44},[38,3483,2942],{"class":52},[38,3485,3486,3488,3490],{"class":40,"line":173},[38,3487,3444],{"class":52},[38,3489,85],{"class":44},[38,3491,3449],{"class":52},[38,3493,3494,3496,3498],{"class":40,"line":185},[38,3495,1323],{"class":52},[38,3497,248],{"class":44},[38,3499,3459],{"class":52},[38,3501,3502],{"class":40,"line":242},[38,3503,3504],{"class":52},"            stack.append((x, count))\n",[38,3506,3507],{"class":40,"line":254},[38,3508,163],{"emptyLinePlaceholder":162},[38,3510,3511,3513],{"class":40,"line":406},[38,3512,257],{"class":44},[38,3514,2181],{"class":52},[1733,3516,3517],{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":33,"searchDepth":56,"depth":56,"links":3519},[],"Weekly Contest 591 過程思路與心得",{},"/blog/leetcode-contest/leetcode-weekly-591",{"title":1757,"description":3520},"blog/Leetcode Contest/leetcode-weekly-591",[1748,1749,1750,1751],"WAX25mKJ1n2dKDKj76DIjEpDlybg1uqtWLTLUnlYIlE",{"id":3528,"title":3529,"author":6,"body":3530,"category":1738,"date":5622,"description":5623,"extension":1741,"image":33,"language":1742,"meta":5624,"navigation":162,"path":5625,"seo":5626,"stem":5627,"tags":5628,"updatedAt":1752,"__hash__":5631},"blog/blog/concurrency.md","Python 並發處理方法",{"type":8,"value":3531,"toc":5601},[3532,3537,3540,3543,3546,3551,3599,3603,3638,3642,3675,3679,3697,3700,3848,3851,5177,5180,5428,5432,5438,5456,5460,5465,5483,5486,5491,5495,5498,5502,5505,5519,5523,5526,5572,5575,5598],[3533,3534,3536],"h2",{"id":3535},"這篇文章的用處","這篇文章的用處？",[11,3538,3539],{},"若專案內有遇到效能瓶頸，這可能可以幫助你加速。",[11,3541,3542],{},"Python 提供了幾種並發方式，每種方式適用於不同類型的任務。",[3533,3544,3545],{"id":3545},"各方式介紹",[3547,3548,3550],"h3",{"id":3549},"_1-多線程multithreading","1. 多線程（Multithreading）",[998,3552,3553,3560,3581,3587,3593],{},[1001,3554,3555,3559],{},[3556,3557,3558],"strong",{},"特點","：由於 GIL 的存在，多線程無法實現真正的並行，線程間由解釋器切換執行。",[1001,3561,3562,3565,3566,3569,3570],{},[3556,3563,3564],{},"適用場景","：適合 ",[3556,3567,3568],{},"I/O 綁定任務","，如：\n",[998,3571,3572,3575,3578],{},[1001,3573,3574],{},"API 呼叫",[1001,3576,3577],{},"檔案讀寫",[1001,3579,3580],{},"使用者輸入等待",[1001,3582,3583,3586],{},[3556,3584,3585],{},"限制","：在 CPU 綁定任務（如計算 Fibonacci 數列）中，效能與單線程迴圈相差無幾。",[1001,3588,3589,3592],{},[3556,3590,3591],{},"優點","：線程間資料共享簡單，記憶體開銷低。",[1001,3594,3595,3598],{},[3556,3596,3597],{},"缺點","：受 GIL 限制，無法利用多核心。",[3547,3600,3602],{"id":3601},"_2-多進程multiprocessing","2. 多進程（Multiprocessing）",[998,3604,3605,3610,3628,3633],{},[1001,3606,3607,3609],{},[3556,3608,3558],{},"：每個進程擁有獨立的 Python 解釋器和 GIL，因此可以在不同 CPU 核心上實現真正的並行。",[1001,3611,3612,3565,3614,3569,3617],{},[3556,3613,3564],{},[3556,3615,3616],{},"CPU 綁定任務",[998,3618,3619,3622,3625],{},[1001,3620,3621],{},"數學運算",[1001,3623,3624],{},"圖像處理",[1001,3626,3627],{},"日誌分析",[1001,3629,3630,3632],{},[3556,3631,3591],{},"：繞過 GIL，實現真並行，速度較快。",[1001,3634,3635,3637],{},[3556,3636,3597],{},"：記憶體使用量高，進程間資料共享較複雜（需使用管道或共享記憶體）。",[3547,3639,3641],{"id":3640},"_3-asyncio","3. Asyncio",[998,3643,3644,3649,3665,3670],{},[1001,3645,3646,3648],{},[3556,3647,3558],{},"：使用協程（coroutines）實現非阻塞的並發，適合 I/O 綁定任務。",[1001,3650,3651,3653,3654],{},[3556,3652,3564],{},"：\n",[998,3655,3656,3659,3662],{},[1001,3657,3658],{},"網路請求",[1001,3660,3661],{},"檔案 I/O",[1001,3663,3664],{},"其他等待外部資源的任務",[1001,3666,3667,3669],{},[3556,3668,3591],{},"：輕量，記憶體使用效率高。",[1001,3671,3672,3674],{},[3556,3673,3597],{},"：不適合 CPU 密集型任務，因為它並非真正的並行。",[3547,3676,3678],{"id":3677},"_4-第三方庫","4. 第三方庫",[998,3680,3681,3687,3692],{},[1001,3682,3683,3686],{},[3556,3684,3685],{},"例子","：Cython、NumPy、Pandas、PyTorch 等。",[1001,3688,3689,3691],{},[3556,3690,3558],{},"：這些庫通常使用 C 語言實現，部分操作可繞過 GIL，提供高效能。",[1001,3693,3694,3696],{},[3556,3695,3564],{},"：特定計算密集型任務（如矩陣運算）。",[3533,3698,3699],{"id":3699},"特性比較表",[3701,3702,3703,3725],"table",{},[3704,3705,3706],"thead",{},[3707,3708,3709,3713,3716,3719,3722],"tr",{},[3710,3711,3712],"th",{},"特性",[3710,3714,3715],{},"Multi-threading",[3710,3717,3718],{},"Multi-processing",[3710,3720,3721],{},"AsyncIO",[3710,3723,3724],{},"Disabled GIL",[3726,3727,3728,3746,3763,3781,3798,3814,3829],"tbody",{},[3707,3729,3730,3736,3739,3742,3744],{},[3731,3732,3733],"td",{},[3556,3734,3735],{},"並行",[3731,3737,3738],{},"❌",[3731,3740,3741],{},"✅",[3731,3743,3738],{},[3731,3745,3741],{},[3707,3747,3748,3753,3756,3759,3761],{},[3731,3749,3750],{},[3556,3751,3752],{},"記憶體共享",[3731,3754,3755],{},"容易",[3731,3757,3758],{},"困難",[3731,3760,3755],{},[3731,3762,3755],{},[3707,3764,3765,3770,3773,3776,3778],{},[3731,3766,3767],{},[3556,3768,3769],{},"記憶體使用",[3731,3771,3772],{},"低",[3731,3774,3775],{},"高",[3731,3777,3772],{},[3731,3779,3780],{},"中等",[3707,3782,3783,3788,3791,3794,3796],{},[3731,3784,3785],{},[3556,3786,3787],{},"CPU 密集型",[3731,3789,3790],{},"差",[3731,3792,3793],{},"好",[3731,3795,3790],{},[3731,3797,3793],{},[3707,3799,3800,3805,3807,3809,3812],{},[3731,3801,3802],{},[3556,3803,3804],{},"I/O 密集型",[3731,3806,3793],{},[3731,3808,3780],{},[3731,3810,3811],{},"最佳",[3731,3813,3793],{},[3707,3815,3816,3821,3823,3825,3827],{},[3731,3817,3818],{},[3556,3819,3820],{},"實作複雜度",[3731,3822,3780],{},[3731,3824,3775],{},[3731,3826,3780],{},[3731,3828,3775],{},[3707,3830,3831,3836,3839,3842,3845],{},[3731,3832,3833],{},[3556,3834,3835],{},"競爭條件風險",[3731,3837,3838],{},"低（GIL保護）",[3731,3840,3841],{},"低（隔離）",[3731,3843,3844],{},"無（單執行緒）",[3731,3846,3847],{},"高（需手動處理）",[3533,3849,3850],{"id":3850},"範例程式碼",[28,3852,3854],{"className":30,"code":3853,"language":32,"meta":33,"style":33},"import time\nimport threading\nimport multiprocessing\nimport asyncio\nimport sys\nfrom concurrent.futures import ThreadPoolExecutor\nfrom functools import wraps\n\n# 計時裝飾器，用於測量執行時間\ndef timing_decorator(func):\n    @wraps(func)\n    def wrapper(*args, **kwargs):\n        start = time.time()\n        result = func(*args, **kwargs)\n        end = time.time()\n        print(f\"{func.__name__} 執行時間: {end - start:.4f} 秒\")\n        return result\n    return wrapper\n\n# CPU 密集型任務：計算 Fibonacci 數列\ndef fib(n):\n    if n \u003C= 1:\n        return n\n    return fib(n - 1) + fib(n - 2)\n\n# I/O 綁定任務：模擬網路請求（全局函數）\ndef sync_io_task():\n    time.sleep(1)  # 模擬 1 秒的 I/O 延遲\n\n# 異步 I/O 任務\nasync def io_bound_task():\n    await asyncio.sleep(1)  # 模擬 1 秒的 I/O 延遲\n    return \"I/O 任務完成\"\n\n# 多線程實現\n@timing_decorator\ndef run_multithreading(n_tasks, task_type=\"cpu\"):\n    threads = []\n    if task_type == \"cpu\":\n        for _ in range(n_tasks):\n            t = threading.Thread(target=fib, args=(35,))\n            threads.append(t)\n            t.start()\n        for t in threads:\n            t.join()\n    else:  # I/O 任務\n        for _ in range(n_tasks):\n            t = threading.Thread(target=sync_io_task)\n            threads.append(t)\n            t.start()\n        for t in threads:\n            t.join()\n\n# 多進程實現\n@timing_decorator\ndef run_multiprocessing(n_tasks, task_type=\"cpu\"):\n    processes = []\n    if task_type == \"cpu\":\n        for _ in range(n_tasks):\n            p = multiprocessing.Process(target=fib, args=(35,))\n            processes.append(p)\n            p.start()\n        for p in processes:\n            p.join()\n    else:  # I/O 任務\n        for _ in range(n_tasks):\n            p = multiprocessing.Process(target=sync_io_task)\n            processes.append(p)\n            p.start()\n        for p in processes:\n            p.join()\n\n# Asyncio 實現\n@timing_decorator\nasync def run_asyncio(n_tasks):\n    tasks = [io_bound_task() for _ in range(n_tasks)]\n    await asyncio.gather(*tasks)\n\n# 禁用 GIL 的多線程實現（需 Python 3.13 --disable-gil）\n@timing_decorator\ndef run_nogil_multithreading(n_tasks, task_type=\"cpu\"):\n    with ThreadPoolExecutor(max_workers=n_tasks) as executor:\n        if task_type == \"cpu\":\n            futures = [executor.submit(fib, 35) for _ in range(n_tasks)]\n        else:  # I/O 任務\n            futures = [executor.submit(sync_io_task) for _ in range(n_tasks)]\n        for future in futures:\n            future.result()\n\n# 主程式\nif __name__ == \"__main__\":\n    n_tasks = 4  # 任務數量\n\n    print(\"=== CPU 密集型任務 (計算 Fibonacci 數列) ===\")\n    print(\"多線程 (Multithreading):\")\n    run_multithreading(n_tasks, task_type=\"cpu\")\n\n    print(\"\\n多進程 (Multiprocessing):\")\n    run_multiprocessing(n_tasks, task_type=\"cpu\")\n\n    if sys.version_info >= (3, 13) and hasattr(sys, \"disable_gil\"):\n        print(\"\\n禁用 GIL 的多線程:\")\n        run_nogil_multithreading(n_tasks, task_type=\"cpu\")\n    else:\n        print(\"\\n禁用 GIL 的多線程: 需要 Python 3.13 並啟用 --disable-gil\")\n\n    print(\"\\n=== I/O 綁定任務 (模擬網路請求) ===\")\n    print(\"多線程 (Multithreading):\")\n    run_multithreading(n_tasks, task_type=\"io\")\n\n    print(\"\\n多進程 (Multiprocessing):\")\n    run_multiprocessing(n_tasks, task_type=\"io\")\n\n    print(\"\\nAsyncio:\")\n    asyncio.run(run_asyncio(n_tasks))\n\n    if sys.version_info >= (3, 13) and hasattr(sys, \"disable_gil\"):\n        print(\"\\n禁用 GIL 的多線程:\")\n        run_nogil_multithreading(n_tasks, task_type=\"io\")\n    else:\n        print(\"\\n禁用 GIL 的多線程: 需要 Python 3.13 並啟用 --disable-gil\")\n",[35,3855,3856,3863,3870,3877,3884,3891,3903,3915,3919,3924,3935,3943,3963,3973,3991,4000,4046,4052,4060,4064,4069,4078,4090,4096,4120,4124,4129,4139,4152,4156,4161,4174,4188,4195,4199,4204,4209,4226,4235,4249,4262,4294,4299,4304,4316,4321,4332,4344,4359,4363,4367,4377,4381,4385,4390,4394,4409,4419,4432,4445,4472,4478,4484,4497,4503,4512,4525,4540,4545,4550,4561,4566,4571,4577,4582,4594,4616,4629,4634,4640,4645,4661,4684,4697,4722,4732,4752,4765,4771,4776,4782,4799,4813,4818,4831,4843,4858,4863,4880,4894,4899,4934,4950,4964,4971,4987,4992,5008,5019,5033,5038,5053,5066,5071,5087,5093,5098,5127,5142,5155,5162],{"__ignoreMap":33},[38,3857,3858,3860],{"class":40,"line":41},[38,3859,2236],{"class":44},[38,3861,3862],{"class":52}," time\n",[38,3864,3865,3867],{"class":40,"line":56},[38,3866,2236],{"class":44},[38,3868,3869],{"class":52}," threading\n",[38,3871,3872,3874],{"class":40,"line":79},[38,3873,2236],{"class":44},[38,3875,3876],{"class":52}," multiprocessing\n",[38,3878,3879,3881],{"class":40,"line":91},[38,3880,2236],{"class":44},[38,3882,3883],{"class":52}," asyncio\n",[38,3885,3886,3888],{"class":40,"line":102},[38,3887,2236],{"class":44},[38,3889,3890],{"class":52}," sys\n",[38,3892,3893,3895,3898,3900],{"class":40,"line":120},[38,3894,2230],{"class":44},[38,3896,3897],{"class":52}," concurrent.futures ",[38,3899,2236],{"class":44},[38,3901,3902],{"class":52}," ThreadPoolExecutor\n",[38,3904,3905,3907,3910,3912],{"class":40,"line":134},[38,3906,2230],{"class":44},[38,3908,3909],{"class":52}," functools ",[38,3911,2236],{"class":44},[38,3913,3914],{"class":52}," wraps\n",[38,3916,3917],{"class":40,"line":140},[38,3918,163],{"emptyLinePlaceholder":162},[38,3920,3921],{"class":40,"line":148},[38,3922,3923],{"class":169},"# 計時裝飾器，用於測量執行時間\n",[38,3925,3926,3929,3932],{"class":40,"line":159},[38,3927,3928],{"class":44},"def",[38,3930,3931],{"class":48}," timing_decorator",[38,3933,3934],{"class":52},"(func):\n",[38,3936,3937,3940],{"class":40,"line":166},[38,3938,3939],{"class":48},"    @wraps",[38,3941,3942],{"class":52},"(func)\n",[38,3944,3945,3947,3950,3952,3954,3957,3960],{"class":40,"line":173},[38,3946,59],{"class":44},[38,3948,3949],{"class":48}," wrapper",[38,3951,750],{"class":52},[38,3953,700],{"class":44},[38,3955,3956],{"class":52},"args, ",[38,3958,3959],{"class":44},"**",[38,3961,3962],{"class":52},"kwargs):\n",[38,3964,3965,3968,3970],{"class":40,"line":185},[38,3966,3967],{"class":52},"        start ",[38,3969,85],{"class":44},[38,3971,3972],{"class":52}," time.time()\n",[38,3974,3975,3977,3979,3982,3984,3986,3988],{"class":40,"line":242},[38,3976,2075],{"class":52},[38,3978,85],{"class":44},[38,3980,3981],{"class":52}," func(",[38,3983,700],{"class":44},[38,3985,3956],{"class":52},[38,3987,3959],{"class":44},[38,3989,3990],{"class":52},"kwargs)\n",[38,3992,3993,3996,3998],{"class":40,"line":254},[38,3994,3995],{"class":52},"        end ",[38,3997,85],{"class":44},[38,3999,3972],{"class":52},[38,4001,4002,4005,4007,4010,4013,4016,4019,4022,4025,4027,4030,4032,4035,4038,4041,4044],{"class":40,"line":406},[38,4003,4004],{"class":68},"        print",[38,4006,750],{"class":52},[38,4008,4009],{"class":44},"f",[38,4011,4012],{"class":753},"\"",[38,4014,4015],{"class":68},"{",[38,4017,4018],{"class":52},"func.",[38,4020,4021],{"class":68},"__name__}",[38,4023,4024],{"class":753}," 執行時間: ",[38,4026,4015],{"class":68},[38,4028,4029],{"class":52},"end ",[38,4031,214],{"class":44},[38,4033,4034],{"class":52}," start",[38,4036,4037],{"class":44},":.4f",[38,4039,4040],{"class":68},"}",[38,4042,4043],{"class":753}," 秒\"",[38,4045,770],{"class":52},[38,4047,4048,4050],{"class":40,"line":421},[38,4049,257],{"class":44},[38,4051,2181],{"class":52},[38,4053,4054,4057],{"class":40,"line":435},[38,4055,4056],{"class":44},"    return",[38,4058,4059],{"class":52}," wrapper\n",[38,4061,4062],{"class":40,"line":451},[38,4063,163],{"emptyLinePlaceholder":162},[38,4065,4066],{"class":40,"line":462},[38,4067,4068],{"class":169},"# CPU 密集型任務：計算 Fibonacci 數列\n",[38,4070,4071,4073,4076],{"class":40,"line":468},[38,4072,3928],{"class":44},[38,4074,4075],{"class":48}," fib",[38,4077,1841],{"class":52},[38,4079,4080,4082,4084,4086,4088],{"class":40,"line":485},[38,4081,2395],{"class":44},[38,4083,1961],{"class":52},[38,4085,667],{"class":44},[38,4087,810],{"class":68},[38,4089,53],{"class":52},[38,4091,4092,4094],{"class":40,"line":491},[38,4093,257],{"class":44},[38,4095,2145],{"class":52},[38,4097,4098,4100,4103,4105,4107,4109,4111,4113,4115,4118],{"class":40,"line":511},[38,4099,4056],{"class":44},[38,4101,4102],{"class":52}," fib(n ",[38,4104,214],{"class":44},[38,4106,810],{"class":68},[38,4108,1094],{"class":52},[38,4110,765],{"class":44},[38,4112,4102],{"class":52},[38,4114,214],{"class":44},[38,4116,4117],{"class":68}," 2",[38,4119,770],{"class":52},[38,4121,4122],{"class":40,"line":522},[38,4123,163],{"emptyLinePlaceholder":162},[38,4125,4126],{"class":40,"line":528},[38,4127,4128],{"class":169},"# I/O 綁定任務：模擬網路請求（全局函數）\n",[38,4130,4131,4133,4136],{"class":40,"line":536},[38,4132,3928],{"class":44},[38,4134,4135],{"class":48}," sync_io_task",[38,4137,4138],{"class":52},"():\n",[38,4140,4141,4144,4146,4149],{"class":40,"line":547},[38,4142,4143],{"class":52},"    time.sleep(",[38,4145,219],{"class":68},[38,4147,4148],{"class":52},")  ",[38,4150,4151],{"class":169},"# 模擬 1 秒的 I/O 延遲\n",[38,4153,4154],{"class":40,"line":555},[38,4155,163],{"emptyLinePlaceholder":162},[38,4157,4158],{"class":40,"line":560},[38,4159,4160],{"class":169},"# 異步 I/O 任務\n",[38,4162,4163,4166,4169,4172],{"class":40,"line":567},[38,4164,4165],{"class":44},"async",[38,4167,4168],{"class":44}," def",[38,4170,4171],{"class":48}," io_bound_task",[38,4173,4138],{"class":52},[38,4175,4176,4179,4182,4184,4186],{"class":40,"line":576},[38,4177,4178],{"class":44},"    await",[38,4180,4181],{"class":52}," asyncio.sleep(",[38,4183,219],{"class":68},[38,4185,4148],{"class":52},[38,4187,4151],{"class":169},[38,4189,4190,4192],{"class":40,"line":1473},[38,4191,4056],{"class":44},[38,4193,4194],{"class":753}," \"I/O 任務完成\"\n",[38,4196,4197],{"class":40,"line":1484},[38,4198,163],{"emptyLinePlaceholder":162},[38,4200,4201],{"class":40,"line":1494},[38,4202,4203],{"class":169},"# 多線程實現\n",[38,4205,4206],{"class":40,"line":1501},[38,4207,4208],{"class":48},"@timing_decorator\n",[38,4210,4211,4213,4216,4219,4221,4224],{"class":40,"line":1511},[38,4212,3928],{"class":44},[38,4214,4215],{"class":48}," run_multithreading",[38,4217,4218],{"class":52},"(n_tasks, task_type",[38,4220,85],{"class":44},[38,4222,4223],{"class":753},"\"cpu\"",[38,4225,813],{"class":52},[38,4227,4228,4231,4233],{"class":40,"line":1521},[38,4229,4230],{"class":52},"    threads ",[38,4232,85],{"class":44},[38,4234,638],{"class":52},[38,4236,4237,4239,4242,4244,4247],{"class":40,"line":1531},[38,4238,2395],{"class":44},[38,4240,4241],{"class":52}," task_type ",[38,4243,196],{"class":44},[38,4245,4246],{"class":753}," \"cpu\"",[38,4248,53],{"class":52},[38,4250,4251,4253,4255,4257,4259],{"class":40,"line":1543},[38,4252,105],{"class":44},[38,4254,1853],{"class":52},[38,4256,111],{"class":44},[38,4258,798],{"class":68},[38,4260,4261],{"class":52},"(n_tasks):\n",[38,4263,4264,4267,4269,4272,4276,4278,4281,4284,4286,4288,4291],{"class":40,"line":1553},[38,4265,4266],{"class":52},"            t ",[38,4268,85],{"class":44},[38,4270,4271],{"class":52}," threading.Thread(",[38,4273,4275],{"class":4274},"s4XuR","target",[38,4277,85],{"class":44},[38,4279,4280],{"class":52},"fib, ",[38,4282,4283],{"class":4274},"args",[38,4285,85],{"class":44},[38,4287,750],{"class":52},[38,4289,4290],{"class":68},"35",[38,4292,4293],{"class":52},",))\n",[38,4295,4296],{"class":40,"line":1570},[38,4297,4298],{"class":52},"            threads.append(t)\n",[38,4300,4301],{"class":40,"line":1581},[38,4302,4303],{"class":52},"            t.start()\n",[38,4305,4306,4308,4311,4313],{"class":40,"line":1590},[38,4307,105],{"class":44},[38,4309,4310],{"class":52}," t ",[38,4312,111],{"class":44},[38,4314,4315],{"class":52}," threads:\n",[38,4317,4318],{"class":40,"line":1606},[38,4319,4320],{"class":52},"            t.join()\n",[38,4322,4323,4326,4329],{"class":40,"line":1617},[38,4324,4325],{"class":44},"    else",[38,4327,4328],{"class":52},":  ",[38,4330,4331],{"class":169},"# I/O 任務\n",[38,4333,4334,4336,4338,4340,4342],{"class":40,"line":1626},[38,4335,105],{"class":44},[38,4337,1853],{"class":52},[38,4339,111],{"class":44},[38,4341,798],{"class":68},[38,4343,4261],{"class":52},[38,4345,4346,4348,4350,4352,4354,4356],{"class":40,"line":1631},[38,4347,4266],{"class":52},[38,4349,85],{"class":44},[38,4351,4271],{"class":52},[38,4353,4275],{"class":4274},[38,4355,85],{"class":44},[38,4357,4358],{"class":52},"sync_io_task)\n",[38,4360,4361],{"class":40,"line":1650},[38,4362,4298],{"class":52},[38,4364,4365],{"class":40,"line":1655},[38,4366,4303],{"class":52},[38,4368,4369,4371,4373,4375],{"class":40,"line":1674},[38,4370,105],{"class":44},[38,4372,4310],{"class":52},[38,4374,111],{"class":44},[38,4376,4315],{"class":52},[38,4378,4379],{"class":40,"line":1689},[38,4380,4320],{"class":52},[38,4382,4383],{"class":40,"line":1700},[38,4384,163],{"emptyLinePlaceholder":162},[38,4386,4387],{"class":40,"line":1706},[38,4388,4389],{"class":169},"# 多進程實現\n",[38,4391,4392],{"class":40,"line":1715},[38,4393,4208],{"class":48},[38,4395,4396,4398,4401,4403,4405,4407],{"class":40,"line":1721},[38,4397,3928],{"class":44},[38,4399,4400],{"class":48}," run_multiprocessing",[38,4402,4218],{"class":52},[38,4404,85],{"class":44},[38,4406,4223],{"class":753},[38,4408,813],{"class":52},[38,4410,4412,4415,4417],{"class":40,"line":4411},57,[38,4413,4414],{"class":52},"    processes ",[38,4416,85],{"class":44},[38,4418,638],{"class":52},[38,4420,4422,4424,4426,4428,4430],{"class":40,"line":4421},58,[38,4423,2395],{"class":44},[38,4425,4241],{"class":52},[38,4427,196],{"class":44},[38,4429,4246],{"class":753},[38,4431,53],{"class":52},[38,4433,4435,4437,4439,4441,4443],{"class":40,"line":4434},59,[38,4436,105],{"class":44},[38,4438,1853],{"class":52},[38,4440,111],{"class":44},[38,4442,798],{"class":68},[38,4444,4261],{"class":52},[38,4446,4448,4451,4453,4456,4458,4460,4462,4464,4466,4468,4470],{"class":40,"line":4447},60,[38,4449,4450],{"class":52},"            p ",[38,4452,85],{"class":44},[38,4454,4455],{"class":52}," multiprocessing.Process(",[38,4457,4275],{"class":4274},[38,4459,85],{"class":44},[38,4461,4280],{"class":52},[38,4463,4283],{"class":4274},[38,4465,85],{"class":44},[38,4467,750],{"class":52},[38,4469,4290],{"class":68},[38,4471,4293],{"class":52},[38,4473,4475],{"class":40,"line":4474},61,[38,4476,4477],{"class":52},"            processes.append(p)\n",[38,4479,4481],{"class":40,"line":4480},62,[38,4482,4483],{"class":52},"            p.start()\n",[38,4485,4487,4489,4492,4494],{"class":40,"line":4486},63,[38,4488,105],{"class":44},[38,4490,4491],{"class":52}," p ",[38,4493,111],{"class":44},[38,4495,4496],{"class":52}," processes:\n",[38,4498,4500],{"class":40,"line":4499},64,[38,4501,4502],{"class":52},"            p.join()\n",[38,4504,4506,4508,4510],{"class":40,"line":4505},65,[38,4507,4325],{"class":44},[38,4509,4328],{"class":52},[38,4511,4331],{"class":169},[38,4513,4515,4517,4519,4521,4523],{"class":40,"line":4514},66,[38,4516,105],{"class":44},[38,4518,1853],{"class":52},[38,4520,111],{"class":44},[38,4522,798],{"class":68},[38,4524,4261],{"class":52},[38,4526,4528,4530,4532,4534,4536,4538],{"class":40,"line":4527},67,[38,4529,4450],{"class":52},[38,4531,85],{"class":44},[38,4533,4455],{"class":52},[38,4535,4275],{"class":4274},[38,4537,85],{"class":44},[38,4539,4358],{"class":52},[38,4541,4543],{"class":40,"line":4542},68,[38,4544,4477],{"class":52},[38,4546,4548],{"class":40,"line":4547},69,[38,4549,4483],{"class":52},[38,4551,4553,4555,4557,4559],{"class":40,"line":4552},70,[38,4554,105],{"class":44},[38,4556,4491],{"class":52},[38,4558,111],{"class":44},[38,4560,4496],{"class":52},[38,4562,4564],{"class":40,"line":4563},71,[38,4565,4502],{"class":52},[38,4567,4569],{"class":40,"line":4568},72,[38,4570,163],{"emptyLinePlaceholder":162},[38,4572,4574],{"class":40,"line":4573},73,[38,4575,4576],{"class":169},"# Asyncio 實現\n",[38,4578,4580],{"class":40,"line":4579},74,[38,4581,4208],{"class":48},[38,4583,4585,4587,4589,4592],{"class":40,"line":4584},75,[38,4586,4165],{"class":44},[38,4588,4168],{"class":44},[38,4590,4591],{"class":48}," run_asyncio",[38,4593,4261],{"class":52},[38,4595,4597,4600,4602,4605,4607,4609,4611,4613],{"class":40,"line":4596},76,[38,4598,4599],{"class":52},"    tasks ",[38,4601,85],{"class":44},[38,4603,4604],{"class":52}," [io_bound_task() ",[38,4606,2091],{"class":44},[38,4608,1853],{"class":52},[38,4610,111],{"class":44},[38,4612,798],{"class":68},[38,4614,4615],{"class":52},"(n_tasks)]\n",[38,4617,4619,4621,4624,4626],{"class":40,"line":4618},77,[38,4620,4178],{"class":44},[38,4622,4623],{"class":52}," asyncio.gather(",[38,4625,700],{"class":44},[38,4627,4628],{"class":52},"tasks)\n",[38,4630,4632],{"class":40,"line":4631},78,[38,4633,163],{"emptyLinePlaceholder":162},[38,4635,4637],{"class":40,"line":4636},79,[38,4638,4639],{"class":169},"# 禁用 GIL 的多線程實現（需 Python 3.13 --disable-gil）\n",[38,4641,4643],{"class":40,"line":4642},80,[38,4644,4208],{"class":48},[38,4646,4648,4650,4653,4655,4657,4659],{"class":40,"line":4647},81,[38,4649,3928],{"class":44},[38,4651,4652],{"class":48}," run_nogil_multithreading",[38,4654,4218],{"class":52},[38,4656,85],{"class":44},[38,4658,4223],{"class":753},[38,4660,813],{"class":52},[38,4662,4664,4667,4670,4673,4675,4678,4681],{"class":40,"line":4663},82,[38,4665,4666],{"class":44},"    with",[38,4668,4669],{"class":52}," ThreadPoolExecutor(",[38,4671,4672],{"class":4274},"max_workers",[38,4674,85],{"class":44},[38,4676,4677],{"class":52},"n_tasks) ",[38,4679,4680],{"class":44},"as",[38,4682,4683],{"class":52}," executor:\n",[38,4685,4687,4689,4691,4693,4695],{"class":40,"line":4686},83,[38,4688,1103],{"class":44},[38,4690,4241],{"class":52},[38,4692,196],{"class":44},[38,4694,4246],{"class":753},[38,4696,53],{"class":52},[38,4698,4700,4703,4705,4708,4710,4712,4714,4716,4718,4720],{"class":40,"line":4699},84,[38,4701,4702],{"class":52},"            futures ",[38,4704,85],{"class":44},[38,4706,4707],{"class":52}," [executor.submit(fib, ",[38,4709,4290],{"class":68},[38,4711,1094],{"class":52},[38,4713,2091],{"class":44},[38,4715,1853],{"class":52},[38,4717,111],{"class":44},[38,4719,798],{"class":68},[38,4721,4615],{"class":52},[38,4723,4725,4728,4730],{"class":40,"line":4724},85,[38,4726,4727],{"class":44},"        else",[38,4729,4328],{"class":52},[38,4731,4331],{"class":169},[38,4733,4735,4737,4739,4742,4744,4746,4748,4750],{"class":40,"line":4734},86,[38,4736,4702],{"class":52},[38,4738,85],{"class":44},[38,4740,4741],{"class":52}," [executor.submit(sync_io_task) ",[38,4743,2091],{"class":44},[38,4745,1853],{"class":52},[38,4747,111],{"class":44},[38,4749,798],{"class":68},[38,4751,4615],{"class":52},[38,4753,4755,4757,4760,4762],{"class":40,"line":4754},87,[38,4756,105],{"class":44},[38,4758,4759],{"class":52}," future ",[38,4761,111],{"class":44},[38,4763,4764],{"class":52}," futures:\n",[38,4766,4768],{"class":40,"line":4767},88,[38,4769,4770],{"class":52},"            future.result()\n",[38,4772,4774],{"class":40,"line":4773},89,[38,4775,163],{"emptyLinePlaceholder":162},[38,4777,4779],{"class":40,"line":4778},90,[38,4780,4781],{"class":169},"# 主程式\n",[38,4783,4785,4788,4791,4794,4797],{"class":40,"line":4784},91,[38,4786,4787],{"class":44},"if",[38,4789,4790],{"class":68}," __name__",[38,4792,4793],{"class":44}," ==",[38,4795,4796],{"class":753}," \"__main__\"",[38,4798,53],{"class":52},[38,4800,4802,4805,4807,4810],{"class":40,"line":4801},92,[38,4803,4804],{"class":52},"    n_tasks ",[38,4806,85],{"class":44},[38,4808,4809],{"class":68}," 4",[38,4811,4812],{"class":169},"  # 任務數量\n",[38,4814,4816],{"class":40,"line":4815},93,[38,4817,163],{"emptyLinePlaceholder":162},[38,4819,4821,4824,4826,4829],{"class":40,"line":4820},94,[38,4822,4823],{"class":68},"    print",[38,4825,750],{"class":52},[38,4827,4828],{"class":753},"\"=== CPU 密集型任務 (計算 Fibonacci 數列) ===\"",[38,4830,770],{"class":52},[38,4832,4834,4836,4838,4841],{"class":40,"line":4833},95,[38,4835,4823],{"class":68},[38,4837,750],{"class":52},[38,4839,4840],{"class":753},"\"多線程 (Multithreading):\"",[38,4842,770],{"class":52},[38,4844,4846,4849,4852,4854,4856],{"class":40,"line":4845},96,[38,4847,4848],{"class":52},"    run_multithreading(n_tasks, ",[38,4850,4851],{"class":4274},"task_type",[38,4853,85],{"class":44},[38,4855,4223],{"class":753},[38,4857,770],{"class":52},[38,4859,4861],{"class":40,"line":4860},97,[38,4862,163],{"emptyLinePlaceholder":162},[38,4864,4866,4868,4870,4872,4875,4878],{"class":40,"line":4865},98,[38,4867,4823],{"class":68},[38,4869,750],{"class":52},[38,4871,4012],{"class":753},[38,4873,4874],{"class":68},"\\n",[38,4876,4877],{"class":753},"多進程 (Multiprocessing):\"",[38,4879,770],{"class":52},[38,4881,4883,4886,4888,4890,4892],{"class":40,"line":4882},99,[38,4884,4885],{"class":52},"    run_multiprocessing(n_tasks, ",[38,4887,4851],{"class":4274},[38,4889,85],{"class":44},[38,4891,4223],{"class":753},[38,4893,770],{"class":52},[38,4895,4897],{"class":40,"line":4896},100,[38,4898,163],{"emptyLinePlaceholder":162},[38,4900,4902,4904,4907,4909,4911,4914,4916,4919,4921,4923,4926,4929,4932],{"class":40,"line":4901},101,[38,4903,2395],{"class":44},[38,4905,4906],{"class":52}," sys.version_info ",[38,4908,846],{"class":44},[38,4910,689],{"class":52},[38,4912,4913],{"class":68},"3",[38,4915,2292],{"class":52},[38,4917,4918],{"class":68},"13",[38,4920,1094],{"class":52},[38,4922,1378],{"class":44},[38,4924,4925],{"class":68}," hasattr",[38,4927,4928],{"class":52},"(sys, ",[38,4930,4931],{"class":753},"\"disable_gil\"",[38,4933,813],{"class":52},[38,4935,4937,4939,4941,4943,4945,4948],{"class":40,"line":4936},102,[38,4938,4004],{"class":68},[38,4940,750],{"class":52},[38,4942,4012],{"class":753},[38,4944,4874],{"class":68},[38,4946,4947],{"class":753},"禁用 GIL 的多線程:\"",[38,4949,770],{"class":52},[38,4951,4953,4956,4958,4960,4962],{"class":40,"line":4952},103,[38,4954,4955],{"class":52},"        run_nogil_multithreading(n_tasks, ",[38,4957,4851],{"class":4274},[38,4959,85],{"class":44},[38,4961,4223],{"class":753},[38,4963,770],{"class":52},[38,4965,4967,4969],{"class":40,"line":4966},104,[38,4968,4325],{"class":44},[38,4970,53],{"class":52},[38,4972,4974,4976,4978,4980,4982,4985],{"class":40,"line":4973},105,[38,4975,4004],{"class":68},[38,4977,750],{"class":52},[38,4979,4012],{"class":753},[38,4981,4874],{"class":68},[38,4983,4984],{"class":753},"禁用 GIL 的多線程: 需要 Python 3.13 並啟用 --disable-gil\"",[38,4986,770],{"class":52},[38,4988,4990],{"class":40,"line":4989},106,[38,4991,163],{"emptyLinePlaceholder":162},[38,4993,4995,4997,4999,5001,5003,5006],{"class":40,"line":4994},107,[38,4996,4823],{"class":68},[38,4998,750],{"class":52},[38,5000,4012],{"class":753},[38,5002,4874],{"class":68},[38,5004,5005],{"class":753},"=== I/O 綁定任務 (模擬網路請求) ===\"",[38,5007,770],{"class":52},[38,5009,5011,5013,5015,5017],{"class":40,"line":5010},108,[38,5012,4823],{"class":68},[38,5014,750],{"class":52},[38,5016,4840],{"class":753},[38,5018,770],{"class":52},[38,5020,5022,5024,5026,5028,5031],{"class":40,"line":5021},109,[38,5023,4848],{"class":52},[38,5025,4851],{"class":4274},[38,5027,85],{"class":44},[38,5029,5030],{"class":753},"\"io\"",[38,5032,770],{"class":52},[38,5034,5036],{"class":40,"line":5035},110,[38,5037,163],{"emptyLinePlaceholder":162},[38,5039,5041,5043,5045,5047,5049,5051],{"class":40,"line":5040},111,[38,5042,4823],{"class":68},[38,5044,750],{"class":52},[38,5046,4012],{"class":753},[38,5048,4874],{"class":68},[38,5050,4877],{"class":753},[38,5052,770],{"class":52},[38,5054,5056,5058,5060,5062,5064],{"class":40,"line":5055},112,[38,5057,4885],{"class":52},[38,5059,4851],{"class":4274},[38,5061,85],{"class":44},[38,5063,5030],{"class":753},[38,5065,770],{"class":52},[38,5067,5069],{"class":40,"line":5068},113,[38,5070,163],{"emptyLinePlaceholder":162},[38,5072,5074,5076,5078,5080,5082,5085],{"class":40,"line":5073},114,[38,5075,4823],{"class":68},[38,5077,750],{"class":52},[38,5079,4012],{"class":753},[38,5081,4874],{"class":68},[38,5083,5084],{"class":753},"Asyncio:\"",[38,5086,770],{"class":52},[38,5088,5090],{"class":40,"line":5089},115,[38,5091,5092],{"class":52},"    asyncio.run(run_asyncio(n_tasks))\n",[38,5094,5096],{"class":40,"line":5095},116,[38,5097,163],{"emptyLinePlaceholder":162},[38,5099,5101,5103,5105,5107,5109,5111,5113,5115,5117,5119,5121,5123,5125],{"class":40,"line":5100},117,[38,5102,2395],{"class":44},[38,5104,4906],{"class":52},[38,5106,846],{"class":44},[38,5108,689],{"class":52},[38,5110,4913],{"class":68},[38,5112,2292],{"class":52},[38,5114,4918],{"class":68},[38,5116,1094],{"class":52},[38,5118,1378],{"class":44},[38,5120,4925],{"class":68},[38,5122,4928],{"class":52},[38,5124,4931],{"class":753},[38,5126,813],{"class":52},[38,5128,5130,5132,5134,5136,5138,5140],{"class":40,"line":5129},118,[38,5131,4004],{"class":68},[38,5133,750],{"class":52},[38,5135,4012],{"class":753},[38,5137,4874],{"class":68},[38,5139,4947],{"class":753},[38,5141,770],{"class":52},[38,5143,5145,5147,5149,5151,5153],{"class":40,"line":5144},119,[38,5146,4955],{"class":52},[38,5148,4851],{"class":4274},[38,5150,85],{"class":44},[38,5152,5030],{"class":753},[38,5154,770],{"class":52},[38,5156,5158,5160],{"class":40,"line":5157},120,[38,5159,4325],{"class":44},[38,5161,53],{"class":52},[38,5163,5165,5167,5169,5171,5173,5175],{"class":40,"line":5164},121,[38,5166,4004],{"class":68},[38,5168,750],{"class":52},[38,5170,4012],{"class":753},[38,5172,4874],{"class":68},[38,5174,4984],{"class":753},[38,5176,770],{"class":52},[3533,5178,5179],{"id":5179},"執行結果分析",[28,5181,5185],{"className":5182,"code":5183,"language":5184,"meta":33,"style":33},"language-bash shiki shiki-themes github-light github-dark","$ uv run --no-project --python 3.13.5+freethreaded test.py\n\n=== CPU 密集型任務 (計算 Fibonacci 數列) ===\n多線程 (Multithreading):\nrun_multithreading 執行時間: 0.8912 秒\n\n多進程 (Multiprocessing):\nrun_multiprocessing 執行時間: 1.0846 秒\n\n禁用 GIL 的多線程:\nGIL 狀態: 禁用\nrun_nogil_multithreading 執行時間: 0.8713 秒\n\n=== I/O 綁定任務 (模擬網路請求) ===\n多線程 (Multithreading):\nrun_multithreading 執行時間: 1.0072 秒\n\n多進程 (Multiprocessing):\nrun_multiprocessing 執行時間: 1.1046 秒\n\nAsyncio:\nrun_asyncio 執行時間: 0.0000 秒\n\n禁用 GIL 的多線程:\nGIL 狀態: 禁用\nrun_nogil_multithreading 執行時間: 1.0093 秒\n","bash",[35,5186,5187,5210,5214,5237,5245,5259,5263,5271,5283,5287,5298,5309,5321,5325,5338,5344,5355,5359,5365,5376,5380,5385,5397,5401,5409,5417],{"__ignoreMap":33},[38,5188,5189,5192,5195,5198,5201,5204,5207],{"class":40,"line":41},[38,5190,5191],{"class":48},"$",[38,5193,5194],{"class":753}," uv",[38,5196,5197],{"class":753}," run",[38,5199,5200],{"class":68}," --no-project",[38,5202,5203],{"class":68}," --python",[38,5205,5206],{"class":753}," 3.13.5+freethreaded",[38,5208,5209],{"class":753}," test.py\n",[38,5211,5212],{"class":40,"line":56},[38,5213,163],{"emptyLinePlaceholder":162},[38,5215,5216,5219,5222,5225,5228,5231,5234],{"class":40,"line":79},[38,5217,5218],{"class":753},"===",[38,5220,5221],{"class":753}," CPU",[38,5223,5224],{"class":753}," 密集型任務",[38,5226,5227],{"class":52}," (計算 ",[38,5229,5230],{"class":753},"Fibonacci",[38,5232,5233],{"class":753}," 數列",[38,5235,5236],{"class":52},") ===\n",[38,5238,5239,5242],{"class":40,"line":91},[38,5240,5241],{"class":48},"多線程",[38,5243,5244],{"class":52}," (Multithreading):\n",[38,5246,5247,5250,5253,5256],{"class":40,"line":102},[38,5248,5249],{"class":48},"run_multithreading",[38,5251,5252],{"class":753}," 執行時間:",[38,5254,5255],{"class":68}," 0.8912",[38,5257,5258],{"class":753}," 秒\n",[38,5260,5261],{"class":40,"line":120},[38,5262,163],{"emptyLinePlaceholder":162},[38,5264,5265,5268],{"class":40,"line":134},[38,5266,5267],{"class":48},"多進程",[38,5269,5270],{"class":52}," (Multiprocessing):\n",[38,5272,5273,5276,5278,5281],{"class":40,"line":140},[38,5274,5275],{"class":48},"run_multiprocessing",[38,5277,5252],{"class":753},[38,5279,5280],{"class":68}," 1.0846",[38,5282,5258],{"class":753},[38,5284,5285],{"class":40,"line":148},[38,5286,163],{"emptyLinePlaceholder":162},[38,5288,5289,5292,5295],{"class":40,"line":159},[38,5290,5291],{"class":48},"禁用",[38,5293,5294],{"class":753}," GIL",[38,5296,5297],{"class":753}," 的多線程:\n",[38,5299,5300,5303,5306],{"class":40,"line":166},[38,5301,5302],{"class":48},"GIL",[38,5304,5305],{"class":753}," 狀態:",[38,5307,5308],{"class":753}," 禁用\n",[38,5310,5311,5314,5316,5319],{"class":40,"line":173},[38,5312,5313],{"class":48},"run_nogil_multithreading",[38,5315,5252],{"class":753},[38,5317,5318],{"class":68}," 0.8713",[38,5320,5258],{"class":753},[38,5322,5323],{"class":40,"line":185},[38,5324,163],{"emptyLinePlaceholder":162},[38,5326,5327,5329,5332,5335],{"class":40,"line":242},[38,5328,5218],{"class":753},[38,5330,5331],{"class":753}," I/O",[38,5333,5334],{"class":753}," 綁定任務",[38,5336,5337],{"class":52}," (模擬網路請求) ===\n",[38,5339,5340,5342],{"class":40,"line":254},[38,5341,5241],{"class":48},[38,5343,5244],{"class":52},[38,5345,5346,5348,5350,5353],{"class":40,"line":406},[38,5347,5249],{"class":48},[38,5349,5252],{"class":753},[38,5351,5352],{"class":68}," 1.0072",[38,5354,5258],{"class":753},[38,5356,5357],{"class":40,"line":421},[38,5358,163],{"emptyLinePlaceholder":162},[38,5360,5361,5363],{"class":40,"line":435},[38,5362,5267],{"class":48},[38,5364,5270],{"class":52},[38,5366,5367,5369,5371,5374],{"class":40,"line":451},[38,5368,5275],{"class":48},[38,5370,5252],{"class":753},[38,5372,5373],{"class":68}," 1.1046",[38,5375,5258],{"class":753},[38,5377,5378],{"class":40,"line":462},[38,5379,163],{"emptyLinePlaceholder":162},[38,5381,5382],{"class":40,"line":468},[38,5383,5384],{"class":48},"Asyncio:\n",[38,5386,5387,5390,5392,5395],{"class":40,"line":485},[38,5388,5389],{"class":48},"run_asyncio",[38,5391,5252],{"class":753},[38,5393,5394],{"class":68}," 0.0000",[38,5396,5258],{"class":753},[38,5398,5399],{"class":40,"line":491},[38,5400,163],{"emptyLinePlaceholder":162},[38,5402,5403,5405,5407],{"class":40,"line":511},[38,5404,5291],{"class":48},[38,5406,5294],{"class":753},[38,5408,5297],{"class":753},[38,5410,5411,5413,5415],{"class":40,"line":522},[38,5412,5302],{"class":48},[38,5414,5305],{"class":753},[38,5416,5308],{"class":753},[38,5418,5419,5421,5423,5426],{"class":40,"line":528},[38,5420,5313],{"class":48},[38,5422,5252],{"class":753},[38,5424,5425],{"class":68}," 1.0093",[38,5427,5258],{"class":753},[3547,5429,5431],{"id":5430},"cpu-密集型任務計算-fibonacci-數列","CPU 密集型任務（計算 Fibonacci 數列）",[11,5433,5434,5435],{},"執行時間排序：",[3556,5436,5437],{},"GIL Disabled (0.8713 秒) \u003C 多線程 (0.8912 秒) \u003C 多進程 (1.0846 秒)",[998,5439,5440,5445,5450],{},[1001,5441,5442,5444],{},[3556,5443,5241],{},"：受 GIL 限制，執行速度與單 CPU 執行差不多",[1001,5446,5447,5449],{},[3556,5448,5267],{},"：運用多個 CPU 核心加速",[1001,5451,5452,5455],{},[3556,5453,5454],{},"GIL Disabled","：運用多個 CPU 核心加速，且避免了多進程管理的額外開銷",[3547,5457,5459],{"id":5458},"io-綁定任務模擬網路請求","I/O 綁定任務（模擬網路請求）",[11,5461,5434,5462],{},[3556,5463,5464],{},"Asyncio (0.0000 秒) \u003C\u003C 多線程 (1.0072 秒) ≈ GIL Disabled (1.0093 秒) ≈ 多進程 (1.1046 秒)",[998,5466,5467,5473],{},[1001,5468,5469,5472],{},[3556,5470,5471],{},"多線程、多進程、GIL Disabled","：三者效能差不多",[1001,5474,5475,5478,5479,5482],{},[3556,5476,5477],{},"Asyncio","：效能最好，因為測試任務使用 ",[35,5480,5481],{},"await asyncio.sleep","，基本上不會有運行時間開銷",[3533,5484,5485],{"id":5485},"實際應用場景",[11,5487,5488],{},[3556,5489,5490],{},"首先需要考慮業務場景，做這個優化加速是否有需要？如果加速沒有很重要的話就是一個 Nice to have 的優化。",[3547,5492,5494],{"id":5493},"不建議使用-disabled-gil","不建議使用 Disabled GIL",[11,5496,5497],{},"目前 Disabled GIL 還在測試階段，許多套件都還沒完全支援，也需要自己處理變數管理等問題，目前不考慮使用。",[3547,5499,5501],{"id":5500},"適合使用-multiprocessing-的場景","適合使用 Multiprocessing 的場景",[11,5503,5504],{},"非 AI 的大量運算需求，可以使用 Multiprocessing 來加速：",[998,5506,5507,5513],{},[1001,5508,5509,5512],{},[3556,5510,5511],{},"售電平台的最佳參數求取","：目前策略使用網格搜索，可以切分網格分配給 CPU 執行",[1001,5514,5515,5518],{},[3556,5516,5517],{},"EV 管理平台","：需要定時計算電站使用率",[3547,5520,5522],{"id":5521},"適合使用-asyncio-的場景","適合使用 Asyncio 的場景",[11,5524,5525],{},"網路的大量需求，可以使用 Asyncio 來加速：",[998,5527,5528,5534,5552,5562],{},[1001,5529,5530,5533],{},[3556,5531,5532],{},"MQTT / OCPP","：這類 pub/sub 協議",[1001,5535,5536,3653,5539],{},[3556,5537,5538],{},"爬蟲或大量 Third-party API 請求",[998,5540,5541],{},[1001,5542,5543,5544,5547,5548,5551],{},"使用 ",[35,5545,5546],{},"aiohttp"," 替換 ",[35,5549,5550],{},"requests"," 模組",[1001,5553,5554,3653,5557],{},[3556,5555,5556],{},"Database 異步操作",[998,5558,5559],{},[1001,5560,5561],{},"pymongo 遷移到 async client (≥ v4.13)",[1001,5563,5564,3653,5567],{},[3556,5565,5566],{},"Web Framework",[998,5568,5569],{},[1001,5570,5571],{},"Flask 遷移到 FastAPI",[3533,5573,5574],{"id":5574},"參考資料",[998,5576,5577,5584,5591],{},[1001,5578,5579],{},[15,5580,5583],{"href":5581,"rel":5582},"https://www.youtube.com/watch?v=brYsDi-JajI",[19],"【python】asyncio的理解與入門，搞不明白協程？看這個視頻就夠了",[1001,5585,5586],{},[15,5587,5590],{"href":5588,"rel":5589},"https://www.youtube.com/watch?v=K0BjgYZbgfE&t=94s",[19],"【python】await機制詳解。再來個硬核內容，把並行和依賴背後的原理全給你講明白",[1001,5592,5593],{},[15,5594,5597],{"href":5595,"rel":5596},"https://pymongo.readthedocs.io/en/stable/async-tutorial.html",[19],"Async Tutorial - PyMongo 4.14.1 documentation",[1733,5599,5600],{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":33,"searchDepth":56,"depth":56,"links":5602},[5603,5604,5610,5611,5612,5616,5621],{"id":3535,"depth":56,"text":3536},{"id":3545,"depth":56,"text":3545,"children":5605},[5606,5607,5608,5609],{"id":3549,"depth":79,"text":3550},{"id":3601,"depth":79,"text":3602},{"id":3640,"depth":79,"text":3641},{"id":3677,"depth":79,"text":3678},{"id":3699,"depth":56,"text":3699},{"id":3850,"depth":56,"text":3850},{"id":5179,"depth":56,"text":5179,"children":5613},[5614,5615],{"id":5430,"depth":79,"text":5431},{"id":5458,"depth":79,"text":5459},{"id":5485,"depth":56,"text":5485,"children":5617},[5618,5619,5620],{"id":5493,"depth":79,"text":5494},{"id":5500,"depth":79,"text":5501},{"id":5521,"depth":79,"text":5522},{"id":5574,"depth":56,"text":5574},"2025-10-24","介紹 Python 並發處理方法，包括多線程、多進程、asyncio 以及其實務應用。",{},"/blog/concurrency",{"title":3529,"description":5623},"blog/concurrency",[1751,5629,5630,5477],"Concurrency","Threading","kN1Wwn-a_-qug2Xu4sKMYHWVsmetrprGl94eSxUxzbE",{"id":5633,"title":5634,"author":6,"body":5635,"category":1738,"date":5622,"description":6019,"extension":1741,"image":33,"language":1742,"meta":6020,"navigation":162,"path":6021,"seo":6022,"stem":6023,"tags":6024,"updatedAt":1752,"__hash__":6025},"blog/blog/python-gil-introduction.md","Python GIL 介紹",{"type":8,"value":5636,"toc":6007},[5637,5641,5646,5649,5669,5672,5676,5681,5685,5705,5709,5712,5787,5791,5794,5862,5866,5869,5893,5896,5916,5919,5975,5977],[3533,5638,5640],{"id":5639},"什麼是-gil","什麼是 GIL？",[22,5642,5643],{},[11,5644,5645],{},"💡 GIL 是 CPython 解釋器中的一個鎖，確保在任何時刻只有一個線程可以執行 Python 字節碼。",[11,5647,5648],{},"這意味著即使有多個線程，Python 程式也無法真正利用多核心 CPU 實現並行（parallelism），僅能實現並發（concurrency）的假象。GIL 為 Python 提供了以下好處：",[998,5650,5651,5657,5663],{},[1001,5652,5653,5656],{},[3556,5654,5655],{},"簡化種族條件（Race Conditions）","：防止Multi thread同時修改共享資料，降低記憶體損壞風險。",[1001,5658,5659,5662],{},[3556,5660,5661],{},"簡化垃圾回收（Garbage Collection）","：GIL 使記憶體管理更簡單，無需複雜的鎖機制。",[1001,5664,5665,5668],{},[3556,5666,5667],{},"歷史背景","：Python 於 1991 年設計時，多數電腦僅有單核心 CPU，GIL 是當時簡化實現的合理選擇。",[11,5670,5671],{},"然而，GIL 的缺點顯而易見：它限制了多核心 CPU 的利用率，使 Python 在 CPU 密集型任務（如數學計算、資料解析、AI 模型訓練）上的效能不如預期。",[3533,5673,5675],{"id":5674},"為什麼移除-gilpep-703-python-313","為什麼移除 GIL？（PEP 703, Python 3.13）",[22,5677,5678],{},[11,5679,5680],{},"💡 隨著硬體技術的進步（多核心 CPU 普及）和 Python 社群對高效能的需求，GIL 逐漸成為瓶頸。PEP 703（Python 3.13）提出使 GIL 可選，允許程式在編譯時或運行時禁用 GIL，讓Multi thread直接利用操作系統的線程調度器，實現真正的並行。",[3547,5682,5684],{"id":5683},"移除-gil-的動機","移除 GIL 的動機",[998,5686,5687,5693,5699],{},[1001,5688,5689,5692],{},[3556,5690,5691],{},"社群需求","：開發者希望 Python 能更快，並充分利用現代多核心硬體。",[1001,5694,5695,5698],{},[3556,5696,5697],{},"效能提升","：禁用 GIL 後，某些 CPU 密集型任務（如桶排序、分形生成）可顯著加速。",[1001,5700,5701,5704],{},[3556,5702,5703],{},"競爭壓力","：其他語言（如 Go、Rust）支援真正的並行，Python 需跟上時代。",[3547,5706,5708],{"id":5707},"移除-gil-的挑戰","移除 GIL 的挑戰",[11,5710,5711],{},"移除 GIL 並非易事，因為 Python 的許多核心機制依賴 GIL 的保護。以下是主要挑戰：",[2654,5713,5714,5746,5758,5775],{},[1001,5715,5716,5719],{},[3556,5717,5718],{},"引用計數（Reference Counting）",[998,5720,5721,5727],{},[1001,5722,5723,5726],{},[3556,5724,5725],{},"問題","：傳統的非原子引用計數（non-atomic reference counting）不具線程安全，可能導致種族條件。例如，refcount++ 分三步（讀、加、寫），可能被其他線程中斷。",[1001,5728,5729,3653,5732],{},[3556,5730,5731],{},"解決方案",[998,5733,5734,5740],{},[1001,5735,5736,5739],{},[3556,5737,5738],{},"原子引用計數","：線程安全，但速度慢 10x-100x。",[1001,5741,5742,5745],{},[3556,5743,5744],{},"偏向引用計數（Biased Reference Counting）","：檢查引用是否僅屬於單一線程，若是則使用快速的非原子計數，否則使用原子計數。",[1001,5747,5748,5751],{},[3556,5749,5750],{},"垃圾回收（Garbage Collection）",[998,5752,5753],{},[1001,5754,5755,5757],{},[3556,5756,5725],{},"：傳統垃圾回收依賴 GIL 保護，需改用延遲引用計數（deferred reference counting）來處理循環引用。",[1001,5759,5760,5763],{},[3556,5761,5762],{},"記憶體分配",[998,5764,5765,5770],{},[1001,5766,5767,5769],{},[3556,5768,5725],{},"：現有記憶體分配器假設 GIL 保護，不具線程安全。",[1001,5771,5772,5774],{},[3556,5773,5731],{},"：開發新的線程安全記憶體分配器，優化列表和字典的快速讀取。",[1001,5776,5777,5780],{},[3556,5778,5779],{},"兼容性",[998,5781,5782],{},[1001,5783,5784,5786],{},[3556,5785,5725],{},"：許多 C-API 擴展（如 NumPy、Pandas）假設 GIL 存在，需重新編譯以支援無 GIL 環境。",[3533,5788,5790],{"id":5789},"gil-與禁用-gil-的比較","GIL 與禁用 GIL 的比較",[11,5792,5793],{},"以下表格比較了 GIL 和禁用 GIL 的特點：",[3701,5795,5796,5808],{},[3704,5797,5798],{},[3707,5799,5800,5802,5805],{},[3710,5801,3712],{},[3710,5803,5804],{},"啟用 GIL",[3710,5806,5807],{},"禁用 GIL",[3726,5809,5810,5823,5836,5849],{},[3707,5811,5812,5817,5820],{},[3731,5813,5814],{},[3556,5815,5816],{},"並行性",[3731,5818,5819],{},"非真正的並行，僅一個線程執行",[3731,5821,5822],{},"真正的Multi thread並行，利用多核心",[3707,5824,5825,5830,5833],{},[3731,5826,5827],{},[3556,5828,5829],{},"資料共享",[3731,5831,5832],{},"簡單，無需額外鎖",[3731,5834,5835],{},"需小心處理種族條件（如使用 threading.Lock）",[3707,5837,5838,5843,5846],{},[3731,5839,5840],{},[3556,5841,5842],{},"效能",[3731,5844,5845],{},"受限於 GIL，CPU 綁定任務慢",[3731,5847,5848],{},"視程式而定，可能顯著提升（如桶排序、分形生成）",[3707,5850,5851,5856,5859],{},[3731,5852,5853],{},[3556,5854,5855],{},"擴展相容性",[3731,5857,5858],{},"廣泛支援",[3731,5860,5861],{},"需檢查擴展版本（如 Cython、NumPy）",[3533,5863,5865],{"id":5864},"禁用-gil-的推薦場景","禁用 GIL 的推薦場景",[11,5867,5868],{},"禁用 GIL 在以下場景中特別有用：",[998,5870,5871,5877,5882,5887],{},[1001,5872,5873,5876],{},[3556,5874,5875],{},"ETL 處理","：資料提取、轉換和載入需要大量計算。",[1001,5878,5879,5881],{},[3556,5880,3624],{},"：如濾波、轉換等 CPU 密集型操作。",[1001,5883,5884,5886],{},[3556,5885,3627],{},"：處理大量資料並進行模式匹配。",[1001,5888,5889,5892],{},[3556,5890,5891],{},"即時分析","：需要快速響應的計算任務。",[3533,5894,5895],{"id":5895},"注意事項",[998,5897,5898,5904,5910],{},[1001,5899,5900,5903],{},[3556,5901,5902],{},"Race Condition","：禁用 GIL 後，Multi thread可能同時存取共享資料，導致記憶體損壞。建議使用 threading.Lock 或其他同步機制。",[1001,5905,5906,5909],{},[3556,5907,5908],{},"擴展模組相容性","：確認使用的庫（如 NumPy、Pandas、PyTorch）支援無 GIL 環境。",[1001,5911,5912,5915],{},[3556,5913,5914],{},"效能不確定性","：禁用 GIL 不保證所有程式都變快，需針對具體任務進行基準測試。",[3533,5917,5918],{"id":5918},"常見誤解與解答",[2654,5920,5921,5935,5945,5955,5965],{},[1001,5922,5923,5926,5927],{},[3556,5924,5925],{},"並發(Concurrency)與並行(Parallelism)的區別","：",[998,5928,5929,5932],{},[1001,5930,5931],{},"並發是多任務「看似」同時進行，實際上可能是切換執行。",[1001,5933,5934],{},"並行是多任務在多核心上真正同時執行。",[1001,5936,5937,5940],{},[3556,5938,5939],{},"為什麼 Python 慢？",[998,5941,5942],{},[1001,5943,5944],{},"GIL 限制了Multi thread的並行性，導致 CPU 綁定任務無法充分利用多核心。",[1001,5946,5947,5950],{},[3556,5948,5949],{},"禁用 GIL 如何管理 CPU 使用？",[998,5951,5952],{},[1001,5953,5954],{},"透過操作系統的線程調度器，讓Multi thread在多核心上並行執行。",[1001,5956,5957,5960],{},[3556,5958,5959],{},"禁用 GIL 是否總是更快？",[998,5961,5962],{},[1001,5963,5964],{},"不一定，效能提升取決於任務類型和程式設計。某些任務（如 I/O 綁定）可能無明顯改善。",[1001,5966,5967,5970],{},[3556,5968,5969],{},"簡單資料共享是什麼？",[998,5971,5972],{},[1001,5973,5974],{},"指線程間直接存取記憶體的能力，而Multi process需要管道或共享記憶體，較為複雜。",[3533,5976,5574],{"id":5574},[998,5978,5979,5986,5993,6000],{},[1001,5980,5981],{},[15,5982,5985],{"href":5983,"rel":5984},"https://peps.python.org/pep-0703/",[19],"PEP 703 – Making the Global Interpreter Lock Optional in CPython",[1001,5987,5988],{},[15,5989,5992],{"href":5990,"rel":5991},"https://tw.pycon.org/2025/zh-hant/conference/keynotes#Donghee_Na",[19],"PyCon TW 2025 主題演講",[1001,5994,5995],{},[15,5996,5999],{"href":5997,"rel":5998},"https://tw.pycon.org/2025/zh-hant/conference/talk/352",[19],"PyCon TW 2025 - Talk 352",[1001,6001,6002],{},[15,6003,6006],{"href":6004,"rel":6005},"https://tw.pycon.org/2025/zh-hant/conference/talk/335",[19],"PyCon TW 2025 - Talk 335",{"title":33,"searchDepth":56,"depth":56,"links":6008},[6009,6010,6014,6015,6016,6017,6018],{"id":5639,"depth":56,"text":5640},{"id":5674,"depth":56,"text":5675,"children":6011},[6012,6013],{"id":5683,"depth":79,"text":5684},{"id":5707,"depth":79,"text":5708},{"id":5789,"depth":56,"text":5790},{"id":5864,"depth":56,"text":5865},{"id":5895,"depth":56,"text":5895},{"id":5918,"depth":56,"text":5918},{"id":5574,"depth":56,"text":5574},"Python 全域直譯器鎖（GIL）介紹",{},"/blog/python-gil-introduction",{"title":5634,"description":6019},"blog/python-gil-introduction",[1751,5302,5630,5629],"1JlER9elCE4iurskWIIr2pl19MOnyKoNU2R4fwmCB4w",1790038954711]