[高频] 三. 基础算法和数据结构I

来源:互联网 发布:html矢量图标js下载 编辑:程序博客网 时间:2024/06/11 15:11

641. Missing Intervals:  点击打开链接

思路:两端点和一头一尾形成的区间+for循环扫描中间形成的区间

例如:{3,4,50,75},lower=0,upper=99,题目可以理解成在0-99的区间,挖去了3,4,50,95四个点,求剩下的区间

区间:lower->3-1

         75+1->upper

         中间{3,4,50,75}的扫描

注意:Integer.MAX_VALUE+1=Integer.MIN_VALUE

         例如:输入[2147483647],0,2147483647,

         因为2147483647是Integer.MAX_VALUE,而2147483647+1=-2147483648,是Integer.MIN_VALUE

         因此会输出["0->2147483646","-2147483648->2147483647"]

         而期望输出["0->2147483646"]   

         所以三种情况每一种都要加上if判断       

public class Solution {    /**     * @param nums a sorted integer array     * @param lower an integer     * @param upper an integer     * @return a list of its missing ranges     */    public List<String> findMissingRanges(int[] nums, int lower, int upper) {        List<String> result = new ArrayList<String>();        if(nums==null || nums.length==0){                                         //注意corner case            getRange(result,lower,upper);            return result;        }                if(nums[0]!=Integer.MIN_VALUE){            getRange(result,lower,nums[0]-1);        }                for(int i=1;i<nums.length;i++){            if(nums[i-1]!=Integer.MAX_VALUE && nums[i]!=Integer.MIN_VALUE){                getRange(result,nums[i-1]+1,nums[i]-1);            }        }                if(nums[nums.length-1]!=Integer.MAX_VALUE){            getRange(result,nums[nums.length-1]+1,upper);        }        return result;    }        private void getRange(List<String> result,int start,int end){        if(start>end){            return;        }else if(start==end){            result.add(""+start);            return;        }else{            result.add(""+start+"->"+end);        }    }}

156. Merge Intervals: 点击打开链接

思路:区间start端点从小到大排序,从左到右扫一遍

         能合并,就合并

         不能合并,直接下一个

[                     [  [1, 3],               [1, 6],  [2, 6],      =>       [8, 10],  [8, 10],              [15, 18]  [15, 18]            ]]
分析:开始last=null,i=[1,3],res加入[1,3],并且last=[1,3];

         i=[2,6],和last=[1,3]可以合并,更新res里[1,3]的end值使称为[1,6];

         i=[8,10],res加入[8,10],并且last=[8,10];

注意:时间复杂度O(nlogn)

