[高频] 三. 基础算法和数据结构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端点从小到大排序,从左到右扫一遍
能合并,就合并
不能合并,直接下一个
分析:开始last=null,i=[1,3],res加入[1,3],并且last=[1,3];[ [ [1,
3
], [1, 6], [
2
, 6], => [8, 10], [8, 10], [15, 18] [15, 18] ]]
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)随机取数 } }
- [高频] 三. 基础算法和数据结构I
- [高频] 四.基础算法和数据结构II
- 数据结构和算法基础
- 常用数据结构和算法基础
- Java基础数据结构和算法
- 基础数据结构和算法概念
- 算法与数据结构基础(三)插入排序、选择排序和冒泡排序的区别
- 数据结构基础 排序算法(三)算法的稳定性
- 数据结构和算法总结(三)
- 浅谈算法和数据结构: 三 合并排序
- 浅谈算法和数据结构: 三 合并排序
- python进阶(数据结构和算法[三])
- 浅谈算法和数据结构: 三 合并排序
- 浅谈算法和数据结构: 三 合并排序
- 浅谈算法和数据结构: 三 合并排序
- 浅谈算法和数据结构: 三 合并排序
- 浅谈算法和数据结构: 三 合并排序
- 数据结构与算法(三) 栈和队列
- [BZOJ1066][SCOI2007]蜥蜴-网络流
- 【JavaScript的标识符】
- 第一篇
- 结构体
- Android使用原生动画工具类实现平移动画
- [高频] 三. 基础算法和数据结构I
- Android反编译记录
- CentOS 7.2设置SSH公钥登录
- 重头开始设计一个系统吧-数据表设计
- UVA
- 字符串和BF算法的实现
- Hadoop参考命令大全
- ROM
- コンピュターグラフィックス COMPUTER GRAPHICS[FOR CG ENGINEERS]-Chapter6-0708