算法leetcode|30. 串联所有单词的子串(rust重拳出击)

这篇具有很好参考价值的文章主要介绍了算法leetcode|30. 串联所有单词的子串(rust重拳出击)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。



30. 串联所有单词的子串:

给定一个字符串 s 和一个字符串数组 wordswords 中所有字符串 长度相同

s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。

  • 例如,如果 words = ["ab","cd","ef"], 那么 "abcdef""abefcd""cdabef""cdefab""efabcd", 和 "efcdab" 都是串联子串。 "acdbef" 不是串联子串,因为他不是任何 words 排列的连接。

返回所有串联字串在 s 中的开始索引。你可以以 任意顺序 返回答案。

样例 1:

输入:

	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] 也是可以的。

样例 2:

输入:

	s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]
	
输出:

	[]
	
解释:

	因为 words.length == 4 并且 words[i].length == 4,所以串联子串的长度必须为 16。
	s 中没有子串长度为 16 并且等于 words 的任何顺序排列的连接。
	所以我们返回一个空数组。

样例 3:

输入:

	s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]

输出:

	[6,9,12]
	
解释:

	因为 words.length == 3 并且 words[i].length == 3,所以串联子串的长度必须为 9。
	子串 "foobarthe" 开始位置是 6。它是 words 中以 ["foo","bar","the"] 顺序排列的连接。
	子串 "barthefoo" 开始位置是 9。它是 words 中以 ["bar","the","foo"] 顺序排列的连接。
	子串 "thefoobar" 开始位置是 12。它是 words 中以 ["the","foo","bar"] 顺序排列的连接。

提示:

  • 1 <= s.length <= 104
  • 1 <= words.length <= 5000
  • 1 <= words[i].length <= 30
  • words[i] 和 s 由小写英文字母组成

分析:

  • 面对这道算法题目,二当家的陷入了沉思。
  • 由于题干里罗列了所有单词可能的串联出的子串,所以可能理所当然的考虑罗列所有子串,然后再去字符串中查看是否存在,但是这样太慢了,肯定是不对的。
  • 由于题干中说所有字符串 长度相同,考虑用单词计数,滑动窗口解决。
  • 需要注意的一些点是,首先窗口滑动的大小应该是单词的长度才对,另外,由于窗口的大小是单词的长度,那么起始下标就需要考虑偏移。
  • 根据单词长度和单词数,可以知道串联所有单词的子串长度,所以如果从窗口的起始位置到末尾不够子串长度的话,也就不需要再尝试下去。
  • 单词都串联起来,顺序不重要,所以单词计数是关键。

题解:

rust

impl Solution {
    pub fn find_substring(s: String, words: Vec<String>) -> Vec<i32> {
        let mut ans = Vec::new();
        let (m, n, ls) = (words.len(), words[0].len(), s.len());
        for i in 0..n {
            if i + m * n > ls {
                break;
            }
            let mut differ = std::collections::HashMap::new();
            for j in 0..m {
                let word = &s[i + j * n..i + (j + 1) * n];
                *differ.entry(word).or_insert(0) += 1;
            }
            for word in words.iter() {
                let count = differ.entry(word).or_insert(0);
                if *count == 1 {
                    differ.remove(word as &str);
                } else {
                    *count -= 1;
                }
            }
            for start in (i..ls - m * n + 1).step_by(n) {
                if start != i {
                    let mut word = &s[start + (m - 1) * n..start + m * n];
                    let mut count = differ.entry(word).or_insert(0);
                    if *count == -1 {
                        differ.remove(word);
                    } else {
                        *count += 1;
                    }
                    word = &s[start - n..start];
                    count = differ.entry(word).or_insert(0);
                    if *count == 1 {
                        differ.remove(word);
                    } else {
                        *count -= 1;
                    }
                }
                if differ.is_empty() {
                    ans.push(start as i32);
                }
            }
        }
        return ans;
    }
}

go

func findSubstring(s string, words []string) (ans []int) {
    m, n, ls := len(words), len(words[0]), len(s)
	for i := 0; i < n && i+m*n <= ls; i++ {
		differ := map[string]int{}
		for j := 0; j < m; j++ {
			differ[s[i+j*n:i+(j+1)*n]]++
		}
		for _, word := range words {
			if differ[word] == 1 {
				delete(differ, word)
			} else {
				differ[word]--
			}
		}
		for start := i; start < ls-m*n+1; start += n {
			if start != i {
				word := s[start+(m-1)*n : start+m*n]
				if differ[word] == -1 {
					delete(differ, word)
				} else {
					differ[word]++
				}
				word = s[start-n : start]
				if differ[word] == 1 {
					delete(differ, word)
				} else {
					differ[word]--
				}
			}
			if len(differ) == 0 {
				ans = append(ans, start)
			}
		}
	}
	return
}

c++

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int> ans;
        int m = words.size(), n = words[0].size(), ls = s.size();
        for (int i = 0; i < n && i + m * n <= ls; ++i) {
            unordered_map<string, int> differ;
            for (int j = 0; j < m; ++j) {
                ++differ[s.substr(i + j * n, n)];
            }
            for (string &word: words) {
                if (--differ[word] == 0) {
                    differ.erase(word);
                }
            }
            for (int start = i; start < ls - m * n + 1; start += n) {
                if (start != i) {
                    string word = s.substr(start + (m - 1) * n, n);
                    if (++differ[word] == 0) {
                        differ.erase(word);
                    }
                    word = s.substr(start - n, n);
                    if (--differ[word] == 0) {
                        differ.erase(word);
                    }
                }
                if (differ.empty()) {
                    ans.emplace_back(start);
                }
            }
        }
        return ans;
    }
};