          扫描一次n,排序nlogn

/** * Definition of Interval: * public class Interval { *     int start, end; *     Interval(int start, int end) { *         this.start = start; *         this.end = end; *     } */class Solution {    /**     * @param intervals, a collection of intervals     * @return: A new sorted interval list.     */    public List<Interval> merge(List<Interval> intervals) {        ArrayList<Interval> res = new ArrayList<>();                  Collections.sort(intervals,myComparator);        Interval last=null;        for(Interval i:intervals) {              if(last==null || last.end<i.start){                  res.add(i);                  last=i;            } else{                last.end = Math.max(last.end, i.end);                         //更新已经在result list里的元素的end                   }        }          return res;    }    private Comparator<Interval> myComparator = new Comparator<Interval>() {          public int compare(Interval i, Interval j) {              return i.start - j.start;          }      };}

30.  Insert Intervals: 点击打开链接

Insert [2, 5] into [[1,2], [5,9]], we get [[1,9]].

Insert [3, 4] into [[1,2], [5,9]], we get [[1,2], [3,4], [5,9]]

/** * Definition for an interval. * public class Interval { *     int start; *     int end; *     Interval() { start = 0; end = 0; } *     Interval(int s, int e) { start = s; end = e; } * } */public class Solution {    public List<Interval> insert(List<Interval> intervals, Interval newInterval) {      //方法一        List<Interval> result=new ArrayList<>();        int index=0;        while(index<intervals.size() && intervals.get(index).start<newInterval.start){  //先插入到正确位置            index++;                                                                    //使整个给定list还是按start升序        }        intervals.add(index,newInterval);                Interval last=null;                                                             //然后是merge Intervals        for(Interval i:intervals){            if(last==null || last.end<i.start){                result.add(i);                last=i;            }else if(last.end>=i.start){                last.end=Math.max(i.end,last.end);            }        }        return result;      }}

/** * Definition of Interval: * public classs Interval { *     int start, end; *     Interval(int start, int end) { *         this.start = start; *         this.end = end; *     } */class Solution {    /**     * Insert newInterval into intervals.     * @param intervals: Sorted interval list.     * @param newInterval: A new interval.     * @return: A new sorted interval list.     */    public ArrayList<Interval> insert(ArrayList<Interval> intervals, Interval newInterval) {    //方法二        ArrayList<Interval> result = new ArrayList<Interval>();                     for(Interval i: intervals){            if(i.end < newInterval.start){                              //insert[3,4]与[1,2]比较                result.add(i);            }else if(i.start > newInterval.end){                        //insert[3,4]与[5,9]比较                 result.add(newInterval);                newInterval = i;                    }else{                                                      //其他情况就是start取小,end取大                int newStart = Math.min(i.start, newInterval.start);                int newEnd = Math.max(newInterval.end, i.end);                newInterval = new Interval(newStart, newEnd);           //并且不断更新newInterval            }         }         result.add(newInterval);          return result;    }}

646. First Position Unique Character:点击打开链接

public class Solution {    /**     * @param s a string     * @return it's index     */    public int firstUniqChar(String s) {        if(s==null || s.length()==0){            return -1;        }                Map<Character,Integer> map=new HashMap<>();        for(int i=0;i<s.length();i++){            char ch=s.charAt(i);            if(!map.containsKey(ch)){                map.put(ch,1);            }else{                map.put(ch,map.get(ch)+1);            }        }                for(int i=0;i<s.length();i++){                       //这里可以直接返回i            if(map.get(s.charAt(i))==1){                return i;            }        }        return -1;    }}

423. Valid Parentheses:点击打开链接

思路:如果"([{}])",遇到前三个,stack里装了)]},当到了},stack该push},一样就继续遍历,不一样就返回false

public class Solution {    /**     * @param s A string     * @return whether the string is a valid parentheses     */    public boolean isValidParentheses(String s) {        if(s==null || s.length()==0){            return false;        }        Stack<Character> stack=new Stack<>();        for(int i=0;i<s.length();i++){            char c=s.charAt(i);            if(c=='('){                stack.push(')');            }else if(c=='{'){                stack.push('}');            }else if(c=='['){                stack.push(']');            }else if(stack.isEmpty()||stack.pop()!=c){     //如果"()]",当遇到]stack该执行pop,但没有东西在stack里                    return false;                              //还有就是如果pop出的不一样,也返回false            }        }        return stack.isEmpty();                            //如果")()",如果一开始就该pop,stack此时为空,还是要返回false    }}

647. Substring Anagrams:点击打开链接

思路:统计好p字符串每个字符出现的次数

         sliding window从左往右扫一遍,每次判断p.length区间段的字符是不是能还原成p字符串

        都是减少一个左边元素,同时增加一个右边元素,

public class Solution {    /**     * @param s a string     * @param p a non-empty string     * @return a list of index     */    public List<Integer> findAnagrams(String s, String p) {        List<Integer> result=new ArrayList<>();        int[] temp=new int[26];        for(Character i:p.toCharArray()){            temp[i-'a']++;        }                int start=0,end=0;        int matched=0;        while(end<s.length()){            if(temp[s.charAt(end)-'a'] >=1){            //开始已经统计过p字符串,因此只要分p里有的,这里的个数至少为1                matched++;                              //每一个符合条件的都matched++            }            temp[s.charAt(end)-'a']--;                  //已经统计到matched上的,就要从自身字符的总个数上减掉            end++;                                      //或者是不matched的,也要从自身字符的总个数上减掉,会成为-1或更小负数                        if(matched==p.length()){                    //没达到p.length不会添加                result.add(start);            }                        if(end-start==p.length()){                  //一开始从索引0往后遍历end,没达到p.length(),这里不执行                if(temp[s.charAt(start)-'a'] >=0){      //当达到p.length()才进行sliding window                    matched--;                          //如果遍历到的字符自身总个数>=0,说明一开始end遍历的时候属于p里的字符                }                                       //减少一个左边的字符                temp[s.charAt(start)-'a']++;            //但是要补回来左边减少的字符,以便接下来end判断右面是不是有这个字符                start++;                                //如果左边这个字符不是p里有的,也要统计上,因为之前end遍历的时候已经成负数            }                                           //因此怎么加也不是在下一次end判断的时候自身字符总数>=1        }        return result;     }}

648. Word Abbreviation Set: 点击打开链接

方法一

思路:单词在字典中出现次数等于对应缩写在字典中的次数,unique

         单词在字典中出现次数等于对应缩写在字典中的次数,not unique

public class ValidWordAbbr {    // @param dictionary a list of word    Map<String,Integer> mapA=new HashMap<>();    Map<String,Integer> mapW=new HashMap<>();    public ValidWordAbbr(String[] dictionary) {        for(String word:dictionary){            String abbr=getAbbr(word);            if(!mapA.containsKey(abbr)){                mapA.put(abbr,1);            }else{                mapA.put(abbr,mapA.get(abbr)+1);            }        }        for(String word:dictionary){            if(!mapW.containsKey(word)){                mapW.put(word,1);            }else{                mapW.put(word,mapW.get(word)+1);            }        }    }    /**     * @param word a string     * @return true if its abbreviation is unique or false     */    public boolean isUnique(String word) {        return mapA.get(getAbbr(word))==mapW.get(word);    }        private String getAbbr(String word){        if(word.length()<=2){            return word;        }        return ""+word.charAt(0)+String.valueOf(word.length()-2)+word.charAt(word.length()-1);    }}/** * Your ValidWordAbbr object will be instantiated and called as such: * ValidWordAbbr obj = new ValidWordAbbr(dictionary); * boolean param = obj.isUnique(word); */
方法二

思路:Map<缩写词,第一个遍历的单词>,当map里已经有这个缩写词,就要看下对应值的是不是同一个单词,如果不是,说明不是唯一

注意:在判断是不是唯一的时候,如果新的单词不是字典里已经有的,说明也是唯一

public class ValidWordAbbr {    // @param dictionary a list of word    Map<String,String> map;    public ValidWordAbbr(String[] dictionary) {        map=new HashMap<>();        for(String word:dictionary){            String abbr=getAbbr(word);            if(!map.containsKey(abbr)){                map.put(abbr,word);            }else{                                                //如果map里有key有abbr                if(!map.get(abbr).equals(word)){                  //判断key对应的值映射不是当前word,而是之前已经有的word                    map.put(abbr,"-1");                           //说明不是唯一,用"-1"来记                }            }        }    }    /**     * @param word a string     * @return true if its abbreviation is unique or false     */    public boolean isUnique(String word) {        String abbr=getAbbr(word);                                //返回true的两种情况        if(!map.containsKey(abbr)){                               //给出word的abbr不在字典里            return true;        }        return map.get(abbr).equals(word)?true:false;             //map的值映射是word,因为如果不是唯一值映射就是"-1"    }        private String getAbbr(String word){        if(word.length()<=2){            return word;        }        return ""+word.charAt(0)+String.valueOf(word.length()-2)+word.charAt(word.length()-1);    }}/** * Your ValidWordAbbr object will be instantiated and called as such: * ValidWordAbbr obj = new ValidWordAbbr(dictionary); * boolean param = obj.isUnique(word); */

124. Longest Consecutive Sequence: 点击打开链接

例如:{100,4,200,1,3,2},对于数组里的每一个元素e,都看e-1和e+1是否在set里,如果在,就一直往下找,最后算出长度

         为了能直接在set里判断,一开始就要把数组里所有元素放在set里

注意:因为只需要扫面一遍数组里的元素,因此O(n)

public class Solution {    /**     * @param nums: A list of integers     * @return an integer     */    public int longestConsecutive(int[] num) {        if(num == null || num.length == 0){            return 0;        }                Set<Integer> set=new HashSet<>();        for(Integer e:num){            set.add(e);        }                int result=0;        for(Integer e:num){            int pre=e-1;            int next=e+1;            while(set.contains(pre)){                set.remove(pre);                pre--;            }            while(set.contains(next)){                set.remove(next);                next++;            }            result=Math.max(result,next-pre-1);        }                return result;    }}

526. Load Balancer:点击打开链接

思路:O(1)时间内插入,删除,只能hash

         但是还要getRandom(),就要数组或者list来做

public class LoadBalancer {        // This is consistent hashing solution in most companies. However it exceeds the memory limit    List<Integer> list;    Map<Integer,Integer> map;        public LoadBalancer() {        list=new ArrayList<>();        map=new HashMap<>();    }    // @param server_id add a new server to the cluster     // @return void    public void add(int server_id) {        list.add(server_id);                                            //list加入这个元素,其实每次加入的元素都是在list末尾        map.put(server_id,list.size()-1);                               //map里放要添加的server_id和它在list里的位置    }    // @param server_id server_id remove a bad server from the cluster    // @return void    public void remove(int server_id) {        if(map.containsKey(server_id)){                  int index=map.get(server_id);                               //拿到要删除的server_id在map里的位置            list.set(index,list.get(list.size()-1));                    //list把该位置更新成最后一个元素            map.put(list.get(list.size()-1),index);                     //map里也把该位置更新成list的最后一个元素                        list.remove(list.size()-1);                                 //删除list最后一个元素            map.remove(server_id);                                      //map删除要删除的server_id        }    }    // @return pick a server in the cluster randomly with equal probability    public int pick() {        Random r = new Random();        return list.get(r.nextInt(list.size()));                        //r.nextInt(n):表示从0到n(不包括n)随机取数           } }