每日一题——拼写单词【3.17】

每日一题——拼写单词【3.17】

题目

  leetcode题目:(链接https://leetcode-cn.com/problems/find-words-that-can-be-formed-by-characters/)。
  给你一份『词汇表』(字符串数组)words和一张『字母表』(字符串)chars
假如你可以用 chars 中的『字母』(字符)拼写出words中的某个『单词』(字符串),那么我们就认为你掌握了这个单词。
注意:每次拼写时,chars中的每个字母都只能用一次。
返回词汇表words中你掌握的所有单词的长度之和

示例 1:

输入:words = ["cat","bt","hat","tree"], chars = "atach"
输出:6
解释: 
可以形成字符串 "cat" 和 "hat",所以答案是 3 + 3 = 6。

示例 1:

输入:words = ["hello","world","leetcode"], chars = "welldonehoneyr"
输出:10
解释:
可以形成字符串 "hello" 和 "world",所以答案是 5 + 5 = 10。

基本思路

  我一开始想到的是遍历words里每个字符串,对于每一个words[i]里的字母,在chars里找对应字母并删除同时记数,在遍历完每一个words[i]后比较计数器和words[i]的大小关系,若想等则在最终结果上加上计数器的值。这个方法可行,但是涉及字符串的改变,运算时间太长了。
  涉及要记录多个值各自的数量的时候,我们可以考虑用哈希表,键值对可以很方便地记录信息。本题中我们可以用一个哈希表Map1记录每个words[i]里的每个字母的数量,用另一个哈希表Map2记录chars里每个字母的数量,然后进行比较,只要Map1里每个key所对应的value都小于等于Map2中同样的key所对应的value的值,就认为可以拼出来这个单词。
  使用真正的哈希表时,存储涉及了哈希运算,也在消耗时间。对于这种可以确定数量的题目,我们可以用数组来完成哈希表的功能。我们可以使用一个长度为26的数组 w 来表示 words[i] 中每个字母的数量,使用长度为26的数组 c 来表示 chars 中每个字母的数量,比较 wc 相同位置的大小即可。
后续优化:进行值的比较耗费时间过长,我们可以考虑去掉上述的数组 w,遍历 words[i] 中每个字母时,将 c 中对应字母数量减一,若出现负数则判定为不可。

具体代码

最初想法——字符串裁剪:

//Java
class Solution {
	public int countCharacters(String[] words, String chars) {
		StringBuilder sb;
		int ans = 0;
		for(int i = 0; i < words.length; i++) {
			sb = new StringBuilder(chars);
			int count = 0;
			for(int j = 0; j < words[i].length(); j++) {
				int index = sb.indexOf(String.valueOf(words[i].charAt(j)));
				if(index > -1) {
					sb.deleteCharAt(index);
					count++;
				}
			}
			if(count == words[i].length()) {
				ans = ans + count;
			}
		}
		return ans;
    }
}

时间复杂度:遍历了words[]中的所有字母,所以时间复杂度为 O ( n ) O(n) O(n),n表示words[]中所有字母数量总和。
空间复杂度:额外需要m个空间存放StringBuilder,空间复杂度为 O ( m ) O(m) O(m),m表示words[]中字符串的数量。

哈希数组——优化后:

//Java
class Solution {
	public int countCharacters(String[] words, String chars) {
		int[] c = new int[26];
		Arrays.fill(c, 0);
		int ans = 0;
		
		for(int i = 0; i < chars.length(); i++) {
			c[chars.charAt(i) - 97]++;
		}
		for(int i = 0; i < words.length; i++) {
			if(needAdd(words[i], c)) {
				ans = ans + words[i].length();
			}
		}
		return ans;
    }
	
	private boolean needAdd(String w, int[] c) {
		int[] temp = new int[c.length];
		System.arraycopy(c, 0, temp, 0, c.length);
		for(int i = 0; i < w.length(); i++) {
			if(--temp[w.charAt(i) - 97] < 0) {
				return false;
			}
		}
		return true;
	}
}

时间复杂度:遍历了words[]中的所有字母,所以时间复杂度为 O ( n ) O(n) O(n),n表示words[]中所有字母数量总和。
空间复杂度:对于这种调用方法后进行变量声明的模块,空间复杂度如何计算,博主没有查到相关的例子,希望有经验的小伙伴可以给与帮助。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值