454.四数相加II
题目链接:Loading Question... - 力扣(LeetCode)
该题目的关键点并不需要记录四个满足条件数的下标,也就是说只记录满足条件的次数即可。通过HashMap即可降低暴力求法的时间复杂度,使用Map去记录前两个数组中可能出现的数以及出现该组合的次数。再通过两层循环的方式计算后两个数组可能出现的和并去Map中查看是否有符合条件的相反数。该方法的时间复杂度降低到了O(n^2)
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
int ans = 0;
HashMap<Integer,Integer> record = new HashMap<>();
for(int i : nums1){
for(int j : nums2){
int sum = i + j;
if(!record.containsKey(sum)){
record.put(sum,1);
}
else{
record.put(sum,record.get(sum) + 1);
}
}
}
for(int i : nums3){
for(int j : nums4){
int sum = i + j;
if(record.containsKey(0 - sum)){
ans += record.get(0 - sum);
}
}
}
return ans;
}
}
383.赎金信
先统计报纸中的词频,再去循环赎金信一个一个删,如果到某个词的时候发现词频已经为0了,就可以确定,报纸不足以改编出赎金信,代码实现如下:
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
char[] mag = magazine.toCharArray();
char[] ran = ransomNote.toCharArray();
HashMap<Character,Integer> record = new HashMap<>();
for(char c : mag){
if(!record.containsKey(c)){
record.put(c,1);
}
else{
record.put(c,record.get(c) + 1);
}
}
for(char c : ran){
if(!record.containsKey(c) || record.get(c) == 0) return false;
else{
record.put(c,record.get(c) - 1);
}
}
return true;
}
}
15.三数之和
因为今天是Map和Set的专题,所以这里不采用双指针的方式去写,采用HashSet的方式去写,其实两种方法的本质是一样的。代码如下:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(nums);
for(int i = 0; i < nums.length; i++){
if(nums[i] > 0){ // 第一个数的去重
return result;
}
if(i > 0 && nums[i] == nums[i - 1]){
continue;
}
Set<Integer> record = new HashSet<>();
for(int j = i + 1; j < nums.length; j++){
if(j > i + 2 && // 第三个数的去重
nums[j] == nums[j - 1] &&
nums[j] == nums[j - 2]){
continue;
}
int sum = 0 - (nums[i] + nums[j]);
// 这里的nums[j]其实代表的是第三个数,没找到伴的第二个数存在了set当中。
if(record.contains(sum)){
result.add(Arrays.asList(nums[i],nums[j],sum));
record.remove(sum); // 删除第二个数
}else{
record.add(nums[j]);
}
}
}
return result;
}
}
18.四数之和
这个题和上面的三数之和,思路是一样的,只不过最外层又多了一层循环。这种写法多少有点稀里糊涂对了的感觉= =理的不是很清晰。先记录一下吧
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(nums);
for(int i = 0; i < nums.length; i++){ // 外面的两层普通循环只需要进行相邻元素去重即可。
if(nums[i] > 0 && nums[i] > target){
return result;
}
if(i > 0 && nums[i] == nums[i - 1]){
continue;
}
for(int j = i + 1; j < nums.length; j++){
if(j > i + 1 && nums[j] == nums[j - 1]){
continue;
}
Set<Long> record = new HashSet<>();
for(int k = j + 1; k < nums.length; k++){ // 最内层的循环需要特殊处理考虑一下,
if(k > j + 3 && nums[k] == nums[k - 1] && nums[k] == nums[k-2] && nums[k] == nums[k-3]){
continue;
}
long sum = (long)target - ((long)nums[i] + nums[j] + nums[k]); // 这里nums[i]前面的long类型转换是为了避免三个数相加溢出
// 这里的nums[j]其实代表的是第三个数,没找到伴的第二个数存在了set当中。
if(record.contains(sum)){
result.add(Arrays.asList(nums[i],nums[j],nums[k],(int)sum));
record.remove(sum); // 删除第二个数
}else{
record.add((long)nums[k]);
}
}
}
}
return result;
}
}