454.四数相加II
思路:将4层for循环转换成两次 两层for循环,前两层使用哈希map key存两数之和 value存出现当前key的次数,后两层判断key是否存在,value为结果次数
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
int res=0;
//创建map集合key值放nums1和nums2的和,value存对应的次数
HashMap<Integer, Integer> map = new HashMap<>();
for(int i:nums1){
for(int j:nums2){//遍历nums1和nums2的值
if(map.containsKey(i+j)){//如果这个和存在key值存在
map.put(i+j,map.get(i+j)+1);//就在这个key原来的基础上value+1
}else{//如果不存在说明这个是和是第一次出现,所以value值为1
map.put(i+j,1);
}
}
}
for(int i:nums3){
for(int j:nums4){//统计nums3和nums4的值
if(map.containsKey(0-i-j)){//存在nums3、nums4的和对应想法的key值说明这四个数组和为0
res += map.get(0-i-j);//统计这个key1的次数就是对应和为0的个数
}
}
}
return res;
}
}
383. 赎金信
思路:字典法,构建26位(由小写字母构成),通过-‘a'获取数组下标使其+1,最后看数组结果是否存在-1,没有成功有失败
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
// shortcut
if (ransomNote.length() > magazine.length()) {
return false;
}
// 定义一个哈希映射数组
int[] record = new int[26];
// 遍历
for(char c : magazine.toCharArray()){
record[c - 'a'] += 1;
}
for(char c : ransomNote.toCharArray()){
record[c - 'a'] -= 1;
}
// 如果数组中存在负数,说明ransomNote字符串总存在magazine中没有的字符
for(int i : record){
if(i < 0){
return false;
}
}
return true;
}
}
15. 三数之和
思路:先排序,
去重(为什么 是nums[i] == nums[i-1] 而不是nums[i] == nums[i+1],这样会少结果例如 {-1,-1,2}),
使用双指针(left right) 大致 i left ...... right ,如果和小于0,left往右走,和大于0,right往左走获取结果后,对left,与right去重,left去重 left++,right去重right--
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
//先将数组元素排序
Arrays.sort(nums);
// 找出a + b + c = 0
// a = nums[i], b = nums[left], c = nums[right]
for(int i =0;i < nums.length;i++){
// 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了
if(nums[i] > 0){
return result;
}
//a去重 为什么 是nums[i] == nums[i-1] 而不是nums[i] == nums[i+1]
//这样会少结果例如 {-1,-1,2}
if(i > 0 && nums[i] == nums[i-1]){
//跳过当前元素
continue;
}
int left = i + 1;
int right = nums.length - 1;
while(right > left){
if(nums[i] + nums[left] + nums[right] > 0){
right--;
}else if(nums[i] + nums[left] + nums[right] < 0){
left++;
}else{
result.add(Arrays.asList(nums[i],nums[left],nums[right]));
// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重
while(right > left && nums[right] == nums[right -1]) right--;
while(right > left && nums[left] == nums[left +1]) left++;
//left right 双指针往里面缩
right--;
left++;
}
}
}
return result;
}
}
18. 四数之和 (相较于三数之和 外面多套了一层for循环,多一次去重)
因此五数,六数之和同理
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(nums);
for(int k=0; k < nums.length; k++){
//一级剪枝
if(nums[k] > target && nums[k] >= 0){
break;
}
//对k去重
if(k > 0 && nums[k] == nums[k-1]){
continue;
}
for(int i = k + 1; i < nums.length; i++){
//二级剪枝
if(nums[k] + nums[i] > target && nums[k] + nums[i] >= 0){
break;
}
//对i去重
if(i > k + 1 && nums[i] == nums[i-1]){
continue;
}
int left = i+1;
int right = nums.length - 1;
while(right > left){
int sum = nums[k] + nums[i] + nums[left] + nums[right];
if(sum > target){
right--;
}else if(sum < target){
left++;
}else{
result.add(Arrays.asList(nums[k],nums[i],nums[left],nums[right]));
//left,right去重
while(right > left && nums[right] == nums[right-1]) right--;
while(right > left && nums[left] == nums[left+1]) left++;
right--;
left++;
}
}
}
}
return result;
}
}