454. 四数相加 II
这题我上来就暴力解,结果就超时了,qwq
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
int n = nums1.length, a = 0, b = 0, count = 0;
int[] nums12 = new int[n*n];
int[] nums34 = new int[n*n];
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
nums12[a++] = nums1[i] + nums2[j];
}
}
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
nums34[b++] = nums3[i] + nums4[j];
}
}
for(int i = 0; i < n*n; i++){
for(int j = 0; j < n*n; j++){
if(nums12[i] + nums34[j] == 0){
count++;
}
}
}
return count;
}
}
经过一番深思熟虑(参考官解,读书人的事。。dddd),选择用hashmap存nums1+nums2的数据,如果得到相同的数据,给对应value值+1就行了。
用到了getOrDefault方法,
getOrDefault(Object key, V defaultValue)
方法返回指定的键映射的值,或defaultValue
如果这个Map不包含的键映射。
把defaultValue
设置成0,在得到值后+1,就可以实现键存在时值+1,不存在时创建键值对了。
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
HashMap h = new HashMap<>();
//把nums1+nums2数据存到map中,遇到相同的数据该数据对应value值+1
for(int i : nums1){
for(int j : nums2){
h.put(i+j, h.getOrDefault(i+j, 0)+1);
}
}
int count = 0;
//在nums3+nums4中找能跟map中的值相加为0的,这里表现为相反数
for(int i : nums3){
for(int j : nums4){
if(h.containsKey(-i-j)){
count += h.get(-i-j);
}
}
}
return count;
}
}
383. 赎金信
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
HashMap h = new HashMap<>();
//把俩字符串都变成小字符串,只含一个字符的那种
//不知道为啥要变成小字符串,变成char不香吗
//变char的见本题第三个代码
String[] r = ransomNote.split("");
String[] m = magazine.split("");
//对于m里的每个小字符串添加到map里,不存在值就是1,存在就+1
for(String i : m){
h.put(i, h.getOrDefault(i, 0)+1);
}
//遍历r,去map里找,没有直接false,有就值-1直到0就remove
for(String i : r){
if(!h.containsKey(i)){
return false;
}else{
int value = h.get(i)-1;
h.put(i, value);
if(value == 0){
h.remove(i);
}
}
}
return true;
}
}
执行用时:38 ms, 在所有 Java 提交中击败了5.01%的用户。喵的,只能说很卑微了,这个执行用时5555,不就遍历了一遍嘛!偷看下官解
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
if (ransomNote.length() > magazine.length()) {
return false;
}
//两个字符串变成字符数组
char[] r = ransomNote.toCharArray();
char[] m = magazine.toCharArray();
//把m里字符都按照字母表顺序存在新建数组里,a对应就是0…
int[] alp = new int[26];
for (char c : m) {
alp[c - 'a']++;
}
//遍历r,去新数组里找有没有这个字符,没有就false,有就-1
for (char c : r) {
alp[c - 'a']--;
if(alp[c - 'a'] < 0) {
return false;
}
}
return true;
}
}
经过这个题发现自己很擅长把简单问题复杂化,真的谢。
官解就是写了个数组存个数,毕竟就26个字母,也存的过来,我咋没想到呢,就很容易被一些条条框框约束到,比如说今天做的哈希题目,自从第一题被哈希教育了之后,就非要哈希不可了。。以后还是要,发!散!思!维!可以多看看别人怎么想的,就算自己没时间重新写一遍了,但是至少要学习一些思路~
看了题解之后很不服气的我把String改成了Charater。
于是:执行用时:12 ms, 在所有 Java 提交中击败了21.05%的用户。
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
HashMap h = new HashMap<>();
char[] r = ransomNote.toCharArray();
char[] m = magazine.toCharArray();
for(char i : m){
Character c = new Character(i);
h.put(c, h.getOrDefault(c, 0)+1);
}
for(char i : r){
Character c = new Character(i);
if(!h.containsKey(c)){
return false;
}else{
int value = h.get(c)-1;
h.put(c, value);
if(value == 0){
h.remove(c);
}
}
}
return true;
}
}
happy happy happy,比原来进步了,看来String比起char来就是又占内存又费时间
15. 三数之和
真醉了,又是只会暴力解,干脆没写代码,反正肯定超时5555
直接上题解:三数之和 - 三数之和 - 力扣(LeetCode)
真没想到第三个循环可以反着遍历,欸。
对着官解注释哭着写:
class Solution {
public List> threeSum(int[] nums) {
int n = nums.length;
Arrays.sort(nums);
List> ans = new ArrayList>();
// 枚举 a
for (int first = 0; first < n; first++) {
// 需要和上一次枚举的数不相同
if (first > 0 && nums[first] == nums[first - 1]) {
continue;
}
// c 对应的指针初始指向数组的最右端
int third = n - 1;
int target = -nums[first];
// 枚举 b
for (int second = first + 1; second < n; second++) {
// 需要和上一次枚举的数不相同
if (second > first + 1 && nums[second] == nums[second - 1]) {
continue;
}
// 需要保证 b 的指针在 c 的指针的左侧
while (second < third && nums[second] + nums[third] > target) {
third--;
}
// 如果指针重合,随着 b 后续的增加
// 就不会有满足 a+b+c=0 并且 b list = new ArrayList();
list.add(nums[first]);
list.add(nums[second]);
list.add(nums[third]);
ans.add(list);
}
}
}
return ans;
}
}
18. 四数之和
跟上一题思路类似,直接看题解吧:四数之和 - 四数之和 - 力扣(LeetCode)
下次可以把上面两题再写一遍思路!思路!