Day07的题目
LeetCode454 四数相加:给四个长度相同的数组,找出每个数组中取一个数结果为0的组合个数
核心思想:将四个数组分成两组,使用HashMap存入前两个数组的两个元素的所有和,重复的就要多次计算,value存这个结果出现的次数。然后查看后两个数组的和的负数是否在map里面,在的话返回值加上 这个结果出现的次数。
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
HashMap<Integer,Integer> map = new HashMap<>();
for(int num1 : nums1){
for(int num2: nums2){
int sum = num1+num2;
// getOrDefault表示没有这个key就返回后面的值,这里是0。
// 这里实现存sum,如果已经有了就value加一
map.put(sum,map.getOrDefault(sum,0)+1);
}
}
int res = 0 ;
for(int num3 : nums3){
for(int num4 : nums4){
// 如果map中包含有(num1+num2)= -num3-num4 ,那么就存在num1+num2+num3+num4=0,那么结果就加上num1+num2的个数。
res+= map.getOrDefault(0-num3-num4,0);
}
}
return res;
}
}
LeetCode 赎金信:实际上就是给两个字符串,判断第一个字符串能不能由第二个字符串内部的字符构成(每次字符只能用一次)
核心思想:这道题比较简单,只要把第二个字符串的所有字符计数,然后把第一个字符串中用到的字符减一,如果没有出现结果是负数的情况,那么就够用。
public boolean canConstruct(String ransomNote, String magazine) {
// 使用数组比HashMap快
int[] record = new int[26];
for(int i = 0 ; i < magazine.length() ; i ++){
// 记录magazine中的字符
record[magazine.charAt(i) - 'a'] ++;
}
for(int i = 0 ; i < ransomNote.length() ; i ++){
// 如果减一之前已经为0 那么直接返回false
if(record[ransomNote.charAt(i) - 'a' ]== 0) return false;
record[ransomNote.charAt(i) - 'a'] --;
}
return true;
}
LeetCode15 三数之和:从数组中得到三个数和为0的序列,需要去重
核心思想:1.使用数组存储两个数的和,然后使用hashmap从数组中取出target-sum的值,这样能达到效果,但是因为需要去重,这样得到的结果边界条件难控制并且难以去重。推荐使用双指针的方法来做。下面的代码是双指针的模式。主要注意去重部分:对-2,-2,1,1,1这样的数组,第二个-2的结果一定包含在第一个-2中,所以直接跳过,防止重复。对于-2,1,1的结果,会出现多个,所以在找到一组结果的时候,把左右指针都移动到下一个不相同的元素上。
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res= new ArrayList<>();
// 排序
Arrays.sort(nums);
for(int i = 0 ; i < nums.length; i ++){
// 如果起始的值就大于0,那么三个数的和不可能是0,直接返回
if(nums[i] > 0 ) return res;
// 如果当前的起始值和上一个数相同,那么就直接跳过,因为同样的起始值,得到的结果一定是包含在上一个的结果中,这里进行去重
if(i > 0 && nums[i] == nums[i-1]) continue;
// 左指针指向下一个元素
int left = i+1;
// 右指针指向末尾元素
int right = nums.length-1;
// 左右指针遍历
while(left < right){
// 如果起始值,左指针右指针的元素和大于0,那么将右指针左移
if(nums[i] + nums[left] + nums[right] > 0){
right --;
// 小于0 右移
}else if ( nums[i] + nums[left] + nums[right] < 0){
left ++;
}else{
// 等于0 的时候,把这三个值加入到返回值
List<Integer> list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[left]);
list.add(nums[right]);
res.add(list);
// 这里需要使得左右指针都指向下一个不相同的元素,否则对于 -2 1 1 1 1 1 1,会出现很多组 -2 1 1 这样的重复数据
while(left < right && nums[left + 1] == nums[left] ){
left ++;
}
while(left < right && nums[right-1] == nums[right]){
right --;
}
// 移动到第一个不相同的元素
right --;
left ++;
}
}
}
return res;
}
}
LeetCode18 四数之和:与上题相同,只不过是四个数字,结果不为0而是target
核心思想:使用双指针,与三数之和类似,但是去重条件略微不同。
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
// 结果集
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
// nums[i]为第一个数
for(int i = 0 ; i < nums.length ; i ++){
// 如果第一个就大于目标值,而且大于等于0,那么之后相加必不可能等于target,因为已经排序了
if(nums[i] > target && nums[i] >= 0) return res;
// 同样跳过相同的初始值
if(i > 0 && nums[i] == nums[i-1]) continue;
for(int k = i + 1 ; k < nums.length ; k ++){
// nums[k]是第二个数
// 如果这两个数之和都大于target,并且target大于0,那么就直接下一层i循环
if(nums[k]+nums[i] > target && target >=0) break;
// 同样跳过第二个相同的值
if(k > i+1 && nums[k] == nums[k-1]) continue;
int left = k+1;
int right = nums.length-1;
while(left < right){
if(nums[i] + nums[k] + nums[left] + nums[right] > target){
right--;
}else if(nums[i] + nums[k] + nums[left] + nums[right] < target){
left++;
}else{
List<Integer> list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[k]);
list.add(nums[left]);
list.add(nums[right]);
res.add(list);
while(left<right && nums[left+1] == nums[left]){
left ++;
}
while(right > left && nums[right - 1] == nums[right ]){
right--;
}
left ++;
right --;
}
}
}
}
return res;
}
}
6054



被折叠的 条评论
为什么被折叠?