python

class Solution:
    def findSubstring(self, s: str, words: List[str]) -> List[int]:
        ans = []
        m, n, ls = len(words), len(words[0]), len(s)
        for i in range(n):
            if i + m * n > ls:
                break
            differ = Counter()
            for j in range(m):
                word = s[i + j * n: i + (j + 1) * n]
                differ[word] += 1
            for word in words:
                if differ[word] == 1:
                    del differ[word]
                else:
                    differ[word] -= 1
            for start in range(i, ls - m * n + 1, n):
                if start != i:
                    word = s[start + (m - 1) * n: start + m * n]
                    if differ[word] == -1:
                        del differ[word]
                    else:
                        differ[word] += 1
                    word = s[start - n: start]
                    if differ[word] == 1:
                        del differ[word]
                    else:
                        differ[word] -= 1
                if len(differ) == 0:
                    ans.append(start)
        return ans


java

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        List<Integer> ans = new ArrayList<Integer>();
        int           m   = words.length, n = words[0].length(), ls = s.length();
        for (int i = 0; i < n && i + m * n <= ls; ++i) {
            Map<String, Integer> differ = new HashMap<String, Integer>();
            for (int j = 0; j < m; ++j) {
                String word = s.substring(i + j * n, i + (j + 1) * n);
                differ.put(word, differ.getOrDefault(word, 0) + 1);
            }
            for (String word : words) {
                differ.put(word, differ.getOrDefault(word, 0) - 1);
                if (differ.get(word) == 0) {
                    differ.remove(word);
                }
            }
            for (int start = i; start < ls - m * n + 1; start += n) {
                if (start != i) {
                    String word = s.substring(start + (m - 1) * n, start + m * n);
                    differ.put(word, differ.getOrDefault(word, 0) + 1);
                    if (differ.get(word) == 0) {
                        differ.remove(word);
                    }
                    word = s.substring(start - n, start);
                    differ.put(word, differ.getOrDefault(word, 0) - 1);
                    if (differ.get(word) == 0) {
                        differ.remove(word);
                    }
                }
                if (differ.isEmpty()) {
                    ans.add(start);
                }
            }
        }
        return ans;
    }
}

非常感谢你阅读本文~
欢迎【点赞】【收藏】【评论】~
放弃不难,但坚持一定很酷~
希望我们大家都能每天进步一点点~
本文由 二当家的白帽子:https://le-yi.blog.csdn.net/ 博客原创~文章来源地址https://www.toymoban.com/news/detail-400652.html


到了这里,关于算法leetcode|30. 串联所有单词的子串(rust重拳出击)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 30. 串联所有单词的子串【memset(hash, 0, sizeof(hash)) 这样的方式真的不要再使用、leetcode有时真的会g的】

    30. 串联所有单词的子串 C代码:滑动窗口、字符串异位段 C代码:失败案例:哈希表保存重复出现

    2024年02月02日
    浏览(41)
  • 【算法】串联所有单词的子串【滑动窗口】

    滑动窗口

    2024年01月19日
    浏览(43)
  • 【Java刷题篇】串联所有单词的子串

    力扣链接: 串联所有单词的子串 阅读题目后,可以拿到一个关键信息– words中所有字符串长度相等 ,这后续解题思路的一大关键,还有就是串联字串的字符串顺序可以不同。得到这两个关键信息后,我们就很容易联想到运用 滑动窗口 这个算法来解决问题。 好分析完题目后,

    2024年03月22日
    浏览(43)
  • 【算法|动态规划No30】leetcode5. 最长回文子串

    个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 🍔本专栏旨在提高自己算法能力的同时,记录一下自己的学习过程,希望对大家有所帮助 🍓希望我们一起努力、成长,共同进步。

    2024年02月08日
    浏览(40)
  • 算法leetcode|79. 单词搜索(rust重拳出击)

    给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

    2024年02月09日
    浏览(59)
  • 算法leetcode|58. 最后一个单词的长度(rust重拳出击)

    给你一个字符串 s ,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。 单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。 1 = s.length = 10 4 s 仅有英文字母和空格 ’ ’ 组成 s 中至少存在一个单词 面对这道算法题目,二当家的

    2024年02月13日
    浏览(52)
  • 【LeetCode热题100】【子串】和为 K 的子数组

    题目 给你一个整数数组  nums  和一个整数  k  ,请你统计并返回  该数组中和为  k   的子数组的个数  。 子数组是数组中元素的连续非空序列。 示例 1: 示例 2: 提示: 1 = nums.length = 2 * 104 -1000 = nums[i] = 1000 -107 = k = 107 暴力  直接两层循环找出所有连续子数组的和,这个

    2024年01月19日
    浏览(44)
  • 30天拿下Rust之所有权

    概述         在编程语言的世界中,Rust凭借其独特的所有权机制脱颖而出,为开发者提供了一种新颖而强大的工具来防止内存错误。这一特性不仅确保了代码的安全性,还极大地提升了程序的性能。在Rust中,所有权是一种编译时检查机制,用于追踪哪些内存或资源何时可

    2024年03月08日
    浏览(39)
  • LeetCode 1358. 包含所有三种字符的子字符串数目

    滑动窗口的经典题型,直接套模板就行了。

    2024年03月14日
    浏览(59)
  • c 取字符串中的子串

    strcpy(S.ch,ch1) 赋值函数; 字符串没特殊处理,就是从0开始的 %s输出字符串,%c输出字符

    2024年02月07日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包