这个系列就记录我做的算法题
欧耶
1、拼写单词
拼写单词原题链接
给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars。
假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字符串),那么我们就认为你掌握了这个单词。
注意:每次拼写时,chars 中的每个字母都只能用一次。
返回词汇表 words 中你掌握的所有单词的 长度之和。
示例 1:
输入:words = [“cat”,“bt”,“hat”,“tree”], chars = “atach”
输出:6
解释:
可以形成字符串 “cat” 和 “hat”,所以答案是 3 + 3 = 6。
示例 2:
输入:words = [“hello”,“world”,“leetcode”], chars = “welldonehoneyr”
输出:10
解释:
可以形成字符串 “hello” 和 “world”,所以答案是 5 + 5 = 10。
提示:
1 <= words.length <= 1000
1 <= words[i].length, chars.length <= 100
所有字符串中都仅包含小写英文字母
来源:力扣(LeetCode)
这道题的意思就是在给定的字符串数组中,找在给定的字符数组中存在的字符串
public int countCharacters(String[] words, String chars) {
int count = 0;
int sum = 0;
final String preChar = chars;
//将字符串数组遍历
for (int i = 0; i < words.length; i++) {
//将字符串遍历字符
for (int j = 0; j < words[i].length(); j++) {
//如果给定的字母表包含第i个字符串的第j个字符
if (chars.contains(String.valueOf(words[i].charAt(j)))) {
//重新组织字母表,因为题目中说明字母表的每一个字母只能用一次
chars = chars.substring(0, chars.indexOf(String.valueOf(words[i].charAt(j)))) + chars.substring(chars.indexOf(String.valueOf(words[i].charAt(j))) + 1);
//每次变化字母表,计数count加一
count++;
} else {
//如果不包含,就跳出循环
break;
}
//如果count等于字符串的第i个的长度(字符串变成字符数组的长度)
if (count == words[i].length()) {
//总和加上count,用来最后输出
sum += count;
break;
}
}
//重置count,进行下一个字符串的操作
count = 0;
//字母表已经更新,去掉了使用过的字符
chars = preChar;
}
return sum;
}
这真的是我做的第一个算法题,虽然难度定义的是简单,可是对于一个基础薄弱的我来说,还是比较困难的
2、连续数组
连续数组原题链接
给定一个二进制数组, 找到含有相同数量的 0 和 1 的最长连续子数组(的长度)。
示例 1:
输入: [0,1]
输出: 2
说明: [0, 1] 是具有相同数量0和1的最长连续子数组。
示例 2:
输入: [0,1,0]
输出: 2
说明: [0, 1] (或 [1, 0]) 是具有相同数量0和1的最长连续子数组。
注意: 给定的二进制数组的长度不会超过50000。
来源:力扣(LeetCode)
这道题的意思是在一个只有0和1的数组中,找出一个最大的0与1数量相当且连续的子数组的长度
public int findMaxLength(int[] nums) {
int max = 0;//初始化最大的长度
int len = nums.length;
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
map.put(0, -1);//用来标识0和1
//存放当前的最大值
int sum = 0;
//遍历数组nums
for (int x = 0; x < len; x++) {
//若当前的数是1
if (nums[x] == 1) {
//sum+1
sum++;
} else {
//当前数是0就-1
sum--;
}
//如果map的以sum为key的节点没有存放value
if (map.get(sum) == null) {
//添加value
map.put(sum, x);
} else {
//否则当前所有的遍历的最大值是,之前最大值与当下遍历的下标与map中以sum为key的value的差值
max = Math.max(max, x - map.get(sum));
}
}
return max;
}
第一次接触HashMap,从这以后的几天中,一直很疑惑,HashMap有啥用啊,可以存放数据,那链表和数组不都可以吗,今天去看了HashMap源码的详解,感叹,人类真聪明,可以将数组与链表的优点结合起来,甚至可以加上树的思想,真的让人赞叹
3、 字母异位词分组
字母异位词分组原题链接
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
示例:
输入: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”],
输出:
[
[“ate”,“eat”,“tea”],
[“nat”,“tan”],
[“bat”]
]
说明:
所有输入均为小写字母。
不考虑答案输出的顺序。
来源:力扣(LeetCode)
本题的意思是将多个单词中使用相同字母的放在一个链表里,最后多个链表组成一个大的链表
public List<List<String>> groupAnagrams(String[] strs) {
//这里的map泛型用了,String做key,ArrayList<String>做value,便于最后返回
HashMap<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();
//遍历给的字符串数组
for (String string : strs) {
//将字符串变成char的数组
char[] chars = string.toCharArray();
//将它排序,目的为了筛选出相同字母组成的单词
Arrays.sort(chars);
//创建一个由字符数组组成的字符串的key
String key = new String(chars);
//如果map中不存在这个key
if (!map.containsKey(key))
//就put,并创建一个新的链表
map.put(key, new ArrayList<String>());
//map获取当前key的value也就是一个链表,在调用add将当前遍历的字符串放入链表
map.get(key).add(string);
}
//返回值直接创建了一个链表,内容是map的value的集合,这里没有加泛型,其实加不加都可以
return new ArrayList(map.values());
}
这次使用了HashMap,感觉它的用处十分强大,高效率遍历,不受限制的key,value(定义的时候可以随便改),自带的高效率方法,为他打call
开始逐渐感觉到算法的魅力了,以后尽量每天吃透一道新题
一定要保护自己的梦想,即使牺牲一切。
——NANA