leetcode–字符串

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;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柴寺仓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值