哈希-算法题笔记

两数之和

给出一个整型数组 numbers 和一个目标值 target,请在数组中找出两个加起来等于目标值的数的下标,返回的下标按升序排列。
(注:返回的数组下标从1开始算起,保证target一定可以由数组里面2个数字相加得到)

要求:空间复杂度 O(n)O(n),时间复杂度 O(nlogn)O(nlogn)
思路:计算target-numbers[i]的差是否包含在hashMap中,如果在就找到了这两个数,如果不在,就把当前的(numbers[i],i+1)存在hashMap中,继续遍历数组

import java.util.*;
public class Solution {
    /**
     * 
     * @param numbers int整型一维数组 
     * @param target int整型 
     * @return int整型一维数组
     */
    public int[] twoSum (int[] numbers, int target) {
        // write code here
        HashMap<Integer,Integer> map=new HashMap<>();
        int[] ans=new int[2];
        for(int i=0;i<numbers.length;i++){
            int tmp=target-numbers[i];
            if(map.containsKey(tmp)){
                ans[0]=Math.min(i+1,map.get(tmp));
                ans[1]=Math.max(i+1,map.get(tmp));
            }else{
                map.put(numbers[i],i+1);
            }
        }
        return ans;
    }
}

数组中只出现一次的两个数

一个整型数组里除了两个数字只出现一次,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
提示:输出时按非降序排列
思路:

  • 遍历数组,如果HashMap中包含当前num[i],就把(num[i],2)加入HashMap,如果HashMap中不包含当前num[i]就把(num[i],1)加入HashMap
  • 然后判断当前的num[i]的value是否为1,如果为1,就把当前num[i]加入HashSet中,否则就从HashSet中移除当前的num[i]
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param array int整型一维数组 
     * @return int整型一维数组
     */
    public int[] FindNumsAppearOnce (int[] array) {
        // write code here
        HashMap<Integer,Integer> map=new HashMap<>();
        HashSet<Integer> set =new HashSet<>();
        for(int i=0;i<array.length;i++){
            if(map.containsKey(array[i])){
                map.put(array[i],map.get(array[i])+1);
            }else{
                map.put(array[i],1);
            }
            if(map.get(array[i])==1){
                set.add(array[i]);
            }else{
                set.remove(array[i]);
            }
        }
        int[] ans=new int[2];
        int i=0;
        for(Integer val:set){
            ans[i++]=val;
        }
        return ans;
    }
}

三数之和

给出一个有n个元素的数组S,S中是否有元素a,b,c满足a+b+c=0?找出数组S中所有满足条件的三元组。
注意:
三元组(a、b、c)中的元素可以按任意顺序排列。
解集中不能包含重复的三元组。
思路:

  • 排序
  • 三个指针,k,i,j 固定k,i=k+1,j=num.length-1
  • 指针i,j从两边往中间遍历,如果满足条件num[i]+num[j]+num[k]=0,就把这三个数加到结果集中
  • 同时要避免结果集中三元组重复
import java.util.*;
public class Solution {
    public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
        ArrayList<ArrayList<Integer>> res=new ArrayList<>();
        
        Arrays.sort(num);
        int k=0,i=k+1,j=num.length-1;
        while(k<num.length){
            i=k+1;
            j=num.length-1;
            while(i<j){
                int tmp=num[k]+num[i]+num[j];
                if(tmp==0){//如果找到三数之和等于0
                    ArrayList<Integer> list=new ArrayList<>();
                    list.add(num[k]);
                    list.add(num[i]);
                    list.add(num[j]);
                    res.add(list);
                    //为避免重复的三元组
                    while(i<j&&num[i]==num[i+1]){
                        i++;
                    }
                    i++;
                    while(i<j&&num[j]==num[j-1]){
                        j--;
                    }
                    j--;
                }else if(tmp<0){
                    i++;
                }else{
                    j--;
                }
            }
            while(k<num.length-1&&num[k]==num[k+1]){
                k++;
            }
            k++;
        }
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值