6.25_開啟轉盤鎖_heapq(python)_HashMap(java)_char**(c的賦值)
6.25_開啟轉盤鎖:
你有一個帶有四個圓形撥輪的轉盤鎖。每個撥輪都有10個數字: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' 。每個撥輪可以自由旋轉:例如把 '9' 變為'0','0' 變為 '9' 。每次旋轉都只能旋轉一個撥輪的一位數字。
鎖的初始數字為 '0000' ,一個代表四個撥輪的數字的字串。
列表 deadends 包含了一組死亡數字,一旦撥輪的數字和列表裡的任何一個元素相同,這個鎖將會被永久鎖定,無法再被旋轉。
字串 target 代表可以解鎖的數字,你需要給出解鎖需要的最小旋轉次數,如果無論如何不能解鎖,返回 -1 。
示例 1:
輸入:deadends = ["0201","0101","0102","1212","2002"], target = "0202"
輸出:6
解釋:
可能的移動序列為 "0000" -> "1000" -> "1100" -> "1200" -> "1201" -> "1202" -> "0202"。
注意 "0000" -> "0001" -> "0002" -> "0102" -> "0202" 這樣的序列是不能解鎖的,
因為當撥動到 "0102" 時這個鎖就會被鎖定。
示例 2:
輸入: deadends = ["8888"], target = "0009"
輸出:1
解釋:
把最後一位反向旋轉一次即可 "0000" -> "0009"。
示例 3:
輸入: deadends = ["8887","8889","8878","8898","8788","8988","7888","9888"], target = "8888"
輸出:-1
解釋:
無法旋轉到目標數字且不被鎖定。
示例 4:
輸入: deadends = ["0000"], target = "8888"
輸出:-1
提示:
1 <=deadends.length <= 500
deadends[i].length == 4
target.length == 4
target 不在 deadends 之中
target 和 deadends[i] 僅由若干位數字組成
連結:https://leetcode-cn.com/problems/open-the-lock
1、java
import java.util.*; class Solution { public static int openLock(String[] deadends, String target) { if ("0000".equals(target)) { return 0; } Set<String> dead = new HashSet<>(); for (String deadend : deadends) { dead.add(deadend); }View Codeif (dead.contains("0000")) { return -1; } int step = 0; Queue<String> queue = new LinkedList<String>(); queue.offer("0000"); Set<String> seen = new HashSet<String>(); seen.add("0000"); while (!queue.isEmpty()) { ++step; int size = queue.size(); for (int i = 0; i < size; ++i) { String status = queue.poll(); for (String nextStatus : get(status)) { if (!seen.contains(nextStatus) && !dead.contains(nextStatus)) { if (nextStatus.equals(target)) { return step; } queue.offer(nextStatus); seen.add(nextStatus); } } } } return -1; } public static char numPrev(char x) { return x == '0' ? '9' : (char) (x - 1); } public static char numSucc(char x) { return x == '9' ? '0' : (char) (x + 1); } // 列舉 status 通過一次旋轉得到的數字 public static List<String> get(String status) { List<String> ret = new ArrayList<String>(); char[] array = status.toCharArray(); for (int i = 0; i < 4; ++i) { char num = array[i]; array[i] = numPrev(num); ret.add(new String(array)); array[i] = numSucc(num); ret.add(new String(array)); array[i] = num; } return ret; } public static void main(String[] args) { String[] deadends = {"0201","0101","0102","1212","2002"}; String target = "0202"; System.out.println(openLock(deadends, target)); } }
// HashSet集合,contains if (dead.contains("0000")) { return -1; }
Queue<String> queue = new LinkedList<String>(); // 新增元素 queue.offer("a"); // 遍歷元素 for(String q : queue){ System.out.println(q); } // 返回第一個元素,並在佇列中刪除 queue.poll(); queue.element(); //返回第一個元素 queue.peek(); //返回第一個元素 LinkedList<String> sites = new LinkedList<String>(); sites.add("Taobao"); // 使用 addFirst() 在頭部新增元素 sites.addFirst("Wiki"); // 使用 addLast() 在尾部新增元素 sites.addLast("Wiki"); // 使用 removeFirst() 移除頭部元素 sites.removeFirst(); // 使用 removeLast() 移除尾部元素 sites.removeLast(); // 使用 getFirst() 獲取頭部元素 System.out.println(sites.getFirst()); // 使用 getLast() 獲取尾部元素 System.out.println(sites.getLast()); // 迭代元素 for (int size = sites.size(), i = 0; i < size; i++) { System.out.println(sites.get(i)); }
// 建立 HashMap 物件 Sites HashMap<Integer, String> Sites = new HashMap<Integer, String>(); // 新增鍵值對 Sites.put(1, "Google"); // 使用 get(key) 方法來獲取 key 對應的 value: Sites.get(3) // remove(key) 方法來刪除 key 對應的鍵值對(key-value): Sites.remove(4); // 刪除所有鍵值對(key-value)可以使用 clear 方法: Sites.clear(); Sites.size(); // 輸出 key 和 value for (Integer i : Sites.keySet()) { System.out.println("key: " + i + " value: " + Sites.get(i)); } // 返回所有 value 值 for(String value: Sites.values()) { // 輸出每一個value System.out.print(value + ", "); }
2、c++
//#include "iostream" //#include "vector" //#include "unordered_set" //#include "queue" //using namespace std; // //class Solution { //public: // int openLock(vector<string>& deadends, const string& target) { // if (target == "0000") { // return 0; // } // // unordered_set<string> dead(deadends.begin(), deadends.end()); // if (dead.count("0000")) { // return -1; // } // // auto num_prev = [](char x) -> char { // return (x == '0' ? '9' : x - 1); // }; // auto num_succ = [](char x) -> char { // return (x == '9' ? '0' : x + 1); // }; // // // 列舉 status 通過一次旋轉得到的數字 // auto get = [&](string& status) -> vector<string> { // vector<string> ret; // for (int i = 0; i < 4; ++i) { // char num = status[i]; // status[i] = num_prev(num); // ret.push_back(status); // status[i] = num_succ(num); // ret.push_back(status); // status[i] = num; // } // return ret; // }; // // queue<pair<string, int>> q; // q.emplace("0000", 0); // unordered_set<string> seen = {"0000"}; // // while (!q.empty()) { // auto [status, step] = q.front(); // q.pop(); // for (auto&& next_status: get(status)) { // if (!seen.count(next_status) && !dead.count(next_status)) { // if (next_status == target) { // return step + 1; // } // q.emplace(next_status, step + 1); // seen.insert(move(next_status)); // } // } // } // // return -1; // } //}; // //// 報錯的,為啥?? //int main() { // vector<string> deadends = {"0201","0101","0102","1212","2002"}; // string target = "0202"; // cout << Solution().openLock(deadends, target) << endl; //} #include "iostream" #include "vector" #include "unordered_set" #include "queue" using namespace std; struct AStar { // 計算啟發函式 static int getH(const string& status, const string& target) { int ret = 0; for (int i = 0; i < 4; ++i) { int dist = abs(int(status[i]) - int(target[i])); ret += min(dist, 10 - dist); } return ret; }; AStar(const string& status, const string& target, int g): status_{status}, g_{g}, h_{getH(status, target)} { f_ = g_ + h_; } bool operator< (const AStar& that) const { return f_ > that.f_; } string status_; int f_, g_, h_; }; class Solution { public: int openLock(vector<string>& deadends, string target) { if (target == "0000") { return 0; } unordered_set<string> dead(deadends.begin(), deadends.end()); if (dead.count("0000")) { return -1; } auto num_prev = [](char x) -> char { return (x == '0' ? '9' : x - 1); }; auto num_succ = [](char x) -> char { return (x == '9' ? '0' : x + 1); }; auto get = [&](string& status) -> vector<string> { vector<string> ret; for (int i = 0; i < 4; ++i) { char num = status[i]; status[i] = num_prev(num); ret.push_back(status); status[i] = num_succ(num); ret.push_back(status); status[i] = num; } return ret; }; priority_queue<AStar> q; q.emplace("0000", target, 0); unordered_set<string> seen = {"0000"}; while (!q.empty()) { AStar node = q.top(); q.pop(); for (auto&& next_status: get(node.status_)) { if (!seen.count(next_status) && !dead.count(next_status)) { if (next_status == target) { return node.g_ + 1; } q.emplace(next_status, target, node.g_ + 1); seen.insert(move(next_status)); } } } return -1; } }; // 這個就可以執行!! int main() { vector<string> deadends = {"0201","0101","0102","1212","2002"}; string target = "0202"; cout << Solution().openLock(deadends, target) << endl; }View Code
3、c
#include "stdio.h" #include ".\lib\uthash-master\src\uthash.h" /* UT_hash_handle */ struct HashTable { char str[5]; UT_hash_handle hh; }; struct Node { char str[5]; int val; }; char num_prev(char x) { return (x == '0' ? '9' : x - 1); } char num_succ(char x) { return (x == '9' ? '0' : x + 1); } // 列舉 status 通過一次旋轉得到的數字 char** getNextStatus(char* status, int* retSize) { char** ret = malloc(sizeof(char*) * 8); *retSize = 0; for (int i = 0; i < 4; ++i) { char num = status[i]; status[i] = num_prev(num); ret[(*retSize)] = malloc(sizeof(char) * 5); strcpy(ret[(*retSize)++], status); status[i] = num_succ(num); ret[(*retSize)] = malloc(sizeof(char) * 5); strcpy(ret[(*retSize)++], status); status[i] = num; } return ret; } int openLock(char** deadends, int deadendsSize, char* target) { char str_0[5] = "0000"; if (strcmp(target, str_0) == 0) { return 0; } struct HashTable* dead = NULL; struct HashTable* tmp; for (int i = 0; i < deadendsSize; i++) { HASH_FIND(hh, dead, deadends[i], sizeof(char) * 5, tmp); if (tmp == NULL) { tmp = malloc(sizeof(struct HashTable)); strcpy(tmp->str, deadends[i]); HASH_ADD(hh, dead, str, sizeof(char) * 5, tmp); } } HASH_FIND(hh, dead, str_0, sizeof(char) * 5, tmp); if (tmp != NULL) { return -1; } struct Node q[10001]; int left = 0, right = 0; strcpy(q[right].str, str_0); q[right++].val = 0; struct HashTable* seen = NULL; tmp = malloc(sizeof(struct HashTable)); strcpy(tmp->str, str_0); HASH_ADD(hh, seen, str, sizeof(char) * 5, tmp); while (left < right) { char* status = q[left].str; int step = q[left++].val; int nextStatusSize; char** nextStatus = getNextStatus(status, &nextStatusSize); for (int i = 0; i < nextStatusSize; i++) { struct HashTable *tmp1, *tmp2; HASH_FIND(hh, dead, nextStatus[i], sizeof(char) * 5, tmp1); HASH_FIND(hh, seen, nextStatus[i], sizeof(char) * 5, tmp2); if (tmp1 == NULL && tmp2 == NULL) { if (strcmp(nextStatus[i], target) == 0) { return step + 1; } strcpy(q[right].str, nextStatus[i]); q[right++].val = step + 1; tmp = malloc(sizeof(struct HashTable)); strcpy(tmp->str, nextStatus[i]); HASH_ADD(hh, seen, str, sizeof(char) * 5, tmp); } } } return -1; } int main() { char* deadends[] = {"0201", "0101", "0102", "1212", "2002"}; int deadendsSize = sizeof(deadends) / sizeof(deadends[0]); char* target = "0202"; printf("%d ", openLock(deadends, deadendsSize, target)); }View Code
4、python
import heapq # 堆 from typing import Generator, List class AStar: # 計算啟發函式 @staticmethod def getH(status: str, target: str) -> int: ret = 0 for i in range(4): dist = abs(int(status[i]) - int(target[i])) ret += min(dist, 10 - dist) return ret def __init__(self, status: str, target: str, g: str) -> None: self.status = status self.g = g self.h = AStar.getH(status, target) self.f = self.g + self.h def __lt__(self, other: "AStar") -> bool: return self.f < other.f class Solution: def openLock(self, deadends: List[str], target: str) -> int: if target == "0000": return 0 dead = set(deadends) if "0000" in dead: return -1 def num_prev(x: str) -> str: return "9" if x == "0" else str(int(x) - 1) def num_succ(x: str) -> str: return "0" if x == "9" else str(int(x) + 1) def get(status: str) -> Generator[str, None, None]: s = list(status) for i in range(4): num = s[i] s[i] = num_prev(num) yield "".join(s) s[i] = num_succ(num) yield "".join(s) s[i] = num q = [AStar("0000", target, 0)] seen = {"0000"} while q: node = heapq.heappop(q) for next_status in get(node.status): if next_status not in seen and next_status not in dead: if next_status == target: return node.g + 1 heapq.heappush(q, AStar(next_status, target, node.g + 1)) seen.add(next_status) return -1 if __name__ == "__main__": # openLock(self, deadends: List[str], target: str) deadends = ["0201", "0101", "0102", "1212", "2002"] target = "0202" print(Solution().openLock(deadends, target))View Code
Python的富比較方法包括__lt__、__gt__
分別表示:小於、大於,對應的操作運算子為:“<”、“>”。
當一個定義另一個未定義時,未定義的操作執行時會呼叫已經定義的方法求反。這個與__eq__和__ne__的關係還是有較大的不同。
heapq堆的常用方法:
import heapq hList = [] # heapq.heappush(heap, item), heap為定義堆,item增加的元素 heapq.heappush(hList, 2) print(hList) # heapq.heapify(list), 將列表轉換為堆 exampleList = [1,2,3,5,1,5,8,9,6] print(exampleList) heapq.heapify(exampleList) # 跟列表區別??? print(exampleList, type(exampleList)) # heapq.heappop(heap),刪除並返回最小值, # 因為堆的特徵是heap[0]永遠是最小的元素,所以一般都是刪除第一個元素。 print(heapq.heappop(exampleList)) print("heappop: ", exampleList) # heapq.heapreplace(heap.item), 刪除並返回最小元素值,新增新的元素值 print(heapq.heapreplace(exampleList, 99)) print("heapreplace: ", exampleList) # heapq.heappushpop(list,item) # 判斷新增元素值與堆的第一個元素值對比;如果大,則刪除並返回第一個元素,然後新增新元素值item. # 如果小,則返回item. 原堆不變。 print(heapq.heappushpop(exampleList,6)) print("heappushpop:", exampleList) # heapq.merge(…),將多個堆合併 h = [1000] heapq.merge(h,exampleList) # 不改變原來的列表 print("merge: ", h) print("merge: ", exampleList) for i in heapq.merge(h,exampleList): print(i,end=" ") # heapq.nlargest(n,heap), 查詢堆中的最大n個元素 print(heapq.nlargest(3,exampleList)) # heapq.nsmallest(n,heap),查詢堆中的最小n個元素 print(heapq.nsmallest(3,exampleList)) # 使用heapq編寫優先順序佇列 class PriorityQueue: def __init__(self): self.__queue = [] self.__index = 0 def push(self, item, priority): heapq.heappush(self.__queue, (-priority, self.__index, item)) # 第一個引數:新增進的目標序列 # 第二個引數:將一個元組作為整體新增進序列,目的是為了方便比較 # 在priority相等的情況下,比較_index # priority為負數使得新增時按照優先順序從大到小排序,因為堆排序的序列的第一個元素永遠是最小的 self.__index += 1 def pop(self): # 返回按照-priority 和 _index 排序後的第一個元素(是一個元組)的最後一個元素(item) return heapq.heappop(self.__queue)[-1] q = PriorityQueue() q.push("bar", 2) q.push("foo", 1) q.push("gork", 3) q.push("new", 1) print(q.pop()) print(q.pop()) print(q.pop()) print(q.pop()) """ gork # 優先順序最高 bar # 優先順序第二 foo # 優先順序與new相同,比較index,因為先加入,index比new小,所以排在前面 new """ # 回頭用到再仔細研究佇列