每日算法之借助标准库解题(I)

解一些算法题时,我们可以借助语言标准库里的方法或数据结构,它能够有效的帮助我们。比如下面的两道LeetCode上的题目,这两道题很类似,都是求交集问题,但又有很大的不同。

Q1:给定两个数组,编写一个函数来计算它们的交集。

说明:输出结果中的每个元素一定是唯一的。
我们可以不考虑输出结果的顺序。

例如输入: nums1 = [1,2,2,1], nums2 = [2,2]

输出: [2]

Q2:给定两个数组,编写一个函数来计算它们的交集。

说明:
输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。我们可以不考虑输出结果的顺序。

例如:输入: nums1 = [1,2,2,1], nums2 = [2,2]

输出: [2,2]

一、分析一下题目

我们发现题目可以说是完全一样的,都是求两个数组的交集,只不过一个是不含重复元素,另一个需要把所有的交集的数全找出来,包含重复元素。

我们或许可以想到的是如果这是两个有序数组,就好办了,只需要为两个数组分别准备一个指针,并同时比较两个数组,移动指针,根据相对应的题目要求存储结果。那既然这不是有序数组,我们也可以用较快的排序算法或者使用语言标准库里的排序方法给它排好序。然后再解答。

比如对上面第二题的解答方法

class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        int i = 0, j = 0;
        List<Integer> intersection = new ArrayList<Integer>();
        while (i < nums1.length && j < nums2.length) {
            if (nums1[i] < nums2[j]) {
                i++;
            }
            else if (nums1[i] > nums2[j]) {
                j++;
            }
            else {
                intersection.add(nums1[i]);
                i++;
                j++;
            }
        }
        int[] result = new int[intersection.size()];
        for (int k = 0; k < intersection.size(); k++) {
            result[k] = intersection.get(k);
        }
        return result;
    }

二、这种方法很容易理解,效率也比较高,但是这不是我这里要说的重点。

这两道题我们透过本质来看的话,第一题可以看成在一个数组里找是否含有某个元素,第二题可以看出这个元素在这个数组出现了几次。

所以第一题其实可以用我们的set容器,set容器有个特点,不存储重复的元素,所以当我们遍历一遍数组把它放入set容器中时,它的重复元素就自动被筛掉了。之后我们就可以对第二个数组里的元素在第一个数组中进行查找就好了。找到的元素就是我们的最后的解。

话不多说,上一坛代码

public class InserSection {
     public int[] intersection(int[] nums1, int[] nums2) {
         //1.定义一个set容器
        Set<Integer> record=new HashSet();
        List<Integer> res=new ArrayList<>();          //保存交集的元素
        
        //2.数组1放入到set容器中
         for(int i=0;i<nums1.length;i++)
             record.add(nums1[i]);
        
         //3.查找数组2在数组1存在的元素,放入list集合中
         int j=0;
         for(int i=0;i<nums2.length;i++){
              if (record.contains(nums2[i])) {
                res.add(nums2[i]);
                record.remove(nums2[i]);
            }     
         }
            
         //4.由于结果需要输出一个数组,定义一个结果数组保存结果
         int resultArray[]=new int[res.size()];  
         for(int i=0;i<res.size();i++)
           resultArray[i]=res.get(i);
         return resultArray;
     }

三、那么对于第二题很明显就不能用set容器了,因为我们需要的结果包含重复的元素。就需要另外一种容器了,是什么呢?

因为我们需要对某个元素进行统计出现的次数。没错,所以我们需要借助map容器,这个容器的特点就是键值对<key,value>的方式存储元素。我们让它的键key为元素值,值value就是这个键对应元素出现的次数。

话不多说,再来一坛代码

     public int[] intersect(int[] nums1, int[] nums2) {
         //1.定义一个Map<key,value>,key表示数组的元素,value表示该元素出现的次数
            Map<Integer,Integer> record=new HashMap<>(); 
            List<Integer> res=new ArrayList<>();          //保存交集的元素
            
            //2.初始化map集合元素
            for (int i = 0; i < nums1.length; i++) {
                //值作为键,次数作为值
                Integer prev=record.get(nums1[i]);
                //如果键为i的值为空,那么次数为1,否则累加
                record.put(nums1[i],prev==null?1:prev+1);
            }
            
            //3.遍历第二个数组
            for (int i = 0; i < nums2.length; i++) {
                Integer prev=record.get(nums2[i]);  //获取第i个元素出现的次数
                if(prev!=null){
                    res.add(nums2[i]);              //将元素放入到结果集合res中
                    if (prev==1)                    //并当元素只剩余一次的时候移除容器map中
                        record.remove(nums2[i]);
                    else 
                        record.put(nums2[i],prev-1);  //将元素的出现的次数减1
                }
            }
            
            
            //4.将结果从res集合转移到结果数组
            int[] resultArray=new int[res.size()];
            for(int i=0;i<res.size();i++){
                resultArray[i]=res.get(i);
            }
            
          return resultArray;  
        }

四、小结一下

虽然我们上面的解法效率可能不如其他的解法好,但是我想说的是,我们可以当我们对语言标准库里的方法和一些数据结构的特点比较了解和熟悉,它会对我们解答一些算法题有很大的帮助。可能在这两道题目比较简单,所以不是很明显的突出它的优点。不过在后面我还会继续分享关于这部分的内容。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容

  • 本文内容为练习LeetCode题目时的解题思路和不同算法的记录,实现语言为C++,代码保存在Github,均已在L...
    SK木眠阅读 948评论 0 0
  • 王明日阅读 733评论 0 0
  • 很启发自己的两段话: 一个画家曾做过一个试验,请别人来为他的话找出缺点,然后他的话被贬的一无是处。之后,他又请别人...
    88singlelady阅读 579评论 0 2
  • 马路边的灯光晕出些昏黄 我又想起过去 和你在一起的模样 你笑着 在对未来的幻想中徜徉 我说你傻得天真 小看现实的力...
    唐人街的风阅读 267评论 0 4