【技術積累】算法中的貪心算法【三】 天天關注
時間:2023-06-25 10:00:58
貪心算法解決最短超級字符串問題
問題描述
(資料圖片)
給定一個字符串數組,要求找出一個最短的超級字符串,即包含所有字符串的字符串,并且每個字符串僅出現一次。
輸入:["abc", "bcd", "cde"]
輸出:"abcde"
解題思路
1. 將給定的字符串數組按照長度從大到小排序,記為strings。2. 定義一個數組visited,用于記錄每個字符串是否被訪問過,初始值都為false。3. 定義一個變量result,用于記錄最終的最短超級字符串,初始值為空字符串。4. 從第一個字符串開始遍歷strings數組: a. 如果當前字符串已經被訪問過,跳過該字符串。 b. 將當前字符串添加到result中,并將visited數組中對應位置設為true。 c. 從當前字符串的末尾開始,找到strings數組中還未訪問過的字符串中最長的公共后綴,將其添加到result中,更新visited數組。5. 遍歷完所有字符串后,result中存儲的就是最短超級字符串。
偽代碼
function findShortestSuperstring(strings): // 按照長度從大到小排序 sort(strings, descending order of length) // 記錄每個字符串是否被訪問 visited = new Array(strings.length, false) // 存儲最短超級字符串 result = "" for i from 1 to strings.length: if visited[i] is true: continue result += strings[i] visited[i] = true start = strings[i].length while start > 0: maxLen = 0 maxIdx = -1 for j from 0 to strings.length: if visited[j] is true: continue len = commonSuffix(strings[i], strings[j]) if len > maxLen: maxLen = len maxIdx = j if maxIdx == -1: break result += strings[j].substring(maxLen) visited[maxIdx] = true start = strings[maxIdx].length return resultfunction commonSuffix(str1, str2): len1 = str1.length len2 = str2.length len = min(len1, len2) suffix = "" for i from 1 to len: if str1.substring(len1 - i) == str2.substring(0, i): suffix = str2.substring(0, i) return suffix
貪心算法解決最佳工作序列問題
問題描述
有n個待完成的工作,每個工作有一個開始時間和一個結束時間,要求找出一個最佳的工作序列,使得這些工作能夠順利完成,且盡可能多的工作能夠被完成。
解題思路
1. 將給定的工作列表按照結束時間從小到大排序。2. 定義一個變量result,用于記錄最終選擇的最佳工作序列,初始為空序列。3. 選擇第一個工作,將其加入result中。4. 從第二個工作開始遍歷工作列表: a. 如果當前工作的開始時間在上一個工作的結束時間之后,說明可以選擇該工作,將其加入result中。 b. 更新上一個工作為當前工作。5. 遍歷完所有工作后,result中存儲的就是最佳的工作序列。
偽代碼
function findBestJobSequence(jobs): // 按照結束時間從小到大排序 sort(jobs, ascending order of end time) // 存儲最佳工作序列 result = [] result.push(jobs[0]) prevJob = jobs[0] for i from 1 to jobs.length: currJob = jobs[i] if currJob.startTime >= prevJob.endTime: result.push(currJob) prevJob = currJob return result
注意:此處假設輸入的工作列表是類似結構的數據,包含每個工作的開始時間和結束時間的信息,可以根據實際需求進行修改。
貪心算法解決最優加油問題
問題描述
在一條道路上有一輛汽車,道路的長度為L。汽車的油箱容量為C,初始時汽車油箱為空。汽車需要從起點到終點,期間會遇到N個加油站,每個加油站距離起點的距離為d,每個加油站可加油量為v。要求找到一個最優的加油方案,使得汽車能夠順利到達終點,且加油次數最少。
解題思路
1. 定義一個變量tank,用于存儲汽車的當前油量,初始值為0。2. 定義一個變量count,用于存儲加油次數,初始值為0。3. 定義一個變量currDistance,用于存儲當前汽車到達的距離,初始值為0。4. 初始化一個最大堆maxHeap,用于存儲可選的加油站,按照加油量v進行排序。5. 遍歷加油站集合: a. 將當前加油站加入最大堆maxHeap。 b. 如果汽車的油量tank不足以到達當前加油站,且最大堆maxHeap不為空: - 從最大堆maxHeap中取出一個加油站,記為station。 - 計算需要從上一個加油站到達當前加油站所需的油量,記為requiredGas = station.distance - currDistance。 - 如果requiredGas大于汽車的油量tank,則無法到達當前加油站,返回-1。 - 將汽車的油量tank加上requiredGas,并將計數器count加1,表示加了一次油。 - 更新當前汽車到達的距離currDistance為當前加油站的距離。 c. 如果汽車的油量tank仍然不足以到達終點,則無法順利到達終點,返回-1。6. 返回計數器count,表示最少的加油次數。
偽代碼
function findOptimalRefueling(stations, L, C): tank = 0 count = 0 currDistance = 0 maxHeap = initializeMaxHeap() for each station in stations: addStationToMaxHeap(maxHeap, station) if tank < station.distance - currDistance and !isEmpty(maxHeap): while tank < station.distance - currDistance and !isEmpty(maxHeap): station = removeMaxFromHeap(maxHeap) requiredGas = station.distance - currDistance if requiredGas > tank: return -1 tank += requiredGas count += 1 currDistance = station.distance if tank < station.distance - currDistance: return -1 return count
注意:此處假設輸入的加油站集合是一個類似結構的數據,包含每個加油站的距離和可加油量的信息,可以根據實際需求進行修改。
貪心算法解決硬幣問題
算法問題描述:給定一個金額amount和一系列面額不同的硬幣,要求用最少的硬幣組合來湊成amount,并返回硬幣的數量。假設有足夠數量的每種硬幣。
樣例輸入輸出:輸入:amount = 11, coins = [1, 2, 5]輸出:3
解題思路:1. 初始化一個變量count,用于記錄所需的硬幣數量。2. 對面額數組coins進行降序排序,方便貪心選擇。3. 遍歷coins數組,記當前的硬幣面額為coin。4. 若當前硬幣面額coin小于等于amount,則將amount除以coin的商記為numCoins,表示可以使用numCoins個硬幣coin來湊成amount。 - 將numCoins加到count中。 - 將amount更新為amount減去numCoins個硬幣coin的面值。5. 返回count。
偽代碼:
function coinChange(amount, coins) count = 0 sort coins in descending order for coin in coins if coin <= amount then numCoins = amount / coin count = count + numCoins amount = amount - (numCoins * coin) return count
說明:在此問題中,通過貪心選擇每次選擇最大面額的硬幣,因為硬幣的面額是固定的,所以這是一個可以使用貪心算法解決的合適情況。由于要求找出最少的硬幣數量,因此我們先選擇面額最大的硬幣是最優的選擇。然后逐步減少amount,直到amount變為0。注意,這里貪心選擇可能不是全局最優解,但在這個問題中,貪心選擇是可以得到最優解的。
貪心算法解決射擊游戲問題
問題描述:
在一個射擊游戲中,玩家需要射擊一些不同顏色的氣球。每個氣球都有一個指定的得分值和一個爆炸半徑。假設玩家的射擊點是一個二維平面上的坐標(x, y),當玩家發射子彈到該點時,子彈會以該點為中心形成一個爆炸范圍。任何與爆炸范圍相交的氣球都會被擊中。玩家的得分等于所有被擊中氣球的得分值之和。現在,給定一些氣球的坐標、得分值和爆炸半徑,需要確定玩家應該選擇哪個射擊點來使得得分最大化。
樣例輸入輸出:
輸入:氣球列表:[(1,2,3), (2,5,4), (3,1,2), (4,9,5)]描述:[氣球的坐標(x, y),得分值,爆炸半徑]
輸出:最大得分值:14 (通過擊中(1,2)和(2,5)這兩個氣球)
解題思路:
1. 創建一個空集合visited來保存已擊中的氣球。2. 遍歷氣球列表,每次選擇得分值最高的氣球,并將其加入visited集合。3. 定義一個函數is_overlap用來判斷兩個氣球是否有重疊的爆炸范圍。兩個氣球的距離小于等于它們的爆炸半徑之和時,表示它們有重疊。4. 在遍歷氣球列表的過程中,檢查當前氣球與visited集合中的氣球是否有重疊的爆炸范圍。若有重疊,則選擇得分值更高的氣球加入visited集合,替代原有的氣球。5. 遍歷完所有氣球后,visited集合中保存的即為玩家應該擊中的氣球。6. 計算visited集合中氣球的得分值之和,即為最大得分值。
偽代碼:
function is_overlap(ball1, ball2): // 判斷兩個氣球是否有重疊的爆炸范圍 distance = sqrt((ball1.x - ball2.x)^2 + (ball1.y - ball2.y)^2) return distance <= ball1.radius + ball2.radiusfunction shooting_game(balloons): visited = set() max_score = 0 for i in range(len(balloons)): if i not in visited: // 未被擊中過的氣球 visited.add(i) max_score += balloons[i].score for j in range(len(balloons)): if i != j and is_overlap(balloons[i], balloons[j]): if balloons[j].score > balloons[i].score: visited.remove(i) max_score -= balloons[i].score visited.add(j) max_score += balloons[j].score return max_score// 測試balloons = [(1,2,3), (2,5,4), (3,1,2), (4,9,5)]max_score = shooting_game(balloons)print(max_score)
貪心算法解決數組重組問題
算法問題描述:
給定一個整數數組nums,現在需要將數組中的元素重新排列,使得任意兩個相鄰的元素之間的差的絕對值盡可能大。請實現一個函數,返回重組后的數組。注意,重組后的數組可能不是唯一的,只需返回任意一個滿足條件的數組即可。
樣例輸入輸出:
輸入:[1, 2, 3, 4, 5]輸出:[1, 3, 2, 4, 5]
解題思路:
1. 對數組進行排序,從小到大。2. 創建一個空的結果數組result[],并將排序后的第一個元素nums[0]加入result[]。3. 從第二個元素開始遍歷排序后的數組,逐個將元素插入result[]。4. 奇數索引位置上的元素應該盡量取較大的值,所以將當前元素插入result[]的奇數索引位置。5. 偶數索引位置上的元素應該盡量取較小的值,所以將當前元素插入result[]的偶數索引位置。6. 遍歷完所有元素后,result[]即為重組后的數組。
偽代碼:
function rearrange_array(nums): sorted_nums = sort(nums) result = [] result.append(sorted_nums[0]) for i in range(1, len(sorted_nums)): if i % 2 == 0: // 偶數索引位置 result.insert(i, sorted_nums[i]) else: // 奇數索引位置 result.append(sorted_nums[i]) return result// 測試nums = [1, 2, 3, 4, 5]rearranged_nums = rearrange_array(nums)print(rearranged_nums)
輸出:[1, 3, 2, 5, 4]
貪心算法解決左右兩邊元素和相等問題
算法問題描述:
給定一個整數數組nums,現在需要判斷是否存在一個索引,使得索引左邊的元素之和等于索引右邊的元素之和。如果存在這樣的索引,返回True;否則,返回False。
樣例輸入輸出:
輸入:[1, 7, 3, 6, 5, 6]輸出:True
解題思路:
1. 遍歷數組,計算數組中所有元素的和,得到總和total。2. 初始化左側元素之和left_sum為0。3. 從左到右遍歷數組,每次將當前元素加入左側元素之和left_sum,同時將總和total減去當前元素。4. 在遍歷的過程中,檢查左側元素之和left_sum是否等于右側元素之和total減去當前元素的值。若相等,表示存在滿足條件的索引,返回True。5. 若遍歷完所有元素后仍未找到滿足條件的索引,則返回False。
偽代碼:
function equal_sum(nums): total = sum(nums) left_sum = 0 for i in range(len(nums)): total -= nums[i] // 將總和減去當前元素 if left_sum == total: return True left_sum += nums[i] // 將當前元素加入左側元素之和 return False// 測試nums = [1, 7, 3, 6, 5, 6]has_equal_sum = equal_sum(nums)print(has_equal_sum)
輸出:True
貪心算法解決圖著色問題
算法問題描述:
給定一個無向圖,圖的頂點由一個整數標識,圖的邊由一個無序的頂點對表示。要求為圖的每個頂點分配一個顏色,同時要求相鄰的頂點不能有相同的顏色。現在需要設計一個算法,使用貪心算法解決圖著色問題,即找到符合要求的最小顏色數量。
Vertices: [1, 2, 3, 4, 5, 6]Edges: [(1, 2), (1, 3), (2, 4), (3, 4), (4, 5), (5, 6)]
樣例輸入
graph = { 1: [2, 3], 2: [1, 4], 3: [1, 4], 4: [2, 3, 5], 5: [4, 6], 6: [5]}
輸出:3
解題思路:1. 創建一個字典colors,用于存儲每個頂點的顏色值。初始時,將所有頂點的顏色初始化為-1,表示未分配顏色。2. 對圖中的每個頂點進行遍歷,對于每個頂點v,執行以下操作: 1) 創建一個集合used_colors,用于存儲v的鄰接頂點已經使用的顏色值。 2) 遍歷v的鄰接頂點,將顏色值加入到used_colors集合中。 3) 遍歷顏色值1到無窮大的整數,找到一個未被used_colors集合包含的最小整數,將此整數作為v的顏色值。3. 返回字典colors中顏色值的種類數量。
偽代碼:
function graphColoring(graph): colors = {} // 創建一個字典,存儲每個頂點的顏色 for each vertex v in graph: used_colors = set() // 創建集合,存儲v的鄰接頂點已分配的顏色值 for each adjacent_vertex in v.adjacent_vertices: if colors[adjacent_vertex] != -1: // 如果鄰接頂點已分配顏色 used_colors.add(colors[adjacent_vertex]) for color in range(1, infinity): // 從1到無窮大的整數 if color not in used_colors: // 找到一個未被鄰接頂點使用的最小顏色 colors[v] = color break return number of distinct colors in colors
其中,graph表示輸入的無向圖,每個頂點的顏色值存儲在字典colors中。最后,返回colors中不同顏色值的數量。
相關稿件
從“三代種桃人”看現代農業怎么干——算好加減法 做好“一二三”|每日時訊
云浮:“十四五”期末全市計劃新籌建保租房不少于1000套_世界訊息
環球快播:女孩充電被電擊內臟受損面臨截肢 蘋果官方:適配器非原裝,如果是第三方問題,不會賠償
打印紙產業深度調研報告 打印紙行業的前景與未來趨勢分析2023-環球即時看
全球微頭條丨端午假期民航鐵路出行均超2019年水平 拼假出行受歡迎
今熱點:【農牧飼漁】6月USDA跟蹤月報:6月USDA上調三大作物產量,持續關注厄爾尼諾
【天天播資訊】AMD RX 7800 XT顯卡新爆料,將采用新GPU
跨越2100公里,每年最多向浙江輸送300億千瓦時的四川水電 一條銀線 千里“閃送”