1.整数转罗马数字
python:
class Solution:def intToRoman(self, num: int) -> str:dict_ = {1000:'M', 900:'CM', 500:'D', 400:'CD', 100:'C', 90:'XC', 50:'L', 40:'XL', 10:'X', 9:'IX', 5:'V', 4:'IV', 1:'I'}res = ''for key in dict_:count = num // keyres += count * dict_[key]num %= keyreturn res
c++:
class Solution {
public:string intToRoman(int num) {int value[] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};string str_[] = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};string res;for(int i = 0; i < 13; i++){while(num >= value[i]){num -= value[i];res += str_[i];}}return res;}
};
2.电话号码的字母组合
python:
class Solution:def help(self, digits, track):if len(digits)==0:self.res.append(''.join(track))returnfor letter in self.dict_[digits[0]]:# store = track.copy()track.append(letter)self.help(digits[1:], track)# track.pop()track = storedef letterCombinations(self, digits: str) -> List[str]:if len(digits)==0:return []self.dict_={"2":"abc","3":"def","4":"ghi","5":"jkl","6":"mno","7":"pqrs","8":"tuv","9":"wxyz"}self.res = []self.help(digits, [])return self.res
c++:
class Solution {
public:vector<string> res;// unordered_map<char, string> phoneMap;void help(string digits, vector<char> track, unordered_map<char, string> phoneMap){if(digits.empty()){string str(track.begin(), track.end());res.push_back(str);}for(int i=0; i < phoneMap[digits[0]].size(); i++){track.push_back(phoneMap[digits[0]][i]);help(digits.substr(1, digits.size() - 1), track, phoneMap);track.pop_back();}}vector<string> letterCombinations(string digits) {if (digits.empty()) {return res;}unordered_map<char, string> phoneMap{{'2', "abc"},{'3', "def"},{'4', "ghi"},{'5', "jkl"},{'6', "mno"},{'7', "pqrs"},{'8', "tuv"},{'9', "wxyz"}};vector<char> track;help(digits, track, phoneMap);return res;}
};
3.有效的数独
思路用三个hash 记录即可
python:
class Solution:def isValidSudoku(self, board: List[List[str]]) -> bool:rows = [{i:0} for i in range(9)]# print(rows)cols = [{i:0} for i in range(9)]boxs = [{i:0} for i in range(9)]for i in range(9):for j in range(9):box_index = (i // 3) * 3 + j // 3if board[i][j] != '.':num = int(board[i][j])rows[i][num] = rows[i].get(num, 0) + 1cols[j][num] = cols[j].get(num, 0) + 1 boxs[box_index][num] = boxs[box_index].get(num, 0) + 1# print(rows)# print('==i', i)# print('==num', num)if rows[i][num] > 1 or cols[j][num] > 1 or boxs[box_index][num] > 1: return Falsereturn True
c++:
class Solution {
public:bool isValidSudoku(vector<vector<char>>& board) {vector<vector<int>> rows(9, vector<int>(9, 0));vector<vector<int>> cols(9, vector<int>(9, 0));vector<vector<int>> boxs(9, vector<int>(9, 0));for(int i = 0; i < 9; i++){for(int j = 0; j < 9; j++){if (board[i][j] == '.') continue;int num = board[i][j] - '1';int box_index = (i / 3) * 3 + j / 3;rows[i][num]++;cols[j][num]++;boxs[box_index][num]++;if(rows[i][num] > 1 || cols[j][num] > 1 || boxs[box_index][num] > 1){return false;}}}return true;}
};
4.字母异位词分组
python:
class Solution:def groupAnagrams(self, strs: List[str]) -> List[List[str]]:dict_={}for i in range(len(strs)):str_ = ''.join(sorted(strs[i]))if str_ in dict_:dict_[str_].append(strs[i])else:dict_[str_] = [strs[i]]# print(dict_.values())return list(dict_.values())
c++:
class Solution {
public:vector<vector<string>> groupAnagrams(vector<string>& strs) {vector<vector<string>> result;map<string, vector<string>> dict_; for(int i = 0; i < strs.size(); i++){string s = strs[i];sort(s.begin(), s.end());dict_[s].push_back(strs[i]);}map<string, vector<string>> ::iterator it;for(it = dict_.begin(); it != dict_.end(); it++){result.push_back(it->second);}// for(auto x:dict_){ // result.push_back(x.second);// }return result;}
};
5.矩阵置零
python:
class Solution:def setZeroes(self, matrix: List[List[int]]) -> None:"""Do not return anything, modify matrix in-place instead."""m, n = len(matrix), len(matrix[0])row, col = [False] * m, [False] * nfor i in range(m):for j in range(n):if matrix[i][j] == 0:row[i] = col[j] = Truefor i in range(m):for j in range(n):if row[i] or col[j]:matrix[i][j] = 0
c++:
class Solution {
public:void setZeroes(vector<vector<int>>& matrix) {int m = matrix.size();int n = matrix[0].size();vector<int> row(m, 0), col(n, 0);for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (!matrix[i][j]) {row[i] = col[j] = 1;}}}for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (row[i] || col[j]) {matrix[i][j] = 0;}}}}
};
6.最小覆盖子串
思路:滑动窗口
python:
class Solution:def minWindow(self, s: str, t: str) -> str:dict_ = {}for i in t:dict_[i] = dict_.get(i, 0)+1# print('dict_:', dict_)n = len(s)left, right = 0,0remain = 0res = ''minlen = float('inf')while right < n:#向右边拓展if s[right] in dict_:if dict_[s[right]]>0:#大于0这个时候加才有效否则是重复字符remain+=1dict_[s[right]]-=1while remain == len(t):#left 要拓展了 也就是左边要压缩if (right - left) < minlen:minlen = right-leftres = s[left:right+1]# print('==res:', res)left+=1if s[left-1] in dict_:#注意这里left已经加1了 要用前一个字符也就是s[left-1]dict_[s[left - 1]] += 1if dict_[s[left-1]]>0:#大于0这个时候减去才有效否则是重复字符remain -= 1right += 1#放后面进行向右拓展# print('==res:', res)return res
7.单词接龙 II
思路:构建图 然后bfs
python:
class Solution:def findLadders(self, beginWord: str, endWord: str, wordList: List[str]) -> List[List[str]]:cost = {}for word in wordList:cost[word] = float("inf")cost[beginWord] = 0# print('==cost:', cost)# neighbors = collections.defaultdict(list)neighbors = {}ans = []#构建图for word in wordList:for i in range(len(word)):key = word[:i] + "*" + word[i + 1:]if key not in neighbors:neighbors[key] = []neighbors[key].append(word)else:neighbors[key].append(word)# print('==neighbors:', neighbors)q = [[beginWord]]# print('====q:', q)#bfswhile q:path = q.pop(0)# print('===path:', path)cur = path[-1]if cur == endWord:ans.append(path.copy())else:for i in range(len(cur)):new_key = cur[:i] + "*" + cur[i + 1:]if new_key not in neighbors:continuefor neighbor in neighbors[new_key]:# print('==cost[cur] + 1, cost[neighbor]:', cost[cur] + 1, cost[neighbor])if cost[cur] + 1 <= cost[neighbor]:q.append(path + [neighbor])cost[neighbor] = cost[cur] + 1# print('==ans:', ans)# print(cost)return ans
8.最长连续序列
python:
class Solution:def longestConsecutive(self, nums: List[int]) -> int:temp = 1long_length = 0nums = set(nums)for num in nums:if num - 1 in nums:continuewhile num + 1 in nums:temp += 1num += 1long_length = max(long_length, temp)temp = 1return long_length
c++:
class Solution {
public:int longestConsecutive(vector<int>& nums) {unordered_set<int> unums;for(int num:nums){unums.insert(num);}int LongLength = 0, temp = 1;for(int num: unums){if(unums.count(num - 1)){continue;}while(unums.count(num + 1)){temp++;num++; }LongLength = max(LongLength, temp);temp = 1;}return LongLength;}
};
9-1. 单词拆分
思路1:动态规划
#动态规划 dp[i]表示 s 的前 i 位是否可以用 wordDict 中的单词表示,
#
class Solution:def wordBreak(self, s, wordDict):n = len(s)dp = [False] * (n + 1)dp[0] = Truefor i in range(n):for j in range(i+1, n+1):if dp[i] and (s[i:j] in wordDict):dp[j] = Trueprint('==dp:', dp)return dp[-1]
s = "leetcode"
wordDict = ["leet", "code"]
sol = Solution()
res= sol.wordBreak(s, wordDict)
print('==res:', res)
c++实现:
class Solution {
public:bool wordBreak(string s, vector<string>& wordDict) {int n = s.size();unordered_set<string> wordDictSet;for (auto word: wordDict) {wordDictSet.insert(word);} vector<bool> dp(n+1, false);dp[0] = true;for(int i = 0; i < n; i++){for(int j = i+1; j < n+1; j++){ if(dp[i] && wordDictSet.find(s.substr(i, j - i)) != wordDictSet.end()) {// cout<<"s.substr(i, j - i):"<<s.substr(i, j - i)<<endl;dp[j] = true;}}}return dp[n];}
};
思路2:回溯加缓存
#递归 lru_cache用于缓存 将数据缓存下来 加快后续的数据获取 相同参数调用时直接返回上一次的结果
import functools
class Solution:@functools.lru_cache()def helper(self, s):if len(s) == 0:return Trueres = Falsefor i in range(1, len(s)+1):if s[:i] in self.wordDict:res = self.helper(s[i:]) or resreturn resdef wordBreak(self, s, wordDict):self.wordDict = wordDictreturn self.helper(s)
s = "leetcode"
wordDict = ["leet", "code"]
# s = "aaaaaaa"
# wordDict = ["aaaa", "aaa"]
# s= "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab"
# wordDict = ["a","aa","aaa","aaaa","aaaaa","aaaaaa","aaaaaaa","aaaaaaaa","aaaaaaaaa","aaaaaaaaaa"]
sol = Solution()
res= sol.wordBreak(s, wordDict)
print('==res:', res)
9-2.单词拆分 II
思路:递归
class Solution:def helper(self, s, wordDict, memo):if s in memo:#递归终止条件return memo[s]if s=='':#递归终止条件return []res = []for word in wordDict:if not s.startswith(word):continueif len(word)==len(s):#匹配上刚好相等res.append(word)else:#匹配上 但是字符还没到最后rest = self.helper(s[len(word):], wordDict, memo)for tmp in rest:tmp = word+ " "+ tmpres.append(tmp)print('==res:', res)print('==memo:', memo)memo[s] = resreturn resdef wordBreak(self, s, wordDict):if s=='':return []return self.helper(s, wordDict, memo={})
s = "catsanddog"
wordDict = ["and", "cat", "cats", "sand", "dog"]
# s = "cat"
# wordDict = ["cat"]
sol = Solution()
res = sol.wordBreak(s, wordDict)
print(res)
c++:
class Solution {
public:vector<string> helper(string s, vector<string>& wordDict){vector<string> res;for(int i = 0; i < wordDict.size(); i++){string word = wordDict[i];if(s.find(word) != 0){continue;}if(word == s){res.push_back(word);}else{vector<string> temp;temp = helper(s.substr(word.size(), s.size()), wordDict);for(string temp_:temp){res.push_back(word + " "+temp_);}} }return res;}vector<string> wordBreak(string s, vector<string>& wordDict) {if (s.size()==0){return {};}return helper(s, wordDict);}
};
10-1.环形链表
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = Noneclass Solution:def hasCycle(self, head: ListNode) -> bool:#快慢指针 人追人slow,fast = head,headwhile fast and fast.next:fast = fast.next.nextslow = slow.nextif slow==fast:return True return False
c++实现:
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:bool hasCycle(ListNode *head) {ListNode* slow = head;ListNode* fast = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;if(slow == fast){return true;}}return false;}
};
10-2.给定一个有环链表,实现一个算法返回环路的开头节点。
假设有两个指针,分别为快慢指针fast和slow, 快指针每次走两步,慢指针每次前进一步,如果有环则两个指针必定相遇;
反证法:假设快指针真的 越过 了慢指针,且快指针处于位置 i+1,而慢指针处于位置 i,那么在前一步,快指针处于位置 i-1,慢指针也处于位置 i-1,它们相遇了。
A:链表起点
B:环起点
C:相遇点
X:环起点到相遇点距离
Y:链表起点到环起点距离
R:环的长度
S:第一次相遇时走过的路程
1.慢指针slow第一次相遇走过的路程 S1 = Y + X;(11)
快指针fast第一次相遇走过的路程 S2=2S1 = Y + X + NR;(2)
说明:快指针的速度是慢指针的两倍,相同时间内路程应该是慢指针的两倍,Y + X + NR是因为快指针可能经过N圈后两者才相遇;
把(1)式代入(2)式得:Y = NR -X;
2..在将慢指针回到A点,满指针和快指针同时走,在B点相遇,此处就是环节点.
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = Noneclass Solution:def detectCycle(self, head: ListNode) -> ListNode:slow = headfast = head;while fast:if fast and fast.next:slow = slow.nextfast = fast.next.nextelse:return Noneif slow==fast:breakif fast ==None or fast.next==None:return Noneslow= headwhile slow!=fast:slow = slow.nextfast = fast.nextreturn slow
c++实现:
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:ListNode *detectCycle(ListNode *head) {ListNode* slow = head;ListNode* fast = head;while(fast){if(fast && fast->next){slow = slow->next;fast = fast->next->next;}else{return NULL;}if(slow==fast){break;}}if(!fast || !fast->next){return NULL;}slow = head;while(slow!=fast){slow = slow->next;fast = fast->next;}return slow;}
};
11. 重复的DNA序列
python:
class Solution:def findRepeatedDnaSequences(self, s: str) -> List[str]:length = 10res = list()temp = dict()for i in range(len(s) - length + 1):temp[s[i:i+length]] = temp.get(s[i:i+length], 0) + 1if temp[s[i:i+length]] == 2:res.append(s[i:i+length])return res
c++:
class Solution {
public:vector<string> findRepeatedDnaSequences(string s) {if(s.size() < 10){return {};} vector<string> res;map<string, int> temp;int length=10;for(size_t i = 0; i < s.size() - length + 1; i++){string str_ = s.substr(i, length);temp[str_]++;// cout<<str_<<endl;// cout<<temp[str_]<<endl;if(temp[str_] == 2){res.push_back(str_);}}return res;}
};
12.快乐数
python:
class Solution:def nextN(self, n):sum_ = 0while n > 0:digit = n % 10n = n//10sum_ += digit**2return sum_def isHappy(self, n: int) -> bool:visit = set()while n!=1 and n not in visit:visit.add(n)n = self.nextN(n)return n==1
c++
class Solution {
public:int nextN(int n){int sum_ = 0;while(n > 0){sum_ += (n % 10) * (n % 10);n /= 10; }return sum_;}bool isHappy(int n) {unordered_set<int> visit;while(n != 1 && visit.find(n) == visit.end()){visit.insert(n);n = nextN(n);}// cout<<n;return n == 1;}
};
13.同构字符串
python:
class Solution:def isIsomorphic(self, s: str, t: str) -> bool:if len(s) != len(t):return Falsedict_ = dict()for i in range(len(s)):if s[i] in dict_:if dict_[s[i]] != t[i]:return Falseelse:if t[i] in dict_.values():return Falsedict_[s[i]] = t[i]return True
class Solution:def isIsomorphic(self, s: str, t: str) -> bool:if len(s) != len(t):return Falsedict_1 = dict()dict_2 = dict()for i in range(len(s)):if (s[i] in dict_1 and dict_1[s[i]] != t[i]) or (t[i] in dict_2 and dict_2[t[i]] != s[i]): return Falsedict_1[s[i]] = t[i]dict_2[t[i]] = s[i]return True
c++:
class Solution {
public:bool isIsomorphic(string s, string t) {map<char, char> s2t;map<char, char> t2s;for (int i = 0; i < s.size(); ++i) {char x = s[i], y = t[i];if ((s2t.count(x) && s2t[x] != y) || (t2s.count(y) && t2s[y] != x)) {return false;}s2t[x] = y;t2s[y] = x;}return true;}
};
14.求众数 II
python:
class Solution:def majorityElement(self, nums: List[int]) -> List[int]:length = len(nums) // 3 + 1dict_ = {}for num in nums:dict_[num] = dict_.get(num, 0) + 1res = []for key in dict_:if dict_[key] >= length:res.append(key)return res
c++:
class Solution {
public:vector<int> majorityElement(vector<int>& nums) {map<int, int> dict_;vector<int> res;int length = nums.size()/3 + 1;for(int &num:nums){dict_[num]++;}for(auto &iter:dict_){if(iter.second >= length){res.push_back(iter.first);}}return res;}
};
15.丑数 II
python:
class Solution:def nthUglyNumber(self, n: int) -> int:dp = [1]*nindex_two = 0index_three = 0index_five = 0for i in range(1, n):two = dp[index_two]*2three = dp[index_three]*3five = dp[index_five]*5dp[i] = min(two, three, five)if dp[i] == two:index_two += 1if dp[i] == three:index_three += 1if dp[i] == five:index_five += 1# print(dp)return dp[-1]
c++:
class Solution {
public:int nthUglyNumber(int n) {vector<int>dp(n, 1);int index_two = 0, index_three = 0, index_five = 0;for(int i = 1; i < n; i++){int two = dp[index_two]*2;int three = dp[index_three]*3;int five = dp[index_five]*5;dp[i] = min(min(three, two), five);if(two == dp[i]){index_two++;}if(three == dp[i]){index_three++;}if(five == dp[i]){index_five++;}}return dp[n-1];}
};