leetcode–字符串
3.无重复字符的最长子串
字母异位词分组:给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
思路:使用集合去重的目的,使用滑窗取得最长字串
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
Python
def lengthOfLongestSubstring(s: str) -> int:
if not s:
return 0
st = set() # 利用集合去重
cur_len = 0
max_len = 0
left = 0
for i in range(len(s)):
cur_len += 1
while s[i] in st:
st.remove(s[left]) # 不断弹出最左边元素直到满足条件
left += 1
cur_len -= 1
if cur_len > max_len:
max_len = cur_len
st.add(s[i])
return max_len
C++
int lengthOfLongestSubstring(string s) {
if (s.length() == 0) {
return 0;
}
unordered_set<char> st;
int curLen = 0, maxLen = 0;
int left = 0;
for (int i = 0; i < s.length(); i++)
{
curLen++; // curLen也可以用i-l+1替换
while (st.find(s[i]) != st.end()) {
st.erase(s[left]);
left++;
curLen--;
}
maxLen = max(maxLen, curLen);
st.insert(s[i]);
}
return maxLen;
}
拓展:输出最长子串
def lengthOfLongestSubstring(s: str) -> str:
if not s:
return 0
st = set() # 利用集合去重
cur_len = 0
max_len = 0
left = 0
res = [0, 0]
for i in range(len(s)):
cur_len += 1
while s[i] in st:
st.remove(s[left]) # 不断弹出最左边元素直到满足条件
left += 1
cur_len -= 1
if cur_len > max_len:
max_len = cur_len
res = [left, i] # 获取最长字串的索引
st.add(s[i])
return s[res[0]: res[1] + 1]
30.串联所有单词的子串
给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。
s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。
例如,如果 words = [“ab”,“cd”,“ef”], 那么 “abcdef”, “abefcd”,“cdabef”, “cdefab”,“efabcd”, 和 “efcdab” 都是串联子串。 “acdbef” 不是串联子串,因为他不是任何 words 排列的连接。
返回所有串联字串在 s 中的开始索引。你可以以 任意顺序 返回答案。
输入:s = “barfoothefoobarman”, words = [“foo”,“bar”]
输出:[0,9]
解释:因为 words.length = 2 同时 words[i].length = 3,连接的子字符串的长度必须为 6。
子串 “barfoo” 开始位置是 0。它是 words 中以 [“bar”,“foo”] 顺序排列的连接。
子串 “foobar” 开始位置是 9。它是 words 中以 [“foo”,“bar”] 顺序排列的连接。
输出顺序无关紧要。返回 [9,0] 也是可以的。
思路:使用滑窗取出对应长度字符串,切割成word串再与所给串比较【排序容易超时,可改用哈希表】
Python
def findSubstring(s: str, words: List[str]) -> List[int]:
res = []
r = len(words)
c = len(words[0])
sw = sorted(words)
for i in range(0, len(s) - c * r + 1):
cur_word = [s[x: x + c] for x in range(i, c * r + i, c)] # 切割成word串
if sorted(cur_word) == sw:
res.append(i)
return res
C++
vector<int> findSubstring(string s, vector<string>& words) {
vector<int> res;
int r = words.size(), c = words[0].size();
sort(words.begin(), words.end());
for (int i = 0; i < s.size() - r * c + 1; i++)
{
vector<string> curWord;
for (int j = 0; j < c * r + i; j += c)
{
curWord.push_back(s.substr(j, c));
}
sort(curWord.begin(), curWord.end());
if (curWord == words) {
res.push_back(i);
}
}
return res;
}
43. 字符串相乘
给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
输入: num1 = “123”, num2 = “456”
输出: “56088”
思路:模仿乘法相乘,对单个字符转换成数字相乘,个位取余,十位取整,再最后转换成字符串
Python
def multiply(num1: str, num2: str) -> str:
if num1 == '0' or num2 == '0':
return '0'
l1 = [int(x) for x in num1]
l2 = [int(x) for x in num2]
res = [0] * (len(num1) + len(num2))
for i in range(len(num1) - 1, -1, -1):
for j in range(len(num2) - 1, -1, -1):
tmp = l1[i] * l2[j]
idx = i + j + 1 # 个位
idy = i + j # 十位
tmp += res[idx] # 先累加
res[idx] = tmp % 10 # 个位取余
res[idy] += tmp // 10 # 十位取整,累加到十位上
if res[0] == 0:
res = res[1:]
return ''.join(str(x) for x in res)
C++
string multiply(string num1, string num2) {
int l1 = num1.size(), l2 = num2.size();
if (l1 == 0 || l2 == 0) {
return "0";
}
if (num1 == "0" || num2 == "0") {
return "0";
}
vector<int> res(l1 + l2, 0);
for (int i = l1-1; i > -1; i--)
{
for (int j = l2 - 1; j > -1; j--) {
int tmp = (num1[i] - '0') * int(num2[j] - '0'); // char和int转换
int idx = i + j + 1;
int idy = i + j;
tmp += res[idx];
res[idx] = tmp % 10;
res[idy] += tmp / 10;
}
}
if (res[0] == 0) {
res.erase(res.begin());
}
string ans;
for (int i = 0; i < res.size(); i++)
{
ans += res[i] + '0';
}
return ans;
}
49.字母异位词分组
字母异位词分组:给定一个字符串数组,将字母异位词组合在一起。可以按任意顺序返回结果列表。
输入: strs = [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”]
输出: [[“bat”],[“nat”,“tan”],[“ate”,“eat”,“tea”]]
思路:使用排序达到集合去重的目的,再使用defaultdict(list)字典进行分组,最后取values值返回
Python
from typing import List
from collections import defaultdict
def groupAnagrams(strs: List[str]) -> List[List[str]]:
res = defaultdict(list)
for s in strs:
cur = ''.join(sorted(s)) # 注意sorted方法返回的是list
res[cur].append(s)
return list(res.values())
# print(groupAnagrams1(strs = ["eat", "tea", "tan", "ate", "nat", "bat"]))
# [['eat', 'tea', 'ate'], ['tan', 'nat'], ['bat']]
C++
vector<vector<string>> groupAnagrams(vector<string>& strs) {
unordered_map<string, vector<string>> res;
vector<vector<string>> ans;
for (auto& x : strs) {
string cur = x;
sort(cur.begin(), cur.end());
res[cur].push_back(x);
}
for (auto& value : res) {
ans.push_back(value.second);
}
return ans;
}
165.比较版本号
给你两个版本号 version1 和 version2 ,请你比较它们。
版本号由一个或多个修订号组成,各修订号由一个 ‘.’ 连接。每个修订号由 多位数字 组成,可能包含 前导零 。每个版本号至少包含一个字符。修订号从左到右编号,下标从 0 开始,最左边的修订号下标为 0 ,下一个修订号下标为 1 ,以此类推。例如,2.5.33 和 0.1 都是有效的版本号。
比较版本号时,请按从左到右的顺序依次比较它们的修订号。比较修订号时,只需比较 忽略任何前导零后的整数值 。也就是说,修订号 1 和修订号 001 相等 。如果版本号没有指定某个下标处的修订号,则该修订号视为 0 。例如,版本 1.0 小于版本 1.1 ,因为它们下标为 0 的修订号相同,而下标为 1 的修订号分别为 0 和 1 ,0 < 1 。
返回规则如下:
如果 version1 > version2 返回 1,
如果 version1 < version2 返回 -1,
除此之外返回 0。
输入:version1 = “1.01”, version2 = “1.001”
输出:0
解释:忽略前导零,“01” 和 “001” 都表示相同的整数 “1”
思路:取最大长度,不足补0
Python
def compareVersion(version1: str, version2: str) -> int:
nums1 = version1.split('.')
nums2 = version2.split('.')
n1, n2 = len(nums1), len(nums2)
for i in range(max(n1, n2)): # 取最大长度
i1 = int(nums1[i]) if i < n1 else 0 # 补0
i2 = int(nums2[i]) if i < n2 else 0
if i1 != i2:
return 1 if i1 > i2 else -1
return 0
C++
int compareVersion(string version1, string version2) {
stringstream ss; //借助流实现split功能
vector<string> v1, v2;
string s;
ss << version1;
while (getline(ss, s, '.')) {
v1.push_back(s);
}
ss.clear();
ss << version2;
while (getline(ss, s, '.')) {
v2.push_back(s);
}
for (int i = 0; i < max(v1.size(), v2.size()); i++)
{
int i1 = i < v1.size() ? stoi(v1[i]) : 0; //string和int转换 stoi | to_string 也可借助流
int i2 = i < v2.size() ? stoi(v2[i]) : 0;
if (i1 != i2) {
return i1 > i2 ? 1 : -1;
}
}
return 0;
}
166.分数到小数
分数到小数:除法,循环部分用括号圈起来。
输入:numerator = 4, denominator = 333
输出:“0.(012)”
思路:使用divmod得到商和余数,用字典记住左括号的位置
Python
def fractionToDecimal(numerator: int, denominator: int) -> str:
if numerator == 0:
return '0'
res = []
used = {}
if numerator ^ denominator < 0: # 异或小于0,为不同符号
res.append('-')
numerator, denominator = abs(numerator), abs(denominator)
m, n = divmod(numerator, denominator)
res.append(str(m))
if n == 0:
return ''.join(res)
res.append('.')
used[n] = len(res) # 记住余数的位置
while n:
m, n = divmod(n * 10, denominator)
res.append(str(m))
if n in used: # 余数与之前某个值相同
res.insert(used[n], '(')
res.append(')')
break
used[n] = len(res)
return ''.join(res)
# print(fractionToDecimal(numerator = 1, denominator = 333))
# 0.(003)
C++
string fractionToDecimal(int numerator, int denominator) {
string res;
unordered_map<int, int> dict;
if(numerator == 0){
return "0";
}
if((numerator > 0) ^ (denominator > 0)){
res = "-";
}
numerator = abs(numerator);
denominator = abs(denominator);
long m = numerator / denominator;
long n = numerator % denominator;
res += to_string(m);
if(n == 0){
return res;
}
res += ".";
dict[n] = res.size();
while(n){
n *= 10;
m = n / denominator;
n = n % denominator;
res += to_string(m);
if(dict.find(n) != dict.end()){
res.insert(dict[n], "(");
res += ")";
break;
}
dict[n] = res.size();
}
return res;
}