今天学完哈希表得题,感觉更能分清哈希表得使用场景。
1.力扣454
本题需要返回满足条件得数量,所以运用map集合,存储元素和出现得次数。先遍历两个数组并进行求和,并存进map中,在遍历后两个数组求和,判断需要得数是否在map中。
解题步骤:
- 先定义一个map集合,用来存储前两个数组得和,并记录这个和出现得次数
- 利用双层for循环,遍历并存储数组得和
- 在利用双层for循环遍历后两个数组,并判断需要得值是否出现在map结合中
- 若出现则res+=map.get(-mid);
代码如下:
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
HashMap<Integer,Integer> map1 = new HashMap();
int length = nums1.length;
for(int i=0;i<length;i++){
for(int j=0;j<length;j++){
int sum = nums1[i]+nums2[j];
if(map1.containsKey(sum)){
map1.put(sum,map1.get(sum)+1);
}else{
map1.put(sum,1);
}
}
}
int res = 0;
for(int i=0;i<length;i++){
for(int j=0;j<length;j++){
int mid = nums3[i]+nums4[j];
if(map1.containsKey(-mid)){
res +=map1.get(-mid);
}
}
}
return res;
}
2.力扣383
本题和力扣中有效的字母异位词类似,都是通过哈希法中得数组结构解决问题,只是最后判断得条件改变了。
解题步骤:
- 定义一个数组,用来记录第一个字符串中元素出现得次数
- 利用for循环讲对应索引处得值进行加1操作
- 利用for循环对第二个字符串进行遍历,并进行减一操作
- 因为第二个字符串得字串能构成第一个字符串就算满足条件,所以条件改变
代码如下:
public boolean canConstruct(String ransomNote, String magazine) {
int[] arr = new int[26];
for(int i=0;i<ransomNote.length();i++){
char ss = ransomNote.charAt(i);
arr[ss-'a']++;
}
for(int i=0;i<magazine.length();i++){
char ss = magazine.charAt(i);
arr[ss-'a']--;
}
for(int i=0;i<arr.length;i++){
//新得判断条件
if(arr[i]>0){
return false;
}
}
return true;
}
3.力扣15
本题较为复杂,利用动图来理解较为方便,本题利用双指针解决较为易于理解,利用for遍历数组,且定义left指针指向left+1,right指针指向nums.length-1处,让两指针向中间移动,重合则结束寻找,让i后移一位,继续进行判断。
解题步骤:
- 定义一个结果集合,存放返回值,且对数组进行排序操作,方便进行剪枝。
- 利用for循环遍历数组中元素,随后进行剪枝操作:nums[i]>target,若不满足就break
- 对元素i进行去重操作,nums[i]==nums[i-1],满足则continue
- 接下来初始化left指针和right指针,left=i+1;right=nums.length-1;
- 计算nums[i]+nums[left]+nums[right]得值,若>target则right--,小于target则left++;
- 接下来对left和right去重,若nums[left]==nums[left+1]则left++,若nums[right]==nums[right-1],则right--;
- 然后移动双指针。
代码如下:
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
for(int i=0;i<nums.length;i++){
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(right>left){
int sum=nums[i]+nums[left]+nums[right];
if(sum>0){
right--;
}else if(sum<0){
left++;
}else{
res.add(Arrays.asList(nums[i], nums[left], nums[right]));
while(right>left&&nums[left]==nums[left+1]){
left++;
}
while(right>left&&nums[right]==nums[right-1]){
right--;
}
left++;
right--;
}
}
}
return res;
}
4.力扣18
本题和上题一样,多了个剪枝和去重得过程,在三层for循环得基础上再加一个
for循环,就不进行讲解。
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> res = new ArrayList();
Arrays.sort(nums);
for(int k=0;k<nums.length;k++){
if(nums[k]>target&&nums[k]>0){
break;
}
if(k>0&&nums[k]==nums[k-1]){
continue;
}
for(int i=k+1;i<nums.length;i++){
if(i>k+1&&nums[i]==nums[i-1]){
continue;
}
int left = i + 1;
int right = nums.length - 1;
while (right > left) {
long sum = (long) nums[k] + nums[i] + nums[left] + nums[right];
if (sum > target) {
right--;
} else if (sum < target) {
left++;
} else {
res.add(Arrays.asList(nums[k], nums[i], nums[left], nums[right]));
while (right > left && nums[right] == nums[right - 1]) right--;
while (right > left && nums[left] == nums[left + 1]) left++;
left++;
right--;
}
}
}
}
return res;
}